实现按空格键每秒一次攻击,解决长按连点循环触发问题
问题:实现空格键攻击冷却机制失败
需求
- 按空格键时每1秒发起一次攻击
- 两次攻击间隔期间无法触发动作,避免长按空格键循环触发攻击
遇到的问题
- 尝试用状态变量+
setInterval实现,但状态变量未达到预期效果 setInterval仅能延迟连点操作,无法彻底解决长按触发的问题
相关代码
function moovePlayer() { //State to not start the animation while one is already in progress let state = false; let stateAttack = false; $(document).on('keydown', function (e) { if (state == false) { state = true; //Retrieving player parent let parentPlayer = $('.player').parent(); //Retrieving the player parent index let indexParentPlayer = $('.block-x').index(parentPlayer); //Condition to know that it is touching is to press switch (e.code) { {...}//other code case 'Space': //stateAttack is a state variable that prevents spamming the space hold attack if (stateAttack == false) { stateAttack = true; // let intervalAttack = setInterval(function () { //Recovery of the 4 sides of the player let block_x_up = $($('.block-x').eq(indexParentPlayer - number_block_y)); let block_x_down = $($('.block-x').eq(indexParentPlayer + number_block_y)); let block_x_right = $($('.block-x').eq(indexParentPlayer + 1)); let block_x_left = $($('.block-x').eq(indexParentPlayer - 1)); //Checking if enemy in the 4 sides recovered if ((block_x_up.children().length > 0) || (block_x_down.children().length > 0) || (block_x_right.children().length > 0) || (block_x_left.children().length > 0)) { animateAttackRight(); //using the attack function attack($('.player'), $('.enemy')); // clearInterval(intervalAttack); stateAttack = false } else { // clearInterval(intervalAttack); state = false; stateAttack = false } // }, 1000) } else { // clearInterval(intervalAttack) stateAttack = false; } default: state = false; } } }) }
解决方案
核心问题出在状态变量的时机控制错误,且误用了setInterval(你需要的是单次延迟解锁,而非重复执行)。另外长按空格键会连续触发keydown事件,必须确保冷却期间完全忽略后续触发。
修改思路
- 按下空格键且
stateAttack为false时,立即锁定状态并执行攻击逻辑 - 无论攻击是否命中敌人,都启动1秒延迟,时间到后再解锁
stateAttack,保证1秒内仅能触发一次攻击 - 移除冗余的
state变量,简化状态控制逻辑
修改后的代码
function moovePlayer() { let stateAttack = false; // 仅保留攻击冷却状态变量 $(document).on('keydown', function (e) { switch (e.code) { case 'Space': e.preventDefault(); // 阻止空格键默认行为(如页面滚动) if (!stateAttack) { stateAttack = true; // 立即锁定攻击状态 // 获取玩家父元素及索引 let parentPlayer = $('.player').parent(); let indexParentPlayer = $('.block-x').index(parentPlayer); // 获取玩家四周的方块 let block_x_up = $($('.block-x').eq(indexParentPlayer - number_block_y)); let block_x_down = $($('.block-x').eq(indexParentPlayer + number_block_y)); let block_x_right = $($('.block-x').eq(indexParentPlayer + 1)); let block_x_left = $($('.block-x').eq(indexParentPlayer - 1)); // 检查四周是否有敌人 if (block_x_up.children().length > 0 || block_x_down.children().length > 0 || block_x_right.children().length > 0 || block_x_left.children().length > 0) { animateAttackRight(); attack($('.player'), $('.enemy')); } // 1秒后解锁攻击状态,确保冷却时间 setTimeout(() => { stateAttack = false; }, 1000); } break; // 必须添加break,避免执行default逻辑 // 保留其他按键逻辑 default: // 其他按键的处理代码 break; } }); }
关键改进点
- 用
setTimeout替代setInterval:仅需攻击后延迟解锁状态,无需重复执行攻击逻辑 - 按下空格键立即锁定
stateAttack,无论攻击成败,都等待1秒后解锁,严格保证冷却时间 - 添加
e.preventDefault()避免空格键默认行为干扰 - 修复
switch语句的break问题:原代码中Space case未加break,会执行default里的state = false导致状态意外重置 - 移除冗余的
state变量,简化状态控制
修改后,无论长按还是快速连点空格键,都只会每1秒触发一次攻击,完全符合需求。
内容的提问来源于stack exchange,提问作者JoKa
相关产品推荐
相关产品推荐

