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).
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(); }
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); }
gameloop
method itself:voidgameLoop(num delta) { draw(); window.animationFrame.then(gameLoop); } void draw() { super.draw(); if (memory.recalled) { // game over // code left out } }
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.
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.
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.