1

player.fire是一个布尔值,如果空格keydown. 一切正常。

我遇到的问题是控制数组asteroids.firing.push间隔。现在,它添加了一些实例,即使我轻轻点击空格键也是如此。我正在使用requestAnimationFrame.

如何控制push间隔?

    if(player.fire){
        var angle = thisShip.rot, 
        hyp = 10; //speed

        var vX = Math.cos(angle) * hyp, 
        vY = Math.sin(angle) * hyp;

        asteroids.firing.push(new asteroids.model.fire(thisShip.x, thisShip.y, vX, vY));
    }

我已经尝试过类似的方法,但它并没有减慢push间隔,而是产生了一种脉冲效果,一次又一次地重新生成发射序列。

    ...
    if(player.fire){
            fireInterval(thisShip);
    }

    function fireInterval(thisShip){
        var angle = thisShip.rot, 
            hyp = 10; //speed

        var vX = Math.cos(angle) * hyp, 
        vY = Math.sin(angle) * hyp;

        asteroids.firing.push(new asteroids.model.fire(thisShip.x, thisShip.y, vX, vY));

        setTimeout(function(){
            fireInterval(thisShip);
        }, 500);
    } 
4

3 回答 3

5

发生的事情是你每次更新都调用这个函数。我不知道您的引擎是什么样的,但如果您使用requestAnimationFrame,则可能高达 60fps,或者如果您只是尽可能快地循环,则可能会更高,并且更新与绘图无关。

你需要做的是在舰炮上设置某种状态。不管它是什么...

thisShip.cooldownTime = 250; //ms
thisShip.lastFired =    oldTimestamp;

if (currentTime - thisShip.lastFired >= thisShip.cooldownTime) {
    thisShip.fire(); // push the model, set lastFired to current time, etc...
}

此外,就其他人的建议而言:

我不确定你是如何实现监听键盘事件的......
但是在 JS 中处理键,我最倾向于做的是让键盘触发尽可能多的keydown事件keyup和它想要的事件。与缓冲不同的是,key-event 函数所做的唯一一件事就是告诉Keyboard对象一个键是按下还是按下。

在更新期间轮询该Keyboard对象。

document.addEventListener("keydown", function (e) {
    var key = e.keyCode;
    if (!!Keyboard[key]) { return; } 
    Keyboard[key] = e.timeStamp;
});


document.addEventListener("keyup", function (e) {
    var key = e.keyCode;
    delete Keyboard[key];
});

轮询以查看密钥是否已关闭。通过将键的值设置为e.timeStamp,您现在可以知道他们何时开始按住它,因此您可以控制您的船多久开火一次。

更好的是,您可以设置一些抽象系统,例如:

var Keymap = { SPACE : 32, A : 65, ... };
Player1.controls = { FIRE : "SPACE" };

var code = Keymap[Player1.controls.FIRE],
    pressedSince = Keyboard[code]; // timestamp || undefined

现在你有一些东西可以与你的冷却时间和门进行比较。无论他们敲击的速度有多快,或者键盘是否默认通过 turbo-fire 工作,您都应该拥有防止 turbo-fire 所需的所有数据点,以允许按住自动触发(以 250ms 为门控,或门控到屏幕上只有 3 个子弹,或其他),如果您检测到该键一直被轻敲,则门控到一个较小的值,以让按钮捣碎者比按钮持有人稍有优势。

于 2012-09-16T09:37:11.827 回答
1

我假设您if(player.fire){...}的游戏循环中有部分代码?如果是这样,这就是它经常被触发的原因。对此最常用的解决方案是在一次火灾事件发生后有一个“冷静”期,然后用户才能再次开火。例如:

if ( player.fireWait > 0 ) {
  player.fireWait--;
}

if( player.fire && (player.fireWait == 0) ){
  player.fireWait = 20;
  fire( thisShip );
}

上面的一个问题是,如果用户反复点击开火按钮,他们将无法再次开火(直到.fireWait计数器再次击中 0)。这就是为什么无论你的 onkeydown 是什么,你都需要这样做:

player.fireWait = 0;

但是另一张海报正确地指出,您还需要使用键盘缓冲区才能使您的射击机制像大多数游戏一样工作。如果没有缓冲,如果用户按住空间,您将获得单次射击……然后在一段时间后您会突然获得快速射击。这样做的原因是因为keydown它与正常的键盘输入相关,如果你按住一个键,你会看到发生了什么。

于 2012-09-16T09:39:04.570 回答
0

您需要使用某种键盘缓冲区。
我建议看看这篇博文
评论也很有用,从中你可以找到:这个网站

您现在所做的只是将开火动作延迟半秒,但仍会发送所有捕获的“keydown”。
我也会考虑使用“keyup”,可能会更好。

于 2012-09-16T09:33:27.113 回答