基本的 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);
当我移动时,它需要一秒钟左右的时间才能开始以适当的速度移动。速度在一秒钟左右后保持稳定,但如果你来回移动,速度会出于某种原因开始增加。我不知道为什么。
left
和 right
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>
我只是在使用 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);
当我移动时,它需要一秒钟左右的时间才能开始以适当的速度移动。速度在一秒钟左右后保持稳定,但如果你来回移动,速度会出于某种原因开始增加。我不知道为什么。
left
和 right
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>