Writing a game loop

In game apps, the refresh rate of the screen is vital; it must be high enough to ensure agreeable and realistic gameplay. Refreshing means periodically redrawing the screen. This recipe shows you how to build that in your app. It is illustrated in the code of gameloop, a simple version of the well-known memory game that uses the boarding package by Dzenan Ridzanovic. The goal is to click quickly enough to get identical pairs of the colored squares. Start it by running game.html (don't use pub serve for the launch, select Run and then Manage Launches, and in Pub Settings, uncheck use pub serve to serve the application).

How to do it...

  1. The game starts off in main() of game.dart (only the relevant parts of the code are shown here):
    import'dart:async';
    import'dart:html';
    // ... other code
    part'model/memory.dart';
    part'view/board.dart';
    
    main() {
      new Board(new Memory(4), querySelector('#canvas')).draw();
    }
  2. In the constructor of the Board class, the game loop is started with the call to window.animationFrame:
      class Board extends Surface {
        // code left out
        
        Board(Memory memory, CanvasElement canvas) : this.memory = memory,
        super(memory, canvas) {
          // code left out
          querySelector('#canvas').onMouseDown.listen((MouseEvent e) {
          // code left out
          if (memory.recalled) { // game over
          new Timer(const Duration(milliseconds: 5000), ()         =>memory.hide());
        }
      else if (cell.twin.hidden) {
      new Timer(const Duration(milliseconds: 800), () =>cell.hidden = true);
      }
    });
    
    window.animationFrame.then(gameLoop);
    }
  3. And here is the gameloop method itself:
    voidgameLoop(num delta) {
      draw();
      window.animationFrame.then(gameLoop);
    }
    
    void draw() {
      super.draw();
      if (memory.recalled) { // game over
      // code left out
      }
    }

How it works...

In step 1, the game is started by instantiating an object of the Board class (from view/board.dart) and calling the draw method on it. In step 2, the most important statement is the last one in the constructor, window.animationFrame.then(gameLoop);.

This method of the Window class in dart:html returns a Future that completes just before the window is about to repaint, so this is the right time to redraw our screen.

Tip

Use animationFrame to do this, because the animation then uses a consistent frame rate, and thus, looks smoother, and it also works at the screen's refresh rate. Don't use Future or Timer to draw frames; use Timer only if you have to code for a browser that does not support animationFrame!

This is done in the callback method gameloop in step 3; first draw() is executed, then window.animationFrame, and then (gameLoop). So, this recursively calls gameloop again and again. This way, we are sure that the animation will continue.

There's more...

We also see how the class Timer from dart:async is used. For example, in the end-of-game condition (memory is recalled), the colored pattern is hidden from sight after 5 seconds by the following Timer object:

new Timer(const Duration(milliseconds: 5000), () =>memory.hide());

After this duration of time, the anonymous callback function,() =>memory.hide(), is executed. Use the named constructor, Timer.periodic, with the same arguments to execute a callback function periodically.

See also

  • Refer to the Running a recurring function recipe in this chapter to find out more about the Timer class
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset