为什么当我连续按下keydown事件(字母k)时,以下keydown事件不会减慢3000 mil?如果我把手指放下,计数会迅速加起来,因为mcount上没有setTimeout。这是为什么?每次计数之间应该有延迟,但我无法让它工作......
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();
任何建议都将不胜感激!
由于
答案 0 :(得分:6)
1:setTimeout()
返回timeoutId
,可以使用clearTimeout(timeoutId)
清除该console.log
。你没有这样做......所以,在你的3秒延迟之后,所有这些超时都会被召回。
2:你的setTimeout(function() { console.log(mcount++) }, 3000);
被立即执行,因为你没有将它包装在这样的函数中:
{{1}}
答案 1 :(得分:4)
setTimeout
不会导致延迟,它会启动一个计时器,在指定的时间后触发事件。
You cannot "sleep" in Javascript,您需要重构代码,以便它可以处理事件。对于您的代码,看起来您需要在第一次按键时设置标志。然后返回,并且仅在标志被清除时才允许新的按键(即仅响应)。然后可以在setTimeout
的时间后自动清除该标志。
答案 2 :(得分:4)
与@Norguard所说的一样,这是一个实现:http://jsfiddle.net/apu3P/
this.fire = function(){
var cFire = new Date();
if ((cFire - lastFire) / 1000 > 1/me.fireRate){
// code to fire the projectile
lastFire = cFire;
}
};
我将fireRate
设置为一个整数,表示玩家可以每秒发射多少次。
在演示中,我设置了3个玩家,每个玩家都有不同的火力。如果按住空格键,您可以看到这一点。
答案 3 :(得分:2)
虽然这里的每个人都是正确的,但他们缺少的是你需要延迟解雇,而不是被召唤的事件......
在keydown事件内部,设置时间戳,具有事件的上一个时间和当前时间。 在函数内部,有一个time_limit。
因此,当您按键(或反复触发)时,请检查:
current_time - last_fired >= rate_limit;
如果自上次拍摄后当前时间超过3000毫秒,则将last_fired
时间戳设置为当前时间,然后开火。
修改强>
考虑这个简单的例子:
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]; });
在你的游戏循环中,你现在要做的事情有点不同:
您的播放器将自行更新。
在更新内部,它询问键盘是否按下了拍摄键
如果是,则会调用拍摄方法。
这仍然不是100%正确,因为播放器不应该关心或了解键盘。
它应该通过某种服务来处理,而不是要求window.Keyboard
。
无论...
您的控件现在已包含在播放器中 - 因此您可以定义这些控件的内容,而不是在整个地方keyCode
询问。
你的活动现在正在做他们应该做的事情:设置钥匙然后离开
在您当前的迭代中,每当浏览器触发keydown
(可能是300x /秒)时,如果需要,该事件 ALSO 必须调用所有你的玩家逻辑... 300x / sec ......
在较大的游戏中,您可以更进一步,并使用Controls
和Health
制作组件,每个组件都具有所有属性以及执行所需的所有方法自己的工作,没有别的。
以这种方式打破代码也会使得使用不同枪支变得简单
想象一个Inventory
组件:
广告资源包含不同的guns
每个gun
都有自己的rateLimit
,有自己的lastFired
,有自己的bulletCount
,有自己的damage
,并自行激活bulletType
}。
那么你就打电话给player.shoot();
,在里面,它会打电话给inventory.equipped.shoot();
这个内在的功能将照顾所有射击装备枪的逻辑(因为你inventory.add(Gun);
你的枪,inventory.equip(id);
你想要的枪。
答案 4 :(得分:1)
您必须将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();