Skip to content

A template repository to kick start modern game development on the web built using HTML5 Canvas, TypeScript & Webpack.

License

Notifications You must be signed in to change notification settings

brookesb91/state-driven-game-template

Repository files navigation

πŸ•ΉοΈ State Driven Game Development Starter

A template repository to kick start modern game development on the web.

HTML5 TypeScript NodeJS Express.js Webpack Progressive Web App



πŸš€ Quick Start

πŸ›‘ Prerequisites

  • node >= 14
  • npm >= 6

πŸ–₯️ Local Development

Install dependencies.

npm i

Start the development server.

npm run start

See your game by opening your browser at localhost:5000.

Example screen

Changes made to the source files will trigger a recompilation. Refresh the browser to see the changes.

πŸ› οΈ Building

Building the project.

npm run build

The output will be located at /dist.


πŸ“š Project Structure

dist                          [Build output]
src                           [Source root]
  /assets                     [Web assets]
  /icons                      [Web icons]
  /lib                        [Game libraries]
    /core                     [Core libraries - @core]
    /models                   [Game models - @models]
    /sprites                  [Sprite definitions - @sprites]
    /state                    [State definitions - @state]
    /utils                    [Utility libraries - @utils]
    /game.ts                  [Game entry point - @game]
  /index.html                 [Web index page]
  /main.ts                    [App entry point]
  /manifest.webmanifest       [PWA manifest]
  /service-worker.js          [PWA service worker]
dev-server.js                 [Development express server]
tsconfig.json                 [TypeScript configuration]
tslint.json                   [tslint configuration]
webpack.config.js             [Webpack configuration]

🧩 Game States

Game states provide frame by frame functionality for your game.

Creating States

import { OnEnter, OnExit, OnRender, OnUpdate } from '@core';

export class MyGameState implements OnEnter, OnExit, OnRender, OnUpdate {
  enter(): void {
    console.log('Pushed to the stack!');
  }

  exit(): void {
    console.log('Popped from the stack!');
  }

  render(ctx: CanvasRenderingContext2D): void {
    console.log('Rendering frame!');
  }

  update({ time, delta }): void {
    console.log('Updating frame!');
  }
}

Using States

To advance your game to the next state, simply push an instance of your state to the game stack.

import { push } from '@core';

// Push a new state to the stack
push(new MyGameState());

States can also be popped from the stack as long as it has states to pop.

import { pop } from '@core';

// Remove top-most state
pop();

πŸ‘Ύ Sprites

Sprites are objects that render an image on a HTMLCanvasContext2D.

A sprite can be created in the following way.

import { Sprite } from '@core';

// Create and load the image to be rendered.
const image = new Image();
image.src = 'path/to/image.png';

// Create a sprite using the image and parameters.
const sprite = new Sprite(image, {
  // Source width
  w: 16,
  // Source height
  h: 16,
  // Origin x position
  ox: 0,
  // Origin y position
  oy: 0,
});

The sprite can be rendered to a canvas context.

sprite.render(ctx, {
  // Rendering x position
  x: 100,
  // Rendering y position
  y: 50,
});

Optionally, the sprite can be scaled in both directions.

sprite.render(ctx, {
  x: 100,
  y: 50,
  // Scale the sprite by 3
  scaleX: 3,
  scaleY: 3,
});

Sprite Sheets

A SpriteSheet is used to define multiple Sprite objects from a single image.

A SpriteSheet is defined as follows.

const sprites = new SpriteSheet('/path/to/image.png');

Define sprites directly on the sprite sheet to build multiple sprites from the same image.

sprites
  .define('idle_1', { w: 16, h: 16, ox: 0, oy: 0 })
  .define('idle_2', { w: 16, h: 16, ox: 16, oy: 16 });

Sprites can then be retrieved from the sprite sheet.

/**
 * Note that, the `.get` method can return undefined.
 * Accommodate for this by optionally calling render
 * when doing so.
 *
 * `sprite?.render(ctx, config)`
 * */
const sprite = sprites.get('idle_1');

πŸ’‘ Example Projects