Em muitas páginas da web, as pessoas ainda tendem a usar setInterval()
como função principal de um gameloop. Esta não é a melhor maneira de fazer isso. Os navegadores modernos são capazes de avisá-lo assim que estiverem prontos para renderizar uma nova saída usando requestAnimationFrame
.
Exemplo básico usando setInterval ()
var canvas = document.getElementById('canvas'),
cw = canvas.width,
ch = canvas.height,
cx = null,
fps = 30,
bX = 30,
bY = 30,
mX = 10,
mY = 20;
function gameLoop() {
cx.clearRect(0,0,cw,cw);
cx.beginPath();
cx.fillStyle = 'red';
cx.arc(bX, bY, 20, 0, Math.PI * 360);
cx.fill();
if(bX >= cw || bX <= 0) { mX*=-1; }
if(bY >= ch || bY <= 0) { mY*=-1; }
bX+=mX;
bY+=mY;
}
if (typeof (canvas.getContext) !== undefined) {
cx = canvas.getContext('2d');
setInterval(gameLoop, 1000 / fps);
}
O mesmo usando requestAnimationFrame
var vendors = ['webkit', 'moz'];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
}
var canvas = document.getElementById('canvas'),
cw = canvas.width,
ch = canvas.height,
cx = null,
fps = 30,
bX = 30,
bY = 30,
mX = 150,
mY = 300,
lastTime = (new Date()).getTime(),
currentTime = 0,
delta = 0;
function gameLoop() {
window.requestAnimationFrame(gameLoop);
currentTime = (new Date()).getTime();
delta = (currentTime - lastTime) / 1000;
cx.clearRect(0, 0, cw, cw);
cx.beginPath();
cx.fillStyle = 'red';
cx.arc(bX, bY, 20, 0, Math.PI * 360);
cx.fill();
if (bX >= cw || bX <= 0) {
mX *= -1;
}
if (bY >= ch || bY <= 0) {
mY *= -1;
}
bX += (mX * delta);
bY += (mY * delta);
lastTime = currentTime;
}
if (typeof (canvas.getContext) !== undefined) {
cx = canvas.getContext('2d');
gameLoop();
}
Outro método que limita a renderização a um máximo de fps
var vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}
var canvas = document.getElementById('canvas'),
cw = canvas.width,
ch = canvas.height,
cx = null,
fps = 30,
bX = 30,
bY = 30,
mX = 10,
mY = 20,
interval = 1000/fps,
lastTime = (new Date()).getTime(),
currentTime = 0,
delta = 0;
function gameLoop() {
window.requestAnimationFrame(gameLoop);
currentTime = (new Date()).getTime();
delta = (currentTime-lastTime);
if(delta > interval) {
cx.clearRect(0,0,cw,cw);
cx.beginPath();
cx.fillStyle = 'red';
cx.arc(bX, bY, 20, 0, Math.PI * 360);
cx.fill();
if(bX >= cw || bX <= 0) { mX*=-1; }
if(bY >= ch || bY <= 0) { mY*=-1; }
bX+=mX;
bY+=mY;
lastTime = currentTime - (delta % interval);
}
}
if (typeof (canvas.getContext) !== undefined) {
cx = canvas.getContext('2d');
gameLoop();
}