I'm trying to make a game loop for an HTML / Javascript browser game I'm working on. I am currently using this code here as a loop:
while(true)
{
(game code here)
}
The code is in an externally linked Javascript file, and should have a game loop which does not break the game.
After a bit of reading I found out that the loop makes the page unresponsive. What is the correct way to include a game loop in HTML / Javascript without breaking the page?
CodePudding user response:
Javascript within the browser is blocking of any user input. It is also single threaded. Nothing is allowed to change while a function is running. Hence the browser is unresponsive until the script stops. It is this way be design so you don't need to worry if the data you received on the mouse or about the page had changed ... imagine if your program was reading the page information, it changed then you needed to update it using the information you read before it changed ... single threaded means you don't need to worry about that. It did not change the browser was unresponsive.
Note web workers run in a different thread and can signal or event to the functions that update the page. Web workers don't block the browser. And web workers can not update the HTML directly, less the page changed before function ended happens.
Hence you need to run the loop then allow the browser to interact and run the loop again.
setTimeout() has been the old school method, note the delay is optional, (if no delay is used it will start as soon as everything else the browser need to do is completed ... IE get user input)
function gameloop() {
(game code here)
setTimeout(gameloop); // technically the script stopped until the timeout event.
}
setTimeout(gameloop); // fire event with no delay. IE start loop.
New school is requestAnimationFrame() as per Arnav answer. requestAnimationFrame() is faster hence better.
CodePudding user response:
You should never use a while (true)
loop (or anything that will always result in true
).
while (true) {
console.log("Most likely will crash the browser!");
}
I didn't make it a code snippet because it will most likely crash your browser.
What it will do (in this case) is output the string
an infinite number of times (until the browser crashes).
Most likely will crash the browser!
Most likely will crash the browser!
Most likely will crash the browser!
...Stops responding...
A good alternative for a game loop is to use requestAnimationFrame()
.
The great things about it are:
- It's supported in all browsers (even Internet Explorer^)!
- It doesn't crash your browser.
- It only runs when the tab is focused. This means it won't take up resources in the background.
According to MDN Web Docs, it states that:
The
window.requestAnimationFrame()
method tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint.
It returns an long
integer value, which can be used to call window.cancelAnimationFrame()
to cancel it.
A simple example is below.
function loop() {
// You don't need 'window', because by default it's global.
requestAnimationFrame(loop);
// Example...
GameClass.updateGame();
}
The reason you pass the loop()
function in requestAnimationFrame()
is because it will call that function to update on the next repaint, which is why the example GameClass.updateGame()
function is being called as a placeholder.
For more examples, please see the examples on MDN Web Docs. They are more advanced and will take too long to explain in this answer.
In summary, you should use the requestAnimationFrame()
function in place of the while (true)
loop to avoid the browser not responding.
^ Only supported in IE 10 and 11.