You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现按空格键每秒一次攻击,解决长按连点循环触发问题

问题:实现空格键攻击冷却机制失败

需求

  • 按空格键时每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事件,必须确保冷却期间完全忽略后续触发。

修改思路

  1. 按下空格键且stateAttack为false时,立即锁定状态并执行攻击逻辑
  2. 无论攻击是否命中敌人,都启动1秒延迟,时间到后再解锁stateAttack,保证1秒内仅能触发一次攻击
  3. 移除冗余的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 22:20:17