Back

Game Loops

Reading

Refresher

Processing will "try" and execute everything in the draw loop at 60 frames per second (fps). Certain code will impact performance and of course there should be 0 redundant code.

Redundant code includes: repeated statements or statements that have no effect.

Another form of redundant code is unreachable code, this simply adds to your programs files size, which is important when your program is delivered online.

Performance Bottlenecks

  • Excessive draw calls
  • Complex shapes
  • Large images
  • Redundant / repeated loops
  • Redoing heavy calculations (dist, abs)
  • Redundant code

Tips for Improvement

  • Don't draw what cannot be seen (clipping)
  • Simplify your shapes
  • Store heavy calculations temporarily (in a class or in the game loop)
  • Break up large images into smaller pieces (background: tiles, mountains, trees, clouds)

Game Loops

A game loop describes your main draw loop. This is where all objects in your game will be updated, and sometimes created and destroyed. There's some logic that doesn't belong in your game loop, most often specific adjustments to several fields of an object. This logic should be contained within the class of that object, in a method.

We'll take a look at a good game loop and a bad game loop.

A Good Game Loop

A Bad Game Loop

Discussion

As you can see the second loop is a lot messier. If we're having trouble coding our sketch it will be hard to find the specific statements in even a slightly more complicated program than this.

By calling methods you will know exactly which part of your code to focus on when behavior is not as desired.

Never repeat code. Put it in a class. If it's shared, make it a superclass.

Performance

An additional benefit of calling methods from your game loop instead of writing logic statements is performance. In order to determine bottlenecks (slow parts) you can simply comment out method calls to identify what is taking the most time.

Performance Testing

Take a look at the following code for a performance testing metric you can use in your code.

Never put statements in your game loop that belong in a method of a class.
Never (as much as you can) access fields from outside a class.
Never repeat code. Put it in a class. If it's shared, make it a superclass.
Test test test to find bottlenecks.

Timers

The fireTimer

The fireTime variable is an integer stored in the player class to limit the rate of firing Missiles. Remember the draw loop executes at 60fps so if the UP key is held down, the player would fire (or try to) 60 missiles per second.

This is often undesirable, so we'll only let the player fire when the fireTimer variable == 0 and every time it is we'll reset the fireTimer variable to the delay we'd like to see in between Missile firings.

The Missile Life

The Missiles class contains a field for life, this is how we will keep track of how long the missile is "alive" and when it should explode or be removed from the ArrayList it belongs to.

In the Missile update method life is decreased and when it reaches 0, the missile creates and stores a number of explosion objects which it will then update.

Finally the missile class checks to see if all the explosions are removed from the ArrayList of explosions, if this is the case the missile will remove itself from the list it belongs to and cease to be a part of our program.

The Explosion Life

Explosion life is similar to missile life, when it hits zero or is below zero (it often doesn't matter) we will remove the explosion from the ArrayList it belongs to.

Looking back at the Missile class we see that once all explosions are removed, we remove the instance of the missile class in order to eliminate it from our sketch.

Every object should manage it's own timer / lifespan / animation.
Each object should store a reference to the list it belongs to in order to be able to remove itself later.
Objects should take care of their own logic, including: updating, life, timers, removal... This is IMPORTANT!