JavaScript版Flappy Bird在新款MacBook Chrome中运行过快问题求助
问题分析
你的问题核心在于动画逻辑没有基于时间差(delta time)做标准化。requestAnimationFrame的回调执行频率完全依赖浏览器刷新率和设备性能——比如M2 MacBook Pro的Chrome可能以120fps运行,而Safari维持60fps,这就导致你的gravity和slideShipsAnimation函数执行次数差一倍,自然游戏速度快了一倍。
之前尝试delta time出问题,大概率是实现方式有误:要么没正确计算时间差,要么没把固定的每帧数值转换为每秒单位的移动/加速度,反而引入了新的不一致。
修复方案
我们需要把每帧的固定增量(比如velocity += gravityConstant、-3px)改成基于时间的动态计算,确保不管帧率波动,每秒的移动、加速度都是一致的。
1. 重构重力函数
let lastGravityTime = 0; // 把重力常量改成「每秒加速度」,比如原60fps下每帧加0.5,每秒就是30px,直接设为30 const GRAVITY = 30; // px/秒² let birdY = parseInt(getComputedStyle(bird).top); // 初始化时读取一次位置,避免频繁DOM查询 function startGravity() { function gravity(currentTime) { // 计算时间差(转成秒) const delta = (currentTime - lastGravityTime) / 1000; lastGravityTime = currentTime; // 按时间差更新速度和位置 velocity += GRAVITY * delta; birdY += velocity * delta; bird.style.top = `${birdY}px`; loops.gravityAnimation = requestAnimationFrame(gravity); } loops.gravityAnimation = requestAnimationFrame(gravity); }
2. 重构障碍物滑动函数
同样用时间差标准化移动速度,同时把setInterval生成障碍物的逻辑也改成基于帧的计时,避免浏览器节流影响间隔稳定性:
let lastShipTime = 0; const SHIP_SPEED = 180; // px/秒(原60fps下每帧减3px,每秒就是180px) let shipSpawnTimer = 0; const SPAWN_INTERVAL = 5; // 生成障碍物的间隔(秒) function runShips() { function spawnShips(currentTime) { const delta = (currentTime - lastShipTime) / 1000; shipSpawnTimer += delta; if (shipSpawnTimer >= SPAWN_INTERVAL) { // 你的生成障碍物逻辑 createShip(); shipSpawnTimer = 0; } requestAnimationFrame(spawnShips); } function slideShipsAnimation(currentTime) { const delta = (currentTime - lastShipTime) / 1000; lastShipTime = currentTime; document.querySelectorAll('.ships').forEach(ship => { let currentLeft = parseInt(getComputedStyle(ship).left); currentLeft -= SHIP_SPEED * delta; ship.style.left = `${currentLeft}px`; }); loops.slideShipsAnimation = requestAnimationFrame(slideShipsAnimation); } requestAnimationFrame(spawnShips); loops.slideShipsAnimation = requestAnimationFrame(slideShipsAnimation); }
3. 额外优化点
- 避免频繁调用
getComputedStyle:每次调用都会触发浏览器重排,把元素位置、尺寸存在变量里,仅在初始化或样式变更时更新。 - 移动设备故障排查:标准化时间后,若仍有问题,检查触摸事件的处理逻辑——确保跳跃等操作是基于帧同步触发,而非直接修改velocity后立即生效,避免和动画循环冲突。
内容的提问来源于stack exchange,提问作者Art Vardanyan
相关产品推荐
相关产品推荐

