假设我们有一个可以在屏幕周围左右移动的球。当您单击空格时,球应该跳。
我让球在画布上左右移动。但是,当球向左移动(例如)并且我在碰到空格键之前,球就停止向左移动。
迄今签出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!");
});
我如何才能停止这种行为,以便在按下空格键时,球跳起来,但同时仍然向左移动?
一个想法被添加到其他所有人的好主意中:
将用户输入与图形分开。
键盘:
如果您在使用KeyboardJS时遇到问题,请查看Keydrown:http://jeremyckahn.github.io/keydrown/
[捕获关键点时不做任何绘图…只捕获用户希望圆前进的方向的输入。
设置“方向”变量以容纳用户按下[左]或[右]的次数:
var direction=0;
当按下[左]时:
direction--;
当按下[右]时:
direction++;
方向是网号。因此,如果用户按住向左键20次,向右键15次,方向将为-5(-20 + 15)。
设置“海拔”变量以容纳用户按下[空格]的次数:
var altitude=0;
当按下[空格]时:
altitude-=10;
海拔也是网号。
绘图:
将所有图形绘制在单独的动画循环中。而不是使用javascript的setInterval,而是使用经过改进的新方法来创建模仿循环-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++;
}
}
祝您的项目顺利!
问题是,如果在按第一个键后再按另一个键,它将触发该事件,并停止触发另一个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
为true时才使window.KeysDown[i]
函数运行。我希望这个解决方案对您有用。
EDIT:我已经将代码更改为工作代码。我也做了a JSFiddle that demonstrates this。我以前的代码中的问题是,显然开关不能很好地处理整数值,因此我需要将i
转换为字符串。
EDIT:我还向脚本添加了一个额外的部分,使onSpace
函数仅在首次按下空格键时运行,因此直到释放空格键后它才再次运行然后再按一次我也updated my JSFiddle包含了这些更改。
我将创建一个主要功能,该功能以固定的间隔运行,并且每次运行时,它都会根据当前按下的键来更新圆的位置。
主要功能可以这样完成:
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个像素。
[jsFiddle Demo
] >>
您将必须为此手动创建一个框架。 KeyboardJS只是没有削减它。我想我在这里设置了。它使用Action“类”以及关键事件触发器。
动作“类”
jsFiddle Demo
关键事件触发器
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);
};