Skip to content

Game

Game creates the services shared by every state and runs the browser animation loop. It owns the canvas dependencies, assets, input, animation helpers, and state machine so states can receive one consistent services object.

Create the game with a Canvas and the asset definitions it should load. Register and select a state before starting the loop.

const game = new Game(
canvas,
fontDefinitions,
imageDefinitions,
soundDefinitions
);
game.addState('home', HomeState);
game.services.stateMachine.change('home');
game.start();

The constructor creates these objects once and exposes them through game.services. States receive the same object through their State constructor.

flowchart TD
	Game --> Services["GameServices"]
	Services --> Drawing["canvas and context"]
	Services --> Input["input"]
	Services --> Effects["particles and timer"]
	Services --> Assets["fonts, images, and sounds"]
	Services --> Navigation["stateMachine"]
	Services --> State["State constructor"]
Role Services Purpose
Drawing canvas, context The canvas wrapper and its CanvasRenderingContext2D.
Input input Keyboard and pointer input.
Effects particles, timer Particle updates and scheduled work or tweens.
Assets fonts, images, sounds Loaded font, image, and sound resources.
Navigation stateMachine Registration, selection, update, and rendering of states.

new Game(canvas, fontDefinitions, imageDefinitions, soundDefinitions, options)

Section titled “new Game(canvas, fontDefinitions, imageDefinitions, soundDefinitions, options)”
new Game(canvas, fontDefinitions, imageDefinitions, soundDefinitions, options);

Creates the shared services and loads the supplied assets.

Parameter Type Description
canvas Canvas Canvas wrapper that supplies the element, drawing context, width, and height.
fontDefinitions readonly FontDefinition[] Font assets to load.
imageDefinitions readonly ImageDefinition[] Image assets to load.
soundDefinitions readonly SoundDefinition[] Sound assets to load.
options GameOptions (optional) Optional advanced configuration. Most code can omit it.

Asset-definition arrays are read-only inputs: Game loads them into its asset services; it does not mutate the arrays.

game.addState('settings', SettingsState);

Constructs and registers a state under name. Pass the state class, not an instance. Game supplies its shared services object to the state constructor.

class SettingsState extends State {
render(context) {
context.fillText('Settings', 24, 24);
}
}
game.addState('settings', SettingsState);
game.services.stateMachine.change('settings');

State names are strings used later with stateMachine.change(name, props). Use stable, descriptive names such as "home", "settings", or "dialog".

game.start();

Starts the browser animation loop. It immediately runs the first frame and schedules later frames with requestAnimationFrame().

game.update(dt);

Advances the application by dt seconds. In normal use, gameLoop() calls this for every animation frame.

The update order is:

  1. stateMachine.update(dt) lets the active state make decisions.
  2. particles.update(dt) advances particle effects.
  3. timer.update(dt) advances scheduled actions and tweens.
game.render(context);

Clears the canvas and then draws the active state followed by particles. In normal use, gameLoop() calls this after update().

flowchart
	A["requestAnimationFrame timestamp in milliseconds"] --> B["Convert elapsed time to dt seconds"]
	B --> C["Game.update(dt)"]
	C --> D["StateMachine.update(dt)"]
	D --> E["ParticleSystem.update(dt)"]
	E --> F["Timer.update(dt)"]
	F --> G["Game.render(context)"]
	G --> H["Clear canvas"]
	H --> I["StateMachine.render(context)"]
	I --> J["ParticleSystem.render(context)"]
	J --> A

The method is annotated like this:

/**
* @param {string} name
* @param {new (services: GameServices) => State<unknown>} StateType
*/
addState(name, StateType) {}

Read the second parameter from left to right:

Syntax Meaning
new (services: GameServices) => ... A class constructor that can be called with new and receives the shared services object.
State<unknown> The constructor produces a State; its transition-props shape may differ from other registered states.
StateType The parameter is the class itself, such as SettingsState, not new SettingsState(...).

unknown is necessary because one game can register states with different props types. See State for props generics and State Machine for how states are handled.

gameLoop() is a private implementation method. start() invokes it, so application code should not call it directly.

The browser passes requestAnimationFrame() a timestamp in milliseconds. Game subtracts the previous timestamp and divides by 1000, producing the seconds-based dt used by updates and timers. It then updates, renders, saves the timestamp, and schedules the next frame.