02 Game Loops

02 Game Loops

JavaScript Game Development

Intro to game loops

Note: This is not the only way to do this, this is just one simple way to do it. There are probably better or worse ways of doing this, so don’t be too confident with this approach!

A game loop is just an infinite loop that, conventionally, calls three functions at a certain time.

A side note, it is ideal to program loops using concurrency (threads, mutexes, future/promise), but since JS has been synchronous for a long time, it will work smoothly even without it. I recommend using Google Chrome for best results (use developer tools > more tools > performance > Rendering for a deeper look), Firefox if Chrome isn't an option. Others I can't guarantee smooth performance.

Screenshot 2022-04-07 152846.jpg

Loop Life Cycle

NOTE: I call render when we want to draw the entire scene, draw is for drawing individual scene objects.

/*
 *Since JS is synchronous, it will 
 *NOT look like this in this course
 */
while (gameIsRunning) {
    getInput();
    updateLogic();
    render();
}

GetInput

It receives data from any peripherals that send the application an event. Mice, keyboards, printers, scanners, game controllers, joysticks, microphones, drawing tablets, and other devices are examples. Keymanagers and event queues are examples of things you might discover in this strategy. Keymanagers inform the program whether and which keys have been pushed, and the update function determines what to do with that information. Because the OS and many game engines and game engine library authors (such as SDL and FreeGLUT) manage this so well, event queues are no longer used. They just add an event to a queue, remove it, and manage the events that have been popped. With images, there's a lot more to say about event queues. More on event queues with visuals

Update

It updates everything that has to be updated (players, enemies, clocks, events, menus). Here is where all the math and logic are done. As you can probably tell, the input also gets handled here because an input can change the way things are updated.

Render

It handles all the drawing. I have seen some people use rendering and updating in one function; the problem with that is that it won't do precise rendering.

Rendering should be done after all the components have been updated. Rendering is, after all, a visual of the update; we don't want to draw before the update is complete, or else inaccurate placements would occur.

Time

This is an Optional topic, and we will not be using it throughout this course! Feel free to skip it! I just put it here to make this chapter longer for people that plan on taking game programming seriously; a little bit of "what to expect." As mentioned above, game loops should run at a certain time; this is where the term "frame capping" comes from.

Time is fixed; a second for me will be a second for you, no matter what (forget time perception here). CPU clock cycles, on the other hand, vary. A 500MHz CPU will run slower than an 8GHz CPU, no doubt about it. Therefore, a game that is not frame capped will run a lot faster on the 8GHz machine. In order to prevent this, we use time as a factor to update our game (it is known as delta time).

Since we will not be using this method, I will not go too in-depth into it, but basically, we get the system time when the start of the loop was called (usually in ms or ns), delta time is incremented by the loop start minus the last time the loop started divided by target frames in ms or ns, the last time is now set to the time this current loop started, check if delta time meets your criteria, update the game logic, reset delta time, put the thread to sleep, render, and continue after X time (usually less than or equal to 1 second).

There is more math to this, such as Pixel-Per-Meter (great for physics simulations), or how many pixels are X TIME in respect to delta time, but I will not be showing that.

Basic Canvas Animation

In the old days, we used setInterval for game loops, which isn't bad (I started off with it), but you will still have to consider time, as mentioned above, since setInterval doesn't consider appropriate animation times.

There is now a requestAnimationFrame that will "try" to do a good job of animating at 60FPS. Sometimes you will still have to consider frame capping, but not about 80% of the time (for real-time multiplayer games, it would be recommended to frame cap). For more on this, read this article. I recommend learning frame capping if you want to take game programming seriously.

At first, our canvas drawings were static. Simply enter an x and y coordinate, and you're done! Now how can we animate them? By incrementing and decrementing every time the loop is ready.

Play with the values below. Game objects will be in the next chapter, so don't worry about this syntax! It's better to look at the JS file for the loop code.

Challenges:

  • Make the object move backwards.
  • Make it only show a border on the player (see previous chapter).
  • Constraint its movement to inside the canvas only (you will need to use x, y, width, and height values for this).
  • Make it bounce if it hits the border (same as above; mix the constraint and backwards movement).
  • Make it move in a circle or ellipse (trigonometry; you might need to add a variable or two to the object).
  • Make two squares show up on screen and update.

This was more of an explanation than a hands-on show-how, but looking at the JS file should be a whole lot easier to decipher now.

What if we want hundreds of objects? It's not fun to keep typing the same thing over and over!

Next chapter

In the next chapter, we will make this easier with objects and classes, and introduce the initialization of objects. See you soon.