基本的 js 游戏动画不流畅

basic js game not animating smoothly

我只是在使用 js 测试基本的横向滚动条功能。我从来没有做过这样的事情,所以我真的不知道自己在做什么,但我很难在互联网上找到与我所经历的非常相似的东西。这是 git 页面的 link,上面有游戏 https://fgvand94.github.io/side-scroller-test/。我没有使用 canvas 或任何东西。 IDK,如果我需要让它按照我想要的方式工作。我只是想在关键输入上做一个块移动。这是我的 JS 代码

const block = document.querySelector('.block');


let right = false;
let left = false;

const move = (e) =>{
    if (e.keyCode === 37) {
        left = true
    }

    if (e.keyCode === 39) {
        right = true;
    }
    blockmove();
}

const move2 = () => {
    
    right = false;
    left = false;
}


let x = 0;

const blockmove = () => {
    if (right) {
    x += .05;
    block.style.left = `${x}px`;
}
    if (left) {
    x -= .05;
    block.style.left = `${x}px`;        
    }

        requestAnimationFrame(blockmove)
    
}


document.addEventListener('keydown', move);
document.addEventListener('keyup', move2);
requestAnimationFrame(blockmove);

当我移动时,它需要一秒钟左右的时间才能开始以适当的速度移动。速度在一秒钟左右后保持稳定,但如果你来回移动,速度会出于某种原因开始增加。我不知道为什么。

leftright CSS 属性通常由浏览器渲染器进行舍入,因此只有当完整的舍入像素发生变化时,您才会看到对这些属性所做的更改。

您正在将 x 值递增 0.05,这将需要至少出现 10 次才能达到 0.5(~170 毫秒 @60FPS),然后再出现 20 次( ~240ms) 到达下一个 1.5 步骤。

但是,您的代码确实会在每次触发新按键时开始一个新循环,因此在第二次按键时,x 实际上会增加 0.1,在第三次按键时会增加 0.15 等让整个事情 运行 越来越快(直到它吃掉太多资源并开始再次变慢)。请记住,按住按键会定期触发新事件,这可以解释您感觉到的“1 秒”延迟。

为了克服这个问题,启动一个 requestAnimationFrame 循环,并定义您想要移动对象的速度。

此外,虽然第一次练习可能看起来有点复杂,但我应该注意到 requestAnimationFrame 运行s 处于屏幕刷新率,这意味着两个不同的显示器将使您动画 运行 以不同的速度。
为此,我们目前最好的办法是使用增量时间:

const block = document.querySelector('.block');

const speed = 50 / 1000; // 50px per second
let right = false;
let left = false;

const move = (e) => {
  e.preventDefault();
  if (e.keyCode === 37) {
    left = true
  }
  if (e.keyCode === 39) {
    right = true;
  }
}

const move2 = (e) => {
  e.preventDefault();
  if (e.keyCode === 37) {
    left = false
  }
  if (e.keyCode === 39) {
    right = false;
  }
}

let lastTime = performance.now();
let x = 0;

const blockmove = (time) => { // rAF passes a timestamp
                              // representing the last v-sync event
  const delta = (time - lastTime) * speed;
  lastTime = time;
  if (right) {
    x += delta;
    block.style.left = `${x}px`;
  }
  if (left) {
    x -= delta;
    block.style.left = `${x}px`;
  }
  requestAnimationFrame(blockmove)
}


document.addEventListener('keydown', move);
document.addEventListener('keyup', move2);
// start the animation loop only once
requestAnimationFrame(blockmove);
body {
  display: flex;
}

.block {
  background: red;
  height: 200px;
  width: 200px;
  position: relative;
}
<div class="block"></div>