0

我所拥有的是一个与 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 方法的作用,如下所示,是增加元素的leftstyle 属性。我有一个计时器的原因是速度随着时间的推移而增加,但是当按键被释放时,事件应该停止触发。因此,我想调用上一个代码片段中看到的 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函数创建之前声明的,它被设置为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,之后它继续增加。

这是所有代码结构的脚本。

任何想法为什么会发生这种情况?

4

2 回答 2

1

每次setInterval都会创建一个新的timer,所以当你clearInterval必须清除你创建的所有计时器(可能是其中一些)时。看到这个打击:

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');
});
于 2013-05-23T09:55:56.560 回答
1

当用户同时按下两个(或更多)键时,就会发生这种情况。然后,您将move()随后在没有清除间隔的情况下调用 keyup - 这意味着您正在覆盖timer第一个间隔 id 并且永远无法再次停止它,基本上在 keyup 发生时忘记了它。

如何解决这个问题?有一些选择:

  • 一次只运行一个区间。这可以很容易地通过在每个前面timer = setInterval(…)加上clearInterval(timer)(如果它已经被清除就不会发生任何事情)来实现。

  • 有一组跑步间隔。while(timers.length) clearInterval(timers.pop())正如@jarvanJiang 实现的那样,数组没有多大意义,因为如果只释放一个键(如 中),您不想停止所有间隔。清除最旧间隔的一种 FIFO 队列也没有。

    相反,您希望每个键都有一个计时器 ID - 运行间隔的映射。释放键后,您可以通过在地图中查找来确定要清除的间隔。

  • 更好的实现是只有一个间隔,游戏循环,以及一个布尔键映射,指示当前按下了哪些键。这将允许您管理干扰输入,并使动画运行更流畅。

于 2013-05-23T10:20:57.523 回答