让我们说我们有一个可以在屏幕左右移动的球。当你点击空格时,球应该跳跃。
我让球在画布上左右移动。然而,当球向左移动(例如)并且我在任何东西之前击中空格键时,球停止向左移动。
到目前为止查看my example!
我使用KeyboardJS库来处理我的关键事件:
KeyboardJS.on("left", function () {
cc();
x -= xv;
if (x < r) {
circle(x + width, y, r);
if (x + width <= width - r) {
x = x + width;
}
}
circle(x, y, r);
});
KeyboardJS.on("space", null, function () {
console.log("space!");
});
我怎么能让这种行为停止,这样当空格键被击中时,球会跳起来,但同时仍然向左移动?
答案 0 :(得分:2)
问题是,如果在按下第一个键后按另一个键,它将触发该事件,并停止触发另一个keydown事件。这可以在这个简化的例子中看到:
addEventListener('keydown',function(e) {console.log(e.keyCode, e.keyIdentifier)});
如果您运行该脚本,然后按向左然后向上,它将首先显示37 Left
一次,然后它将显示32 U+0020
一次并停止记录左侧键盘。
这就是浏览器(以及大多数其他基本程序)的工作原理。您可以尝试在例如记事本中执行相同的操作,如果先按A键,然后按空格键,它将停止添加更多的As。这也意味着您不能依赖关键事件(或关键事件库)来为您执行此操作。
你可以做的是制作一个包含所有按键的全局对象。例如:
window.KeysDown = {
37: false, //Left
39: false, //Right
38: false, //Up
40: false, //Down
32: false, //Space
};
addEventListener('keydown', function(e) {
var keyCode = e.keyCode||e.charCode||e.which;
if (keyCode == 32 && !window.KeysDown[keyCode])
onSpace();//This will only run when the spacebar is first pressed down.
if (window.KeysDown.hasOwnProperty(keyCode))
window.KeysDown[keyCode] = true;
});
addEventListener('keyup', function(e) {
var keyCode = e.keyCode||e.charCode||e.which;
if (window.KeysDown.hasOwnProperty(keyCode)) window.KeysDown[keyCode] = false;
});
var interval = setInterval(function() {
for (var i in window.KeysDown) {
if (window.KeysDown[i]) switch (i+'') {
case '37': onLeft(); break;
//case '38': window.KeysDown[i] && onUp(); break;
case '39': onRight(); break;
//case '40': window.KeysDown[i] && onDown(); break;
}
}
}, 50);
语法window.KeysDown[i] && onLeft()
只会导致onLeft
函数在window.KeysDown[i]
为真时运行。我希望这个解决方案适合你。
编辑:我已将代码更改为工作代码。我也做了a JSFiddle that demonstrates this。我之前的代码中的问题是显然交换机不能很好地处理整数值,所以我需要将i
转换为字符串。
编辑:我还在脚本中添加了一个额外的部分,使onSpace
函数仅在首次按下空格键时运行,并且不会运行再次,直到空格键被释放并再次按下。我还updated my JSFiddle要包含这些更改。
答案 1 :(得分:2)
一个想法增加了其他人的好主意:
将用户输入与绘图分开。
<强>键盘输入:强>
如果您遇到KeyboardJS问题,请查看Keydrown:http://jeremyckahn.github.io/keydrown/
捕捉关键时不要做任何绘图......只需捕捉用户输入他们希望圆圈移动的方向。
设置“方向”变量以保存用户按[左]或[右]的次数:
var direction=0;
按[左]时:
direction--;
按[右]时:
direction++;
方向是净数。因此,如果用户按住左键20次,右键按下15次,方向将为-5(-20 + 15)。
设置“高度”变量以保存用户按[空格]的次数:
var altitude=0;
按[空格]时:
altitude-=10;
海拔高度也是净值。
<强>绘制:强>
在单独的动画循环中完成所有绘图。而不是使用javascript的setInterval,使用新的和改进的创建imation循环的方式 - requestAnimationFrame
。
// set the starting circle positions
var currentX=canvas.width;
var currentY=canvas.height-r;
function animate(){
// even as we're executing this current animation loop
// request another loop for next time
requestAnimationFrame(animate);
// change the currentX position by the accumulated direction
currentX+=direction;
direction=0;
// change the currentY position by the accumulated altitude
currentY+=altitude;
altitude=0;
// draw the circle at its current position
cc();
circle(currentX,currentY,r);
// apply gravity to the circle
// to make it fall if its in the air
if(currentY<canvas.height-r){
currentY++;
}
}
祝你的项目好运!
答案 2 :(得分:1)
我会创建一个主函数,它以固定的间隔运行,每次运行时,它会根据当前关键的内容更新圆的位置。
主要功能可以这样做:
var keyDown = {};
function mainLoop() {
cc();
//pseudo code
if (keyDown["left"]) {
x -= 5;
}
if(keyDown["space"]) {
y -= 10;
}
// redraw circle at new location
circle(x,y,r);
}
setInterval(mainLoop, 30) //sets the function to be called every 30 milliseconds
// key event handler, first function handles the keydown, second function handles keyup
KeyboardJS.on("left", function() {
keyDown["left"] = true;
}, function() {
keyDown["left"] = false;
});
使用此示例,如果用户在mainLoop
函数运行时按下了左箭头键和空格键,则圆圈将向左移动5个像素,向上移动10个像素。
答案 3 :(得分:1)
的 jsFiddle Demo
强> 的
您将不得不为此手动创建框架。 KeyboardJS只是没有削减它。我想我有点把它放在这里。它使用Action“类”和关键事件触发器。
行动“类”
function Actions(){
this.count = 0;
this.running = {};
this.interval = undefined;
}
Actions.prototype.start = function(action){
if( typeof(this.running[action]) == "undefined"){
this[action]();
this.running[action] = action;
this.count++;
}
var me = this;
if( typeof(this.interval) == "undefined"){
this.interval = setInterval(function(){
for( var act in me.running ){
me[act]();
}
},50);
}
};
Actions.prototype.stop = function(action){
this.running[action] = void 0;
delete this.running[action];
this.count--;
if( this.count == 0 ){
clearInterval(this.interval);
this.interval = void 0;
};
};
Actions.prototype.left = function(){
cc();
x -= xv;
if (x < r) {
circle(x + width, y, r);
if (x + width <= width - r) {
x = x + width;
}
}
circle(x, y, r);
};
Actions.prototype.right = function(){
cc();
x += xv;
if (x >= width - r) {
circle((x - r) - (width - r), y, r);
if ((x - r) - (width - r) > r) {
x = (x - r) - (width - r);
}
}
circle(x, y, r);
};
Actions.prototype.space = function(){
cc();
y -= yv;
circle(x, y, r);
};
关键事件触发器
document.onkeydown = checkKeyDown;
function checkKeyDown(e) {
e = e || window.event;
if (e.keyCode == '37') {
// left arrow
actions.start("left");
}
if (e.keyCode == '39') {
// right arrow
actions.start("right");
}
if (e.keyCode == '32') {
// space bar
actions.start("space");
}
}
document.onkeyup = checkKeyUp;
function checkKeyUp(e) {
e = e || window.event;
if (e.keyCode == '37') {
// left arrow
actions.stop("left");
}
if (e.keyCode == '39') {
// right arrow
actions.stop("right");
}
if (e.keyCode == '32') {
// space bar
actions.stop("space");
}
}