sollten Sie halten simulating
und drawing
getrennt.
Unten ist ein Beispiel wo ich eine simulation
jede Millisekunde (1000 mal in einer Sekunde) mache. Jede Simulation löscht die vorherige Anforderung eines Animationsrahmens.
Wenn die Aktualisierung des Browsers "angekreuzt" ist, wird es drawn
unser Update (inkrementiert unseren Zähler) haben.
nach 1 Sekunde stoppe ich und wir sollten ungefähr Ihre Bildwiederholfrequenz als unsere count
sehen.
//counter
var count = 0;
//draw function
function draw() {
count++;
}
//Animation frame handle
var animationFramHandle;
//Run every millisecond
var interval = setInterval(function() {
//Cancel requestAnimationFrame
cancelAnimationFrame(animationFramHandle);
//request new requestAnimationFrame
animationFramHandle = requestAnimationFrame(draw);
}, 1);
//Wait 1 second
setTimeout(function() {
//Stop simulation
clearInterval(interval);
cancelAnimationFrame(animationFramHandle);
console.log("ticks in a second:", count);
}, 1000);
Bearbeiten - Warum Trennung von Bedenken
auf der Leinwand Zeichnung ist eine teuere Operation, die Sie normalerweise nicht in jedem Frame ausgeführt werden möchten, wenn Sie es vermeiden können .
Im Grunde nur für ein Neuzeichnen aufrufen, wenn sich etwas ändert.
In meinem Beispiel unten ich eine große Menge von Boxen erstellen, simulieren sie und ziehen sie:
//DOM elements
var canvas = document.createElement("canvas");
canvas.width = 400;
canvas.height = 400;
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgba(0,0,0,0.1)";
var drawNode = document.createElement("p");
document.body.appendChild(drawNode);
//Variables
var simulations = 0;
var simulationTime = 0;
var requestAnimationFrameHandle;
//Boxes to simulate and draw
var boxes = [];
while (boxes.length < 10000) {
boxes.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
s: 5
});
}
//Draw function
function draw() {
var t = Date.now();
//Clear
ctx.clearRect(0, 0, canvas.width, canvas.height);
//Draw
for (var bIndex = 0; bIndex < boxes.length; bIndex++) {
var box = boxes[bIndex];
ctx.fillRect(box.x, box.y, box.s, box.s);
}
//Log
drawNode.innerHTML = ("New draw after " + simulations + " simulations<br>Drawing took " + (Date.now() - t) + " ms<br>Simulation time is " + simulationTime + " ms");
simulations = 0;
}
//Simulate function
function simulate(force) {
if (force === void 0) { force = false; }
simulations++;
if (Math.random() * 1000 > 800) {
var t = Date.now();
for (var bIndex = 0; bIndex < boxes.length; bIndex++) {
var box = boxes[bIndex];
box.x = Math.abs(box.x + (Math.random() * 3 - 1)) % canvas.width;
box.y = Math.abs(box.y + (Math.random() * 3 - 1)) % canvas.height;
}
simulationTime = Date.now() - t;
cancelAnimationFrame(requestAnimationFrameHandle);
requestAnimationFrameHandle = requestAnimationFrame(draw);
}
}
setInterval(simulate, 1000/120);
Beachten Sie, wie als sie ist viel schneller zu simulieren sie zeichnen. Als Faustregel gilt, dass Sie nur 1000/60 ~ 16
Millisekunden zwischen jedem Frame haben. Wenn wir also die Millisekunden einer Ziehung ersparen könnten, würden wir dies gerne tun und eine solche Frame-Berechnungszeit auf größere Operationen konzentrieren (wie Pfadfindung) oder Kollisionserkennung oder was auch immer in Ihrem Spiel schwer sein würde).
Auf diese Weise können wir unsere Simulation auch mit einer anderen Rate als der Ziehgeschwindigkeit ausführen, was praktisch ist, wenn mit asynchronen Aufgaben gearbeitet wird.
Bitte werfen Sie einen Blick auf diesen Thread: http://StackOverflow.com/Questions/19764018/Controlling-FPs-With-RequestAnimationframe – mrmnmly
Warum muss es 30 fps sein?Der Trick mit 'requestAnimationFrame' besteht darin, dass es immer die bestmögliche Bildwiederholfrequenz für jeden Monitor bietet, so dass die Beschränkung auf 30 fps seltsam erscheint. –
@ EmilS.Jørgensen ok danke! Es stellt sich heraus, dass der obige Code in Ordnung ist. Es gibt 60 fps in meinem System und ich denke, das ist gut für Spiele. – kofhearts