我已经编写了非常简单的游戏教程,其中使用了一个简单的requestAnimationFrame游戏循环。他们不需要跟踪经过的时间或帧速率:
var canvas = document.querySelector("#canvas");
var ctx = canvas.getContext("2d");
function gameLoop() {
ctx.clearRect(0,0,canvas.width,canvas.height);
//Drawing, etc.
var myRAF = requestAnimationFrame(gameLoop);
}
gameLoop();
现在,我想学习如何从Spritesheet动画化诸如步行周期之类的东西,而不是仅对静态对象的运动进行动画处理。我认为这需要首先学习如何跟踪渲染一帧所需的时间,或者您在哪个帧上。我的印象是,如果您使用RAF而不是setInterval或setTimeout(糟糕!),则不需要这样做。我见过人们使用Date对象,requestAnimationFrame时间戳和Performance.now,尽管我还不了解代码。如果我的目标是从Spritesheets进行动画处理,并确保无论特定玩家获得多少fps,游戏中的运动速度都是相同的,那么哪个是使用requestAnimationFrame开发游戏的最佳选择?我读过,您必须将游戏中的所有速度乘以时间因子,但不知道如何。否则,只有30 fps的慢速计算机正在浏览游戏,并且与60 fps左右的快速计算机gettine相比,以一半的速度射击子弹,对吧?
请向我展示如何在游戏循环中实现时间/帧跟踪代码,以及实现此目标的不同方法的利弊。
冒着听起来像我想要教程的风险,请忽略原始问题的以下部分
也很高兴看到您将如何使用该代码来制作动画,例如从Spritesheet上行走或拍打翅膀,以及如何将移动速度乘以时间因子,以便每个人都能获得相同的游戏体验。
答案 0 :(得分:0)
requestAnimationFrame
进行回调。该回调自页面启动以来经过的时间(以毫秒为单位)。因此,您可以使用该时间从上一个requestAnimationFrame回调的时间中减去该时间,以计算出帧速率,并使用“ deltaTime”通过速度将多个其他值可变。
通常,您基于deltaTime移动事物。如果您的deltaTime以秒为单位,则可以很容易地基于每秒的delta进行任何操作。例如,每帧每秒移动10个单位,您可以执行以下操作
const unitsPerSecond = 10;
x = x + unitsPerSecond * deltaTimeInSeconds
关于帧数,您只需保留自己的计数器
const ctx = document.querySelector('canvas').getContext('2d');
let x = 0;
let y = 0;
const speed = 120; // 120 units per second
let frameNumber = 0;
let previousTime = 0;
function render(currentTime) {
// keep track of frames
++frameNumber;
// convert time to seconds
currentTime *= 0.001;
// compute how much time passed since the last frame
const deltaTime = currentTime - previousTime;
// remember the current time for next frame
previousTime = currentTime;
// move some object frame rate independently
x += speed * deltaTime;
y += speed * deltaTime;
// keep x and y on screen
x = x % ctx.canvas.width;
y = y % ctx.canvas.height;
// clear the canvas
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// draw something
ctx.fillStyle = (frameNumber & 0x1) ? 'red' : 'blue'; // change color based on frame
ctx.fillRect(x - 5, y - 5, 11, 11);
// draw something else based on time
ctx.fillStyle = 'green';
ctx.fillRect(
145 + Math.cos(currentTime) * 50,
75 + Math.sin(currentTime) * 50,
10, 10);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<canvas></canvas>