player.fire
是一个布尔值,如果空格键位于keydown
,则会变为 true 。一切都按预期工作。
我遇到的问题是控制数组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);
}
答案 0 :(得分: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
事件。
不使用缓冲,而是使用 事件,键事件函数会告诉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
现在你有一些东西可以与你的冷却时间和大门进行比较。 它们点击的速度无关紧要,或者如果键盘默认通过涡轮增压工作,你应该拥有防止涡轮火力所需的所有数据点,允许按住自动点火(门控250毫秒,如果你发现钥匙一直被敲击,你可以选择只有3个子弹在屏幕上,或其他任何东西上,然后选通一个较小的值,让按钮瞄准器略微超过按钮架。
答案 1 :(得分:1)
我假设你的游戏循环中有if(player.fire){...}
部分代码?如果是这样,那么它经常被触发的原因。对此最常见的解决方案是在一次火灾事件发生后,在用户再次开火之前进行“冷静”期。 e.g:
if ( player.fireWait > 0 ) {
player.fireWait--;
}
if( player.fire && (player.fireWait == 0) ){
player.fireWait = 20;
fire( thisShip );
}
上述问题之一是,如果用户反复点击开火按钮,则无法再次开火(直到.fireWait
计数器再次击中0)。这就是为什么你的onkeydown是你需要这样做的原因:
player.fireWait = 0;
然而,另一张海报已正确声明您需要使用键盘缓冲区,以便您的消防机制能够像大多数游戏一样工作。如果没有缓冲区,如果用户按下空间,你将得到一个单一的镜头......然后经过一段时间你会突然得到快速射击。这是因为keydown
与正常的键盘输入相关联,如果您按住某个键,您将看到发生了什么事情。
答案 2 :(得分:0)
您需要使用某种键盘缓冲区 我建议看this blog post 评论也非常有用,您可以从中找到:this site
你现在正在做的就是将火力行动延迟半秒,但所有被抓住的“keydown”仍然被发送。
我也会考虑使用“keyup”,可能会更好。