Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么';t JavaScript';s设置超时减速键减速率?_Javascript_Jquery - Fatal编程技术网

为什么';t JavaScript';s设置超时减速键减速率?

为什么';t JavaScript';s设置超时减速键减速率?,javascript,jquery,Javascript,Jquery,当我连续按下按键事件(字母k)时,为什么以下按键事件没有减慢3000 mil?如果我把手指放低,计数会迅速增加,因为mcount上没有设置超时。为什么呢?每次计数之间应该有一个延迟,但我不能让它工作 var mcount = 0; function playershoot() { if(!game.playerHit){ $(document).keydown(function(e){ switch(e.keyCode){ case 75:

当我连续按下按键事件(字母k)时,为什么以下按键事件没有减慢3000 mil?如果我把手指放低,计数会迅速增加,因为mcount上没有设置超时。为什么呢?每次计数之间应该有一个延迟,但我不能让它工作

var mcount = 0;
function playershoot() {
if(!game.playerHit){ 
      $(document).keydown(function(e){ 
        switch(e.keyCode){
        case 75: 
        clearTimeout();
        setTimeout(console.log(mcount++), 3000);
        break;
        }
    });
}

}
playershoot();
任何建议都将不胜感激


感谢

设置超时
不会导致延迟,它会启动计时器,在指定的时间量后触发事件

,您需要重构代码,使其能够处理事件。对于您的代码,看起来您需要在第一次按键时设置一个标志。然后返回,并仅允许在清除标志时按下新的按键(即仅响应)。然后,使用
setTimeout

1可在一段时间后自动清除该标志。返回可使用清除的
timeoutId
。你不会那么做的。。。因此,在您延迟3秒后,所有这些超时都被连续调用

2.:您的
console.log会立即执行,因为您没有将其封装在这样的函数中:

setTimeout(function() { console.log(mcount++) }, 3000);

您必须将setTimeout的返回值传递给clearTimeout。取消它

var mcount = 0,timeout;
    function playershoot() {
    if(!game.playerHit){ 
          $(document).keydown(function(e){ 
            switch(e.keyCode){
            case 75: 
            clearTimeout(timeout );
            timeout = setTimeout(function(){
                       console.log(mcount++);
               }, 3000);
            break;
            }
        });
    }

    }
    playershoot();

虽然这里的每个人都是对的,但他们缺少的是你需要延迟发射,而不是延迟被调用的事件

在keydown事件内部,设置一个时间戳,为事件设置一个上一次时间和一个当前时间。 在函数内部,有一个时间限制

因此,当您按下该键(或反复触发)时,请检查:

current_time - last_fired >= rate_limit;
如果当前时间距离上次射击超过3000毫秒,则将上次射击的时间戳设置为当前时间,然后发射武器

编辑

考虑一下这个简单的例子:

var Keyboard = {};

var player = (function () {
    var gun = {
            charging  : false,
            lastFired : 0,
            rateLimit : 3000
        },

        controls = { shoot : 75 },

        isHit = false,
        public_interface;


    function shoot () {
        var currentTime = Date.now();

        if (gun.rateLimit > currentTime - gun.lastFired) { return; }
        /* make bullet, et cetera */

        gun.lastFired = currentTime;
    }

    function update () {
        if (Keyboard[controls.shoot] || gun.charging) { this.shoot(); }
        // if key was released before this update, then the key is gone...
        // but if the gun was charging, that means that it's ready to be fired

        // do other updates
    }

    function draw (ctx) { /* draw player */ }

    public_interface = {
        shoot : shoot,
        damage : function (amt) { isHurt = true; /* rest of your logic */ }
        draw : draw,
        update : update
    };

    return public_interface;

}());


document.addEventListener("keydown", function (e) {
    // if key is already down, exit
    if (!!Keyboard[e.keyCode]) { return; }
    // else, set the key to the time the key was pressed
    // (think of "charging-up" guns, based on how long you've held the button down)
    Keyboard[e.keyCode] = e.timeStamp;
});

document.addEventListener("keyup", function (e) { delete Keyboard[e.keyCode]; });
在您的gameloop中,您现在要做一些不同的事情:
您的播放机将自我更新。
在更新的内部,它会询问键盘是否按下了射击键。
如果是,那么它将调用shot方法

这仍然不是100%正确,因为玩家不应该关心或了解键盘。
它应该通过某种服务来处理,而不是要求使用
window.Keyboard
。 不管怎样

您的控件现在被包装在播放器中——因此您可以定义这些控件是什么,而不是到处通过
keyCode
询问

您的活动现在正在做它们应该做的事情:设置关键点并离开。
在您当前的迭代中,每次浏览器触发
键控
,可能是300x/秒,如果它愿意,该事件必须调用您的所有播放器逻辑。。。300倍/秒

在更大的游戏中,您可以更进一步,用
控件
健康
制作组件,每个组件都具有完成自己工作所需的所有属性和所有方法,而没有其他功能

以这种方式分解代码也会使拥有不同的枪变得非常简单。
想象一个
库存
组件:
库存包含不同的

每支
都有自己的
速率限制
,有自己的
上次发射
,有自己的
子弹数
,有自己的
伤害
,发射自己的
子弹类型

然后调用
player.shoot(),在内部,它将调用
inventory.affeed.shoot()

该内部功能将负责发射装备枪的所有逻辑(因为您将
库存。添加(枪);
到您的枪中,以及
库存。装备(id);
您想要的枪。

按照@Norguard的说法,这里有一个实现:

我将
fireRate
设置为一个整数,表示玩家每秒可以开火多少次


在演示中,我设置了3个玩家,每个玩家的射击速度不同。如果你按住空格键,你可以看到这个动作。

这里甚至没有这样做。
console.log
没有返回函数对象。啊哈,我想我现在已经明白了。3000是一个计时器,不是延迟机制。如果是这样的话,javascript方法将基于3000的setTimeOuts计时器产生延迟?您没有使用计时器。请尝试传入函数对象。尝试此方法,它会显示相同的缺陷:
setTimeout(警报(“立即完成”),86400*1000)
(将立即显示警报,但被告知“等待”一天:-)此外,“堆叠”SetTimeout可能不需要;因为clearTimeout没有传递任何内容,所以它不执行任何操作(如中所述,不停止任何超时)。因此,如果与函数对象正确使用,SetTimeout将滞后于mcount,但仍将以相同的速度有效增加(除非超时过多).pst,谢谢你的提示!我正在学习如何减少延迟,并在过程中使用setTimeout提高效率。我只是想对快速计数应用延迟。我是否应该检查其他策略,例如mcount是否可以被数值整除,以减慢速度?谢谢你的建议!因此我想要实现的项目需要被包装在函数中?就这样?这是我的问题吗?@blachawk是其中一个问题。还有第一个问题。好的,我会试试这个策略,然后给你回复。谢谢Norguard。@blachawk:看看更新,看看这是否对你有帮助。它比你现在可能正在研究的有点先进,但是(轮询)状态更改……并使用DOM事件设置状态(键盘和鼠标对象),从长远来看,这将使你的生活轻松10亿倍。特别是当你进入多人游戏,或处理许多不同的动作更新,或与许多移动的敌人/子弹/平台同步计时时,阅读变得非常重要,
this.fire = function(){
    var cFire = new Date();

    if ((cFire - lastFire) / 1000 > 1/me.fireRate){            
        // code to fire the projectile
        lastFire = cFire;
    }
};