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

如何解决游戏角色按住移动键时先卡顿再持续移动的问题?

问题解决方案

当前代码的问题在于只在keydown事件触发时执行一次移动,而浏览器默认的按键重复机制本身带有初始延迟(也就是你遇到的0.5秒停顿),所以按住按键时只会先动一步,之后才会因为按键重复触发事件持续移动。

要解决这个问题,我们需要自己跟踪按键的按住状态,配合动画循环实现平滑持续移动,不依赖浏览器的按键重复机制:


1. 定义按键状态跟踪对象

用一个对象记录哪些按键处于按住状态:

const keysPressed = {
  ArrowUp: false,
  ArrowDown: false,
  ArrowLeft: false,
  ArrowRight: false,
  KeyW: false,
  KeyA: false,
  KeyS: false,
  KeyD: false
};

2. 监听按键事件更新状态

通过keydown和keyup事件更新按键状态,同时处理精灵方向切换:

// 按键按下时标记为激活状态
addEventListener('keydown', (action) => {
  if (keysPressed.hasOwnProperty(action.code)) {
    keysPressed[action.code] = true;
    // 切换对应方向的精灵图
    switch(action.code) {
      case "KeyD": case "ArrowRight":
        ui.image_x = 192;
        break;
      case "KeyA": case "ArrowLeft":
        ui.image_x = 288;
        break;
      case "KeyW": case "ArrowUp":
        ui.image_x = 128;
        break;
      case "KeyS": case "ArrowDown":
        ui.image_x = 32;
        break;
    }
  }
});

// 按键松开时标记为未激活状态
addEventListener('keyup', (action) => {
  if (keysPressed.hasOwnProperty(action.code)) {
    keysPressed[action.code] = false;
  }
});

3. 实现动画循环处理持续移动

用requestAnimationFrame创建游戏循环,每一帧检查按键状态并执行移动逻辑:

function gameLoop() {
  // 根据按键状态处理移动
  if (keysPressed.ArrowRight || keysPressed.KeyD) {
    ui.hero.position.x += 2.5;
  }
  if (keysPressed.ArrowLeft || keysPressed.KeyA) {
    ui.hero.position.x -= 2.5;
  }
  if (keysPressed.ArrowUp || keysPressed.KeyW) {
    ui.hero.position.y -= 2.5;
  }
  if (keysPressed.ArrowDown || keysPressed.KeyS) {
    ui.hero.position.y += 2.5;
  }

  // 更新并绘制画面
  ui.update();
  ui.draw();
  ui.draw_sprite();

  // 持续循环
  requestAnimationFrame(gameLoop);
}

// 启动游戏循环
gameLoop();

说明

修改后,只要按键处于按住状态,每一次浏览器刷新帧都会执行移动逻辑,完全避开了浏览器的按键重复延迟,按住按键时角色会立刻平滑持续移动,不会出现停顿。

内容的提问来源于stack exchange,提问作者Spelunkhead

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 13:32:50