0
我正在使用EaselJS開發HTML5 Canvas遊戲,並且在更改我的代碼後發現了一個問題。觸摸事件在這個變化之前就已經開始工作了,但它不再工作了,我不記得我已經改變了什麼,但它與stagemousedown
/stagemouseup
事件無關。我只在iOS 7上測試過遊戲。觸摸事件無法使用EaselJS
有人可以幫助我嗎?
正如我所說的,我不知道問題出在哪裏然後我會在這裏把整個代碼,而不是相關的部分只有(> 400線)的。我強烈建議您看看[小提琴] [1]。
這裏是我的代碼:
function init() {
var objectsCollideAt = {
it: [], // If it is collideable, it'll be in this array.
top: [],
left: [],
right: [],
bottom: []
},
key = {
up: false, // W, arrow up or spacebar
left: false, // A or arrow left
right: false, // D or arrow right
down: false, // S or arrow down
holdingUp: false
},
mouse = {
x: 0,
y: 0
},
touch = {
tollerance: 50 // Object "margins" when using touch or mouse
},
collisionSystem = {
/* This variable is responsible for deactivating the
* edge-to-edge collision detection forEach when a
* side-to-side collision happened, to get better
* performance. Can cause extremely rare bugs.
*/
//sideCollided: false // Commented because it was causing a critical bug.
};
var stage = new createjs.Stage("canvas");
createjs.Touch.enable(stage);
var Graphic = function (src, blockWidth, blockHeight) {
src = src.split(",");
return {
createBlockAt: function (x, y, blockGroupWidth, blockGroupHeight, clsdir, alpha) {
for (var blockY = 0; blockY < blockGroupHeight/blockHeight; blockY++) {
for (var blockX = 0; blockX < blockGroupWidth/blockWidth; blockX++) {
var obj = new createjs.Bitmap(src[Math.floor(Math.random() * src.length)]);
obj.width = blockWidth;
obj.height = blockHeight;
if (typeof alpha !== 'undefined') {
obj.alpha = alpha; // While debugging this can be used to check if a block was made over another block.
}
obj.x = Math.round(x + (blockWidth * blockX));
obj.y = Math.round(y + (blockHeight * blockY));
if (clsdir != "none") {
objectsCollideAt.it.push(obj);
}
if (typeof clsdir !== "undefined") {
clsdir.split(" ");
if (clsdir.indexOf("top") >= 0 && blockY == 0) {
objectsCollideAt.top.push(obj);
}
if (clsdir.indexOf("left") >= 0 && blockX == 0) {
objectsCollideAt.left.push(obj);
}
if (clsdir.indexOf("right") >= 0 && blockX == (blockGroupWidth/blockWidth - 1)) { // blockGroupWidth/width results in the horizontal number of blocks
objectsCollideAt.right.push(obj);
}
if (clsdir.indexOf("bottom") >= 0 && blockY == (blockGroupHeight/blockHeight - 1)) { // blockGroupHeight/height results in the vertical number of blocks.
objectsCollideAt.bottom.push(obj);
}
} else {
if (blockY == 0) {
objectsCollideAt.top.push(obj);
}
}
obj2container.addChild(obj);
}
}
}
}
}
var dirt = Graphic("http://i.imgur.com/zF6Lhfl.png", 40, 40);
var rock = Graphic("http://i.imgur.com/QgxGfJs.png", 40, 40);
var grass = Graphic("http://i.imgur.com/5SkIyyM.png, http://i.imgur.com/CT6yf5q.png, http://i.imgur.com/gTwOePB.png", 40, 40);
var shadow = Graphic("http://i.imgur.com/50I5K1F.png", 40, 40);
var shadow2 = Graphic("http://i.imgur.com/dR9195w.png", 40, 40);
var obj2container = new createjs.Container();
// Note that the hero will respawn in the middle of each object if he die.
// dirt.createBlockAt(X, Y, W, H);
dirt.createBlockAt(0, 40, 40 * 3, 40 * 9);
rock.createBlockAt(40 * 4, 40 * 3, 40 * 3, 40);
dirt.createBlockAt(40 * 3, 40 * 5, 40 * 4, 40 * 5);
rock.createBlockAt(40 * 12, 40 * 6, 40, 40);
shadow.createBlockAt(40 * 5 - 20, 40 * 8 - 2, 40, 40, "none", 0.5);
shadow.createBlockAt(40 * 4, 40 * 9 - 2, 40, 40, "none", 0.5);
rock.createBlockAt(40 * 5 - 20, 40 * 7, 40, 40);
rock.createBlockAt(40 * 4, 40 * 8, 40, 40);
shadow2.createBlockAt(0, 40 * 9, 40 * 7, 40, "none", 0.5);
dirt.createBlockAt(0, 40 * 10, 40 * 14, $(window).height() - (40 * 10)); // Use $(window).height() instead of stage.canvas.height here. stage.canvas.height wasn't set yet. // This will be unnecessary after implementing camera movement.
grass.createBlockAt(0, 40 * 1 - 20, 40 * 3, 20, "none");
grass.createBlockAt(40 * 3, 40 * 5 - 20, 40 * 4, 20, "none");
grass.createBlockAt(0, 40 * 10 - 20, 40 * 14, 20, "none");
obj2container.cache(0, 0, $(window).width(), $(window).height());
stage.addChild(obj2container);
var data = {
images: ["http://i.imgur.com/RjVQ6e1.png"],
frames: {
width: 30,
height: 40
},
animations: {
stand: 0,
run: [1, 2, "runloop", 0.15],
runloop: [3, 7, true, 0.15],
jump: 11,
fall: 12,
stopfalling: [13, 15, "stand", 0.25]
}
};
var spriteSheet = new createjs.SpriteSheet(data);
var hero = new createjs.Sprite(spriteSheet, "stand");
hero.offset = 4 + 1; // "+1" is important, change the first number only.
hero.regX = hero.offset + 2;
hero.regY = hero.offset;
hero.width = 30 - (hero.offset * 2) - 10;
hero.height = 40 - (hero.offset * 2);
hero.xvel = hero.yvel = 0; // Number of pixels the hero will move/8.
if (localStorage.x && localStorage.y && localStorage.xpast && localStorage.ypast) { // Was localStorage declared?
hero.x = Number(localStorage.x);
hero.y = Number(localStorage.y);
hero.xpast = Number(localStorage.xpast);
hero.ypast = Number(localStorage.ypast);
} else {
hero.x = hero.xpast = 40; // Very first X.
hero.y = hero.ypast = 0; // Very first Y.
}
hero.jumping = true;
hero.airtime = 0;
hero.animation = "stand";
stage.addChild(hero);
if (typeof Storage === undefined) {
alert("Your browser doesn't support saving the game. All changes will be discarted when you leave the page.");
}
document.addEventListener("keydown", function (evt) {
if (evt.keyCode == 87 || evt.keyCode == 38 || evt.keyCode == 32) { // up
if (!key.holdingUp && !hero.jumping) { // Check if hero isn't jumping and if user isn't holding the key.
key.up = true;
}
}
if (evt.keyCode == 65 || evt.keyCode == 37) { // left
key.left = true;
}
if (evt.keyCode == 68 || evt.keyCode == 39) { // right
key.right = true;
}
if (evt.keyCode == 83 || evt.keyCode == 40) { // down
key.down = true;
}
});
document.addEventListener("keyup", function (evt) {
if (evt.keyCode == 87 || evt.keyCode == 38 || evt.keyCode == 32) { // up
key.up = false;
key.holdingUp = false;
}
if (evt.keyCode == 65 || evt.keyCode == 37) { // left
key.left = false;
}
if (evt.keyCode == 68 || evt.keyCode == 39) { // right
key.right = false;
}
if (evt.keyCode == 83 || evt.keyCode == 40) { // down
key.down = false;
}
});
stage.on("stagemousedown", function (e) {
if (event.which === 1) {
mouse.x = e.stageX,
mouse.y = e.stageY;
if (mouse.x > hero.x + hero.width + touch.tollerance) {
key.right = true;
}
if (mouse.x < hero.x - touch.tollerance) {
key.left = true;
}
if (mouse.x > hero.x - touch.tollerance && mouse.x < hero.x + hero.width + touch.tollerance && mouse.y > hero.y - touch.tollerance && mouse.y < hero.y + hero.height + touch.tollerance) {
key.up = true;
}
}
});
stage.on("stagemouseup", function() {
setTimeout(function() {
key.up = false;
key.right = false;
key.left = false;
key.holdingUp = false;
}, 1000/60); // Wait for one tick loop.
});
// Collision handler:
function collisionHandler(obj1, obj2array) { // MASTERPIECE!
// Side-to-side collision handler:
objectsCollideAt.top.forEach(function (obj2) {
// Top side:
if (obj1.ypast + obj1.height < obj2.y && obj1.y + obj1.height >= obj2.y &&
// Checks if past position X was correct:
obj1.xpast + obj1.width >= obj2.x && obj1.xpast <= obj2.x + obj2.width) {
hero.yvel = 0;
hero.jumping = false;
if (hero.airtime > 30) {
// hero.xpast and hero.ypast must be set to the same position so it will not cause a collision.
hero.x = hero.xpast = Number(localStorage.x);
hero.y = hero.ypast = Number(localStorage.y);
} else {
obj1.y = obj2.y - obj1.height - 1;
if (typeof Storage !== undefined && !hero.jumping && hero.y == hero.ypast) { // Checks for localStorage support.
localStorage.x = obj2.x + ((obj2.width/2) - (obj1.width/2));
localStorage.y = hero.y;
localStorage.xpast = hero.xpast;
localStorage.ypast = hero.ypast;
//Debugging:
//console.log("Stored "+Number(hero.x)+" as "+Number(localStorage.x)+".");
}
}
hero.airtime = 0;
}
});
objectsCollideAt.left.forEach(function (obj2) {
// Left side:
if (obj1.xpast + obj1.width < obj2.x && obj1.x + obj1.width >= obj2.x &&
// Checks if past position Y was correct:
obj1.ypast + obj1.height >= obj2.y && obj1.ypast <= obj2.y + obj2.height) {
hero.xvel = 0;
obj1.x = obj2.x - obj1.width - 1;
}
});
objectsCollideAt.right.forEach(function (obj2) {
// Right side:
if (obj1.xpast > obj2.x + obj2.width && obj1.x <= obj2.x + obj2.width &&
// Checks if past position Y was correct:
obj1.ypast + obj1.height >= obj2.y && obj1.ypast <= obj2.y + obj2.height) {
hero.xvel = 0;
obj1.x = obj2.x + obj2.width + 1;
}
});
objectsCollideAt.bottom.forEach(function (obj2) {
// Bottom side:
if (obj1.ypast > obj2.y + obj2.height && obj1.y <= obj2.y + obj2.height &&
// Checks if past position X was correct:
obj1.xpast + obj1.width >= obj2.x && obj1.xpast <= obj2.x + obj2.width) {
hero.yvel = 0;
obj1.y = obj2.y + obj2.height + 1;
}
});
/*
Now that every side-to-side collision change was made,
the edge-to-edge collision handler will not detect
blocked collisions.
*/
// Edge-to-edge collision handler:
objectsCollideAt.left.forEach(function (obj2) {
// Top left edge:
if (obj1.ypast + obj1.height < obj2.y && obj1.xpast + obj1.width < obj2.x && obj1.y + obj1.height >= obj2.y && obj1.x + obj1.width >= obj2.x) {
hero.xvel = 0;
obj1.y = obj2.y - obj1.height - 1;
obj1.x = obj2.x - obj1.width - 1;
}
// Bottom left edge:
if (obj1.ypast > obj2.y + obj2.height && obj1.xpast + obj1.width < obj2.x && obj1.y <= obj2.y + obj2.height && obj1.x + obj1.width >= obj2.x) {
hero.yvel = hero.xvel = 0;
obj1.y = obj2.y + obj2.height + 1;
obj1.x = obj2.x - obj1.width - 1;
}
});
objectsCollideAt.right.forEach(function (obj2) {
// Top right edge:
if (obj1.ypast + obj1.height < obj2.y && obj1.xpast > obj2.x + obj2.width && obj1.y + obj1.height >= obj2.y && obj1.x <= obj2.x + obj2.width) {
hero.xvel = 0;
obj1.y = obj2.y - obj1.height - 1;
obj1.x = obj2.x + obj2.width + 1;
}
// Bottom right edge:
if (obj1.ypast > obj2.y + obj2.height && obj1.xpast > obj2.x + obj2.width && obj1.y <= obj2.y + obj2.height && obj1.x <= obj2.x + obj2.width) {
hero.yvel = hero.xvel = 0;
obj1.y = obj2.y + obj2.height + 1;
obj1.x = obj2.x + obj2.width + 1;
}
});
}
function changeAnimation(obj1, frameOrAnimation) {
if (obj1.animation != frameOrAnimation) {
obj1.animation = frameOrAnimation;
obj1.gotoAndPlay(frameOrAnimation);
}
}
// Tick:
createjs.Ticker.on("tick", tick);
createjs.Ticker.setFPS(60);
function tick(event) {
if (key.up && !hero.jumping && !key.holdingUp && Math.abs(hero.ypast - hero.y) < 6) { // Distance between last frame and actual frame y must be less than 6px.
// KNOWN BUG: SOMETIMES THE JUMP HEIGHT DOUBLE! [IMPORTANT]
// Diagnostic: None.
// Reproduction: This bug normally occur during lags and was amplified after implementing time-based logic.
// Solution: Unknown.
hero.yvel -= 145; // How much speed the jump will produce. Please avoid changing this number — Speeds over 200 can kill the hero.
hero.jumping = true;
key.holdingUp = true; // Prevent jumping multiple times while holding the key.
} else {
if (hero.yvel < 0) {
hero.yvel += 3;
}
}
if (key.left && !key.right) {
hero.xvel -= (!hero.jumping) ? 3 : 2;
hero.regX = hero.offset + 12; // Need review.
hero.scaleX = -1;
}
if (key.right && !key.left) {
hero.xvel += (!hero.jumping) ? 3 : 2;
hero.regX = hero.offset + 2; // "+2" is due to the head's opposite side.
hero.scaleX = 1;
}
if (key.down) {
//hero.yvel+=3; // Commented because there's no need for pushing the hero down. If uncommented: // Need review.
}
hero.xvel = (hero.xvel > 0) ? Math.min(hero.xvel, 50) : Math.max(hero.xvel, -50);
//hero.yvel = (hero.yvel > 0)?Math.min(hero.yvel, 125):Math.max(hero.yvel, -125); // No need for this, there's gravity already.
if (hero.jumping == true) {
if (hero.yvel < 50) {
changeAnimation(hero, "jump");
} else {
changeAnimation(hero, "fall");
}
}
if (hero.ypast != hero.y && hero.yvel > 0) {
hero.airtime++;
changeAnimation(hero, "fall");
}
if (hero.airtime > 100) {
// hero.xpast and hero.ypast must be set to the same position so it will not cause a collision.
hero.x = hero.xpast = 0;
hero.y = hero.ypast = 0;
}
if (!key.left && !key.right) {
if (!hero.jumping) {
if (hero.animation == "fall" || hero.animation == "stopfalling") {
changeAnimation(hero, "stopfalling");
} else {
changeAnimation(hero, "stand");
}
if (hero.xvel != 0) {
hero.xvel += (hero.xvel < 0) ? 5 : -5;
}
} else {
if (hero.xvel != 0) {
hero.xvel += (hero.xvel < 0) ? 2 : -2;
}
}
if (Math.abs(hero.xvel) < 3) {
hero.xvel = 0;
}
} else {
if (!hero.jumping && hero.xvel != 0) { // Not jumping, pressing left or right
changeAnimation(hero, "run");
}
}
setTimeout(function() {
hero.yvel += 7;
}, 250);
hero.xpast = hero.x;
hero.ypast = hero.y;
hero.x += Math.round(event.delta/1000 * (hero.xvel * 6));
hero.y += Math.round(event.delta/1000 * (hero.yvel * 6));
collisionHandler(hero, objectsCollideAt.it);
stage.update();
}
// Canvas resizing:
var resizeCanvas = function() {
stage.canvas.width = window.innerWidth;
stage.canvas.height = window.innerHeight;
}
resizeCanvas();
$(window).on('resize', resizeCanvas);
}
// Image preloading (Primitive!):
function loadImgs(src, callback) {
var sprite = new Image();
sprite.onload = callback;
sprite.src = src;
}
loadImgs("http://i.imgur.com/RjVQ6e1.png", function() { // Hero Sprite
loadImgs("http://i.imgur.com/zF6Lhfl.png", function() { // Dirt
loadImgs("http://i.imgur.com/gTwOePB.png", function() { // Grass 3
loadImgs("http://i.imgur.com/CT6yf5q.png", function() { // Grass 2
loadImgs("http://i.imgur.com/5SkIyyM.png", function() { // Grass
loadImgs("http://i.imgur.com/QgxGfJs.png", function() { // Rock
loadImgs("http://i.imgur.com/50I5K1F.png", function() { // Shadow
loadImgs("http://i.imgur.com/dR9195w.png", function() { // Shadow2
init();
});
});
});
});
});
});
});
});