使用 $().keydown 平滑平铺游戏角色移动
Smooth tiled game character movement with $().keydown
我想在我的 tile 游戏中实现角色移动,这样它就不会向服务器发送大量关键事件。目前我已经使用 setInterval 限制了发送的事件数量。
我的想法有问题:
如果玩家没有在正确的时间点击按键,移动可能无法正常工作
连续点击一个键(例如向右箭头),只会在 setInterval 拾取事件时发送键事件。这让它看起来有问题。
我的代码很好:
如果您只需要按住钥匙,它就能完美运行。
同时按住两个键可以沿对角线移动。代码存储正在按下的键。
可能有帮助的事情:
- 与其限制关键事件,不如去抖动效果更好。我只是不希望玩家乱按按键以比按住按键时移动得更快。 (我在去抖代码方面没有取得多大成功)
这是我的代码的精简基本示例:http://jsfiddle.net/empXx/66/
var canvas = document.getElementById('c'),
ctx = canvas.getContext("2d"),
tileSize = 10;
var holdingUp = false;
var holdingDown = false;
var holdingLeft = false;
var holdingRight = false;
var cx = 150;
var cy = 150;
$(document).keydown(function(e) {
if(e.which==37) { holdingLeft = true; }
if(e.which==38) { holdingUp = true; }
if(e.which==39) { holdingRight = true; }
if(e.which==40) { holdingDown = true; }
});
$(document).keyup(function(e) {
if(e.which==37) { holdingLeft = false; }
if(e.which==38) { holdingUp = false; }
if(e.which==39) { holdingRight = false; }
if(e.which==40) { holdingDown = false; }
});
ctx.fillRect(150, 150, tileSize, tileSize);
setInterval(function() {
if(holdingUp) {
cls();
ctx.fillRect(cx, cy - tileSize, tileSize, tileSize);
cy -= tileSize;
} else if(holdingDown) {
cls();
ctx.fillRect(cx, cy + tileSize, tileSize, tileSize);
cy += tileSize;
}
if(holdingLeft) {
cls();
ctx.fillRect(cx - tileSize, cy, tileSize, tileSize);
cx -= tileSize;
} else if(holdingRight) {
cls();
ctx.fillRect(cx + tileSize, cy, tileSize, tileSize);
cx += tileSize;
}
}, 120);
function cls() { ctx.clearRect(0, 0, canvas.width, canvas.height); }
我怎样才能让这个游戏交互更流畅,让用户更愉快,同时减少垃圾邮件?
感谢 John S 的原始修复。我稍微修改了代码以使其更好。目前,如果用户同时按住左右键,播放器将不会移动。这是一个比根据按下键的顺序处理键优先级更简单的解决方案。我还做到了 upCount/downCount 等在 holdUp 和 holdDown 处于活动状态时无法更改。左右运动相同。
简单的 jsfiddle 与基本知识 here
使用此代码实现的生产游戏+反spam/cheat检测是here
JSFiddle 代码,按照 SO 的要求:
var canvas = document.getElementById('c'),
ctx = canvas.getContext("2d"),
tileSize = 10;
var holdingUp = false;
var holdingDown = false;
var holdingLeft = false;
var holdingRight = false;
var cx = 150;
var cy = 150;
var upCount = 0;
var downCount = 0;
var leftCount = 0;
var rightCount = 0;
$(document).keydown(function(e) {
if(e.which==37 && !holdingLeft) { holdingLeft = true; leftCount++; }
if(e.which==38 && !holdingUp) { holdingUp = true; upCount++; }
if(e.which==39 && !holdingRight) { holdingRight = true; rightCount++; }
if(e.which==40 && !holdingDown) { holdingDown = true; downCount++; }
});
$(document).keyup(function(e) {
if(e.which==37) { holdingLeft = false; }
if(e.which==38) { holdingUp = false; }
if(e.which==39) { holdingRight = false; }
if(e.which==40) { holdingDown = false; }
});
ctx.fillRect(150, 150, tileSize, tileSize);
setInterval(function() {
if(!(holdingUp && holdingDown)) {
if((upCount > 0) || holdingUp) {
if (upCount > 0) { upCount--; }
cls();
ctx.fillRect(cx, cy - tileSize, tileSize, tileSize);
cy -= tileSize;
} else if((downCount > 0) || holdingDown) {
if (downCount > 0) { downCount--; }
cls();
ctx.fillRect(cx, cy + tileSize, tileSize, tileSize);
cy += tileSize;
}
} else {
downCount = upCount = 0;
}
if(!(holdingLeft && holdingRight)) {
if((leftCount > 0) || holdingLeft) {
if (leftCount > 0) { leftCount--; }
cls();
ctx.fillRect(cx - tileSize, cy, tileSize, tileSize);
cx -= tileSize;
} else if((rightCount > 0) || holdingRight) {
if (rightCount > 0) { rightCount--; }
cls();
ctx.fillRect(cx + tileSize, cy, tileSize, tileSize);
cx += tileSize;
}
} else {
leftCount = rightCount = 0;
}
}, 120);
function cls() { ctx.clearRect(0, 0, canvas.width, canvas.height); }
我想在我的 tile 游戏中实现角色移动,这样它就不会向服务器发送大量关键事件。目前我已经使用 setInterval 限制了发送的事件数量。
我的想法有问题:
如果玩家没有在正确的时间点击按键,移动可能无法正常工作
连续点击一个键(例如向右箭头),只会在 setInterval 拾取事件时发送键事件。这让它看起来有问题。
我的代码很好:
如果您只需要按住钥匙,它就能完美运行。
同时按住两个键可以沿对角线移动。代码存储正在按下的键。
可能有帮助的事情:
- 与其限制关键事件,不如去抖动效果更好。我只是不希望玩家乱按按键以比按住按键时移动得更快。 (我在去抖代码方面没有取得多大成功)
这是我的代码的精简基本示例:http://jsfiddle.net/empXx/66/
var canvas = document.getElementById('c'),
ctx = canvas.getContext("2d"),
tileSize = 10;
var holdingUp = false;
var holdingDown = false;
var holdingLeft = false;
var holdingRight = false;
var cx = 150;
var cy = 150;
$(document).keydown(function(e) {
if(e.which==37) { holdingLeft = true; }
if(e.which==38) { holdingUp = true; }
if(e.which==39) { holdingRight = true; }
if(e.which==40) { holdingDown = true; }
});
$(document).keyup(function(e) {
if(e.which==37) { holdingLeft = false; }
if(e.which==38) { holdingUp = false; }
if(e.which==39) { holdingRight = false; }
if(e.which==40) { holdingDown = false; }
});
ctx.fillRect(150, 150, tileSize, tileSize);
setInterval(function() {
if(holdingUp) {
cls();
ctx.fillRect(cx, cy - tileSize, tileSize, tileSize);
cy -= tileSize;
} else if(holdingDown) {
cls();
ctx.fillRect(cx, cy + tileSize, tileSize, tileSize);
cy += tileSize;
}
if(holdingLeft) {
cls();
ctx.fillRect(cx - tileSize, cy, tileSize, tileSize);
cx -= tileSize;
} else if(holdingRight) {
cls();
ctx.fillRect(cx + tileSize, cy, tileSize, tileSize);
cx += tileSize;
}
}, 120);
function cls() { ctx.clearRect(0, 0, canvas.width, canvas.height); }
我怎样才能让这个游戏交互更流畅,让用户更愉快,同时减少垃圾邮件?
感谢 John S 的原始修复。我稍微修改了代码以使其更好。目前,如果用户同时按住左右键,播放器将不会移动。这是一个比根据按下键的顺序处理键优先级更简单的解决方案。我还做到了 upCount/downCount 等在 holdUp 和 holdDown 处于活动状态时无法更改。左右运动相同。
简单的 jsfiddle 与基本知识 here
使用此代码实现的生产游戏+反spam/cheat检测是here
JSFiddle 代码,按照 SO 的要求:
var canvas = document.getElementById('c'),
ctx = canvas.getContext("2d"),
tileSize = 10;
var holdingUp = false;
var holdingDown = false;
var holdingLeft = false;
var holdingRight = false;
var cx = 150;
var cy = 150;
var upCount = 0;
var downCount = 0;
var leftCount = 0;
var rightCount = 0;
$(document).keydown(function(e) {
if(e.which==37 && !holdingLeft) { holdingLeft = true; leftCount++; }
if(e.which==38 && !holdingUp) { holdingUp = true; upCount++; }
if(e.which==39 && !holdingRight) { holdingRight = true; rightCount++; }
if(e.which==40 && !holdingDown) { holdingDown = true; downCount++; }
});
$(document).keyup(function(e) {
if(e.which==37) { holdingLeft = false; }
if(e.which==38) { holdingUp = false; }
if(e.which==39) { holdingRight = false; }
if(e.which==40) { holdingDown = false; }
});
ctx.fillRect(150, 150, tileSize, tileSize);
setInterval(function() {
if(!(holdingUp && holdingDown)) {
if((upCount > 0) || holdingUp) {
if (upCount > 0) { upCount--; }
cls();
ctx.fillRect(cx, cy - tileSize, tileSize, tileSize);
cy -= tileSize;
} else if((downCount > 0) || holdingDown) {
if (downCount > 0) { downCount--; }
cls();
ctx.fillRect(cx, cy + tileSize, tileSize, tileSize);
cy += tileSize;
}
} else {
downCount = upCount = 0;
}
if(!(holdingLeft && holdingRight)) {
if((leftCount > 0) || holdingLeft) {
if (leftCount > 0) { leftCount--; }
cls();
ctx.fillRect(cx - tileSize, cy, tileSize, tileSize);
cx -= tileSize;
} else if((rightCount > 0) || holdingRight) {
if (rightCount > 0) { rightCount--; }
cls();
ctx.fillRect(cx + tileSize, cy, tileSize, tileSize);
cx += tileSize;
}
} else {
leftCount = rightCount = 0;
}
}, 120);
function cls() { ctx.clearRect(0, 0, canvas.width, canvas.height); }