如何解决游戏角色按住移动键时先卡顿再持续移动的问题?
问题解决方案
当前代码的问题在于只在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
相关产品推荐
相关产品推荐

