simple-gameloop
TypeScript icon, indicating that this package has built-in type declarations

3.1.0 • Public • Published

Simple Gameloop

A small library for running code with separated update and render functions with RequestAnimationFrame. The Update function can be paused, resumed, or run at customisable rates by passing in a number to multiply the RAF delta by (slow-motion, double speed etc.).

Principles

Separation of Concerns

This library exposes separate update and render functions to encourage separation of game state logic and rendering logic. Where entities in your animation or game are and how they are rendered are separate concerns, so by separating the code into different functions we can avoid coupling them unnecessarily.

Framerate-independent State Updates

The update function is called from inside requestAnimationFrame, but we do not want the update rate to be tied to the render rate. An animation should run at the same rate whether viewed on a 30hz monitor or a 244hz monitor.

To ensure consistent animation regardless of render speed the update function is passed a dt parameter that represents the time in seconds since the last time the update function was called. Any calculations that result in something moving should be multiplied by this value to guarantee that it will move that far per second.

Let's say you want a square to move right at 100 pixels per second. If you assume 60fps you divide 1000 by 60 to get 16.6, so you write

function update() {
  box.x += 16.6;
}

On a computer with a 60hz monitor you'll see the behaviour you're expecting, maybe with a little hitching but eh that's fine. Then you view it on a 144hz monitor and your square has gone zooming off the screen because it's add 16. 6 pixels to it 144 times a second instead of 60.

So what you do instead is you define all of your units in units per second and multiply that by the time since the last update!

function update(deltaTime) {
  box.x += 100 * deltaTime;
}

On a 60hz monitor deltaTime will be 0.166 and 100 * 0.166 = 16.6 pixels per update. On a 144hz monitor deltaTime will be 0.024, bringing us 2.4 pixels per update.

The delta time is calculated every frame so if your browser runs one frame slower than the others for whatever reason the dt will change appropriately and everything should remain consistent. This also holds for the browser being unable to keep up with the max refresh rate - if you create 1,000,000 boxes your animation will likely run at far fewer frames per second but the box movement will continue at the same rate.

To Use

import * as simpleGameloop from 'simple-gameloop';

/**
 * @param dt - time in seconds since last call to update function
 */
const update = function update(dt) {
  // your update logic here
};

const render = function render() {
  // your render logic here
};

const gameLoop: GameLoop = simpleGameloop.createLoop({
  update,
  render,
});

createLoop returns an object with the following functions:

  • pause() - blocks the update function
  • play() - unblocks the update function
  • destroy() - cancels the current animation frame, halting playback completely
  • setSpeed(number) - speed up or slow down the update call by multiplying the delta by the given number

Create Canvas

There is also a helper function for creating a canvas element of a given size.

const canvasObject = simpleGameloop.createCanvas({
    containerSelector: '.canvasContainer',
    classes: 'canvas other-class',
    width: 500,
    height: 500,
});

This will create a 500x500 canvas inside the .canvasContainer element with the classes canvas and other-class.

canvasObject contains references to:

  • canvas the canvas element
  • context the canvas context (e.g. canvas.getContext('2d')).

Demo

There is a demo that you can run with npm run example.

Future

Fixed-rate Updates

If you want your simulation to be deterministic then you want a fixed update rate. This can be done by tracking how much time has progressed and calling update when X time has passed, passing X in as the delta.

Package Sidebar

Install

npm i simple-gameloop

Weekly Downloads

11

Version

3.1.0

License

MIT

Unpacked Size

88 kB

Total Files

34

Last publish

Collaborators

  • terrarum