Search⌘ K
AI Features

Managing Game State

Explore managing game state in reactive game development with RxJS. Understand how to update and render game content smoothly at 60 frames per second while keeping state changes isolated. Learn techniques to handle multiple moving objects like stars efficiently, balancing purity and performance for consistent gameplay.

Updating game state

Keeping a game’s state in sync with the variety of different events that can happen at any point in the game is quite the challenge. Add the requirement that it all needs to render smoothly at sixty frames per second, and life gets very difficult.

Let’s take a few lessons from the ngrx section in Advanced Angular and add in a canvas flavor to ensure a consistent gameplay experience.

Game state

The initial game state could be seen in gameState.ts where we’re using a class so that resetting the game state is as easy as new GameState().

TypeScript 3.3.4
import { fromEvent } from 'rxjs';
import { config } from './config';
import { randInt } from './util';
// Keep track of the state of all movement keys
let keyStatus = {};
fromEvent(document, 'keydown')
.subscribe((e: any) => {
keyStatus[e.keyCode] = true;
});
fromEvent(document, 'keyup')
.subscribe((e: any) => {
keyStatus[e.keyCode] = false;
});
export class GameState {
stars: {
x: number;
y: number;
dy: number;
size: number;
}[] = [];
player = {
x: config.canvas.height - (config.ship.height * 2),
y: (config.canvas.width / 2) - (config.ship.width / 2),
alive: true,
lasers: [{
x: config.canvas.width / 2,
y: -1000
}, {
x: config.canvas.width / 2,
y: -1000
}, {
x: config.canvas.width / 2,
y: -1000
}]
};
keyStatus: { [status: number]: boolean };
enemy = {
x: -1000,
y: 0,
dx: 0,
dy: 0,
alive: true,
lasers: [{
x: config.canvas.width / 2,
y: 10000
}, {
x: config.canvas.width / 2,
y: 10000
}, {
x: config.canvas.width / 2,
y: 10000
}]
};
explosions: {
x: number;
y: number;
framesSince: number;
type: string;
}[] = [{
x: -1000,
y: -1000,
framesSince: 1000,
type: ''
}, {
x: -1000,
y: -1000,
framesSince: 1000,
type: ''
}, {
x: -1000,
y: -1000,
framesSince: 1000,
type: ''
}];
constructor() {
for (let i = 0; i < 100; i++) {
this.stars.push({
x: randInt(0, config.canvas.width),
y: randInt(0, config.canvas.height),
dy: Math.random() * 10,
size: randInt(-3, 1)
});
}
this.keyStatus = keyStatus;
}
}

Like ...