如何利用物理原理来避免运动模糊?

前端开发 2026-07-11

P5.js用于渲染,但这可以在任意语言和图形库中实现(并非引擎)。

在没有固定时间步和插值的情况下移动对象会很清晰;但使用固定时间步和插值时,画面会变得模糊。去掉插值也会让它显得卡顿,原因很明显。

沙盒: editor.p5js.org,把左侧的示例粘贴进去,然后用按钮或 ctrl + enter 运行。

const step = 1 / 60; // Physics step
let acc = 0; // Accumulator

let pos1; // Upper rectangle
let lastPos1; // Last position of the upper rectangle
let pos2; // Lower rectangle

// The function is called once (init)
function setup() {
  createCanvas(windowWidth, windowHeight); // Create the canvas
  frameRate(144); // Set the number of frames per second

  // Initialize the rectangle positions
  pos1 = createVector(0, height / 2 - 100);
  pos2 = createVector(0, height / 2);
}

// The function is called every frame
function draw() {
  background(220); // Fill the background

  acc += deltaTime / 1000; // Increase the accumulator

  lastPos1 = pos1; // Store the last position of the top rectangle

  while (acc >= step) {
    // While the accumulator is greater than the physics step
    pos1.x += 100 * step; // Move the top rectangle to the right
    acc -= step; // Decrease the accumulator
  }

  pos2.x += 100 * (deltaTime / 1000); // Move the bottom rectangle to the right

  const alpha = acc / step; // Interpolation coefficient

  // Position interpolation
  const interpPos = p5.Vector.lerp(lastPos1, pos1, alpha);

  // Top rectangle (moves: physics)
  rect(interpPos.x, interpPos.y, 200, 50);

  // Bottom rectangle (moves: render)
  rect(pos2.x, pos2.y, 200, 50);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.0/p5.js"></script>

解决方案

我错过了一个链接,导致我得出了错误的结论。

-lastPos1 = pos1;
+lastPos1 = pos1.copy();

并把上一次的位置更新移到物理循环中,在当前这次之前。

const step = 1 / 60; // Physics step
let acc = 0; // Accumulator

let pos1; // Upper rectangle
let lastPos1; // Last position of the upper rectangle
let pos2; // Lower rectangle

// The function is called once (init)
function setup() {
  createCanvas(windowWidth, windowHeight); // Create the canvas
  frameRate(144); // Set the number of frames per second

  // Initialize the rectangle positions
  pos1 = createVector(0, height / 2 - 100);
  lastPos1 = pos1.copy();
  pos2 = createVector(0, height / 2);
}

// The function is called every frame
function draw() {
  background(220); // Fill the background

  acc += deltaTime / 1000; // Increase the accumulator

  // Store the last position of the top rectangle

  while (acc >= step) { // While the accumulator is greater than the physics step
    lastPos1 = pos1.copy();
    pos1.x += 100 * step; // Move the top rectangle to the right
    acc -= step; // Decrease the accumulator
  }

  pos2.x += 100 * (deltaTime / 1000); // Move the bottom rectangle to the right

  const alpha = acc / step; // Interpolation coefficient

  // Position interpolation
  const interpPos = p5.Vector.lerp(lastPos1, pos1, alpha);

  // Top rectangle (moves: physics)
  rect(interpPos.x, interpPos.y, 200, 50);

  // Bottom rectangle (moves: render)
  rect(pos2.x, pos2.y, 200, 50);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.0/p5.js"></script>
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章