我所拥有的是一个与keydown事件相关联的元素。
类似问题的答案都指向clearInterval,我无法开始工作。
首先,我使用keyup事件来检查正在按下哪个箭头键:
var counter = 0;
var yPosArray = [];
var right = true;
var done = false;
var leftX;
var rightX;
$(document).keydown (function(e)
{
rightX = parseInt(($('#movingObject').css('left')).replace('px','')) + 50;
leftX = parseInt(($('#movingObject').css('left')).replace('px',''));
if(e.which == 39)// right
{
$('#movingObject').find('img').attr('src','assets/images/mario_right.png');
right = true;
$('#xRight').val(rightX);
$('#xLeft').val(leftX);
move();
}
if(e.which == 37) //left
{
$('#movingObject').find('img').attr('src','assets/images/mario_left.png');
right = false;
$('#xRight').val(rightX);
$('#xLeft').val(leftX);
move();
}
if(e.which == 38) //up
{
if($('#movingObject').css('bottom') == '0px' && !false)
{
done = true;
gravity();
done = false;
}
}
});
如上所示,当满足此条件e.which == 37
时,将调用方法move()
。 move方法的作用如下所示,是增加元素的left
样式属性。我有一个计时器的原因是随着时间的推移速度增加,但是当钥匙被释放时,事件应该停止射击。因此,我想调用keyup事件,如上一个代码片段所示。解释将在那里继续。
var speed = 0;
var maxspeed = 0;
var timer;
function move()
{
var counter = 0;
timer = setInterval(function ()
{
maxspeed++;
$('#movingObject').css('left', moveX + maxspeed + 'px');
++counter;
}, 70);
}
如上所示,在创建move
函数之前声明了timer变量,并将其设置为setInterval
方法。因为变量在根级别,如果这是有意义的,它可以在所有函数中使用。
如下所示,我已启动keyup事件以检查不同的密钥。
$(document).keyup (function(e)
{
var posX = parseInt(($('#movingObject').css('left')).replace('px',''));
if(e.which == 39)// right
{
maxspeed = 0;
clearInterval(timer);
timer = 0;
}
if(e.which == 37) //left
{
maxspeed = 0;
clearInterval(timer);
timer = 0;
}
$('#movingObject').css('left', posX + 'px');
});
上面,我使用了clearInterval并尝试将timer
设置为等于0,然后继续增加。
这是一个fiddle,其中包含我的代码结构的所有脚本。
为什么会发生这种情况?
答案 0 :(得分:1)
每次setInterval
都会创建一个新的timer
,所以当你clearInterval
时,你必须清除你创建的所有计时器(可能是其中一些)。看看这个打击:< / p>
var speed = 0;
var maxspeed = 0;
var timer=[];
function move()
{
var counter = 0;
timer.push(setInterval(function ()
{
maxspeed++;
$('#movingObject').css('left', moveX + maxspeed + 'px');
++counter;
}, 70));
}
$(document).keyup (function(e)
{
var posX = parseInt(($('#movingObject').css('left')).replace('px',''));
if(e.which == 39)// right
{
maxspeed = 0;
$.each(timer,function(i,n){
clearInterval(n);
});
timer=[];
}
if(e.which == 37) //left
{
maxspeed = 0;
$.each(timer,function(i,n){
clearInterval(n);
});
timer=[];
}
$('#movingObject').css('left', posX + 'px');
});
答案 1 :(得分:1)
当用户同时按下两个(或更多)键时,可能会发生这种情况。然后你会在没有中间密钥的情况下调用move()
来清除一个间隔 - 这意味着你要覆盖第一个的timer
间隔id并且永远不能再次停止它,基本上在密钥发生时忘记了它。
如何解决这个问题?有一些选择:
一次只运行一个间隔。这可以通过每timer = setInterval(…)
前加clearInterval(timer)
来实现(如果已经清除则不会发生任何事情)。
有一组运行间隔。像@jarvanJiang实现它的数组没有多大意义,因为如果只释放一个键(如while(timers.length) clearInterval(timers.pop())
),你不想停止所有间隔。也没有一种FIFO队列,其中最早的间隔被清除。
相反,您需要每个键一个计时器ID - 运行间隔的映射。释放钥匙后,您可以通过在地图中查找来确定要清除的间隔。
实现更好的只是一个间隔game loop,以及一个布尔键的映射,指示当前按下了哪些。这将允许您管理干扰输入,并使动画运行更顺畅。