If I understand correctly you're asking how to get your function called multiple times in such a way to create an animation.
Its better to think of this problem in a different way however. Instead of thinking how can you get a moving animation, think of it as a repeating game loop that has two stages to it.
The first that updates your game's logic and the second that re-renders your entire scene.
Thankfully with the JavaScript environment in modern browsers, creating a gameloop is quite easy. You actually have a few options.
Set Interval
The setInterval();
function takes two values, the first is the name of the function you want to repeat and the second is the time in milliseconds in which you want to delay when the function is called again.
So for example
function update() {
}
function render() {
}
function loop() {
update();
render();
}
// Sets loop to run at ~60FPS
// 1000ms = 1s, 1000 / 60 = 16ms
setInterval(loop,1000 / 60);
This will get your game running in a loop, but calling setInterval();
again will cause problems by effectively creating two loops.
If you want to stop a loop you have created this way, you can use the value returned from setInterval();
in the clearInterval();
function.
let loopID = setInterval(loop,1000 / 60);
// stop the gameloop
clearInterval(loopID);
Set Timeout
The setTimeout();
function is the exact same as setInterval apart from one important detail, It waits for the delay you give and executes your function only once.
This is slightly more preferable since control on weather the loop needs to continue can be given over to the programmer.
but to use this to cause a function to loop like before.
function update() {
}
function render() {
}
function loop() {
update();
render();
setTimeout(loop,1000 / 60);
}
setTimeout(loop,1000 / 60);
Similarly setTimeout();
has a cancel function as well clearTimeout();
that you can use in the same was as setInterval();
.
Request Animation Frame
Probably the most well suited looping function for game programming in browsers. requestAnimationFrame();
will take a function and call it at the next vSync (This depends on the browser). In essense what this means is that it will automatically put a loop at 60FPS and take lag into account.
function update() {
}
function render() {
}
function loop() {
update();
render();
requestAnimationFrame(loop);
}
// No additional values required
requestAnimationFrame(loop);
Like the two other functions, requestAnimationFrame();
can be stopped with cancelAnimationFrame();
.
A clear advantage that this function has over the other two is what happens when a user switches tabs. A game loop using this function will effectively become paused when a user switches tabs and resume when they come back, whereas the other two loops would still be running.
Using A Loop For Animation
Using the approach I provided for animation shouldn't be too difficult.
assuming I have a square as follows.
let square = {
x: 0,
y: 0,
dx: 1,
dy: 1,
width: 10,
height: 10
}
I can use the update();
function to move it forward little by little each loop and then re-draw it at it's new position using render();
So the complete animation would look like this
function update() {
// dx & dy refer to delta x & y (velocity)
square.x = square.x + square.dx;
square.y = square.y + square.dy;
}
function render() {
// clear the canvas
ctx.fillStyle = "gray";
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "darkred";
ctx.fillRect(square.x,square.y,square.width,square.height);
}
function loop() {
update();
render();
requestAnimationFrame(loop);
}
// No additional values required
requestAnimationFrame(loop);