使用requestAnimationFrame时,如何让部分动画更新的更快

When using requestAnimationFrame, how to make part of animation update faster

我正在用requestAnimationFrame做一个游戏(蛇游戏),游戏的帧更新速度最初是每秒更新一次

需要将这条蛇的“requestAnimationFrame”从每次一秒更新为每次0.5秒。因为很多蛇的设计,当蛇碰到任何物品时,都会出现加速10秒的情况。

我的问题是如何维护主“requestAnimationFrame”(每秒更新一次),还有一个“requestAnimationFrame”(每0.5秒更新一次)?

主要requestAnimationFrame代码

    let speed = 1;
    let lastRenderTime = 0;

    const doAnimation = function (currentTime) {

        window.requestAnimationFrame(doAnimation);

        const secondRender = (currentTime - lastRenderTime) / 1000;  // secondRender is used to control the update per second

        if (secondRender < 1 / speed) {
            return;
        }
        lastRenderTime = currentTime
    }

    window.requestAnimationFrame(doAnimation);

let then, then2;
(function loop(delta) {
  then = then || delta;
  then2 = then2 || delta;
  
  let time = delta - then;
  let time2 = delta - then2;
  
  if (time > 1000) {
    then = delta;
    // in here every second
  }
  if (time2 > 500) {
    then2 = delta;
    // in here every 0.5 seconds
  }
  
  document.body.innerHTML = time.toFixed(2) + '<br>' + time2.toFixed(2);
  requestAnimationFrame(loop);
})();

requestAnimationFrame射速通常在60Hz左右。即每秒调用 60 次,理论上的最大精度约为 16 毫秒(0.016 秒)。

这意味着在您的循环中,您可以以任何高于此的速率进行更新。但是为什么要截断精度?

requestAnimationFrame 的全部要点是准确知道何时会发生重绘并在正确的时间传递有关动画的信息。举个例子:如果你的蛇必须每秒移动 1000px,你为什么要每秒通知浏览器更新?理想情况下,您应该更新每一帧的视图。所以在这个例子中,每 16 毫秒变化 16px。

请查看以下代码段并注意任何地方都没有条件。不过只是持续更新。

显然最终实现将取决于您的用例,但这只是工作原理。

const boxA = document.getElementById('boxA'); // DEMO
const boxB = document.getElementById('boxB'); // DEMO

let xA = 0; // DEMO
let xB = 0; // DEMO

const speedA = 80; // [px/s]
const speedB = 160; // [px/s]

let then = 0;

const animate = function (now) {
    window.requestAnimationFrame(animate);

    const delta = (now - then) / 1000;

    // A
    const a = speedA * delta;
    boxA.style.transform = `translateX(${xA += a}px)`; // DEMO
    
    // B
    const b = speedB * delta;
    boxB.style.transform = `translateX(${xB += b}px)`; // DEMO
    
    then = now
}

window.requestAnimationFrame(animate);
.container {
  display: flex;
  flex-direction: column;
}

#boxA,
#boxB {
  display: inline-block;
  height: 50px;
  width: 50px;
  transform: translateX(0);
}

#boxA {
  background-color: #ff0000;
}

#boxB {
  background-color: #0000ff;
}
<div class='container'>
  <span id='boxA'></span>
  <span id='boxB'></span>
</div>