Skip to content

Latest commit

 

History

History
189 lines (146 loc) · 7.78 KB

README.md

File metadata and controls

189 lines (146 loc) · 7.78 KB
Unrail Engine logo

Unrail Engine

npm version npm downloads

Unrail Engine is a modern and lightweight 2D game engine written in Typescript during a train ride.

This engine is not only for games, its modules can be used independently. For instance, the render module and the interface one can be used for an animated project.

The renderer is based on the OffscreenCanvas API (currently not supported by Safari & Firefox). The render process is done in a DedicatedWorker which threads the process and speed up the operation ands adapts to the devicePixelRatio.

Examples can be found at /test.
The engine is written using test driven development. Currently there is no test automatisation but the aim is to develop E2E efficient tests.

I - Getting Started
II - Documentation
III - Examples

Getting Started

Installation

Via <script>

To import the engine, you can include the script in your index.html file :

<!-- Production minified ~10kB gzipped -->
<script type="module" src="./unrail-engine.es.js" defer></script> 

Then import it like a regular moduel in your .js file :

import { /* Stuff you need */ } from './unrail-engine/dist/unrail-engine.es.js'

Via NPM:

npm i --save unrail-engine

and import it as an ES module : (the types are included in the package)

import { /* Stuff you need */ } from 'unrail-engine'

Starting a game

The UnrailEngine entry point is the Game object. With this object, all the modules will be instantiated and will work properly. All the objects have to be imported first.

import { Game } from 'unrail-engine'

let game = new Game('Game name')

Then you can register a main loop which will be called the right amout of time to respecct the fps limitation (which can be set by the game.setFPS(fpsNumber) method - default is 60fps)

function update(deltaTime) {
    // Do the update & render job here
}

game.setMainLoop(update)

Then just call game.start() and there you go.

Documentation

The full documentation is available here.

All the entities are built around two methods : update and render. The update method is used to handle the logic of the entity and the render method aims at doing the rendering job and should only use the Renderer static methods.

// main.ts
const { width, height } = getWindowDimensions() 
const env = new Env(width, height) // Create an environment for the game
const game = new Game('Game Name', env)

game.setMainLoop(() => env.update()) // register a main loop
game.start()

Event System

The event system is usefull to communicate between differente classes or objects.
Native events are handled by the system.
The keydown management ideo comes from keydrown and eliminate the delay when long pressing a key.

import { Event } from 'unrail-engine'

// Key Events
Event.onKeyDown('ArrowLeft', e => callback(e)) // While key is down
Event.onKeyPressed('<keyCode>', e => callback(e)) // Fired once

// Custom Events
Event.emit('custom-event-name', params)
Event.on('custom-event-name', callback)

Renderer

The UnrailEngine currently supports 2 render methods : (WebGL rendering is planned)

  • The Renderer object is a classic optimized canvas 2D renderer.
  • The OffscreenRenderer uses the OffscreenCanvas API and web worker to run in a different thread.
    Both renderer uses the same methods name so switching from one to another is as simple as replacing an import alias.
// Choose one or another
import { Renderer } from 'unrail-engine'                      // to use the regular renderer
import { OffscreenRenderer as Renderer } from 'unrail-engine' // to use the multithreaded renderer for better performances
// Canvas2DContext options from : https://developer.mozilla.org/fr/docs/Web/API/CanvasRenderingContext2D
let style: StyleObject = { 
    color?: string, // shorthand for fillStyle & strokeStyle - only non-standard attribute
    strokeStyle?: string,
    lineWidth?: number,
    lineJoin?: CanvasLineJoin,
    fillStyle?: string,
    globalAlpha?: number,
    globalCompositeOperation?: string
}

// Create a canvas & init the Renderer
Renderer.create()               // To create a canvas with the dimension of the window
Renderer.create(width, height)  // To create a canvas with custom dimensions
Renderer.createFromCanvas('#canvas')  // To create a Renderer from an existing canvas

// Renderer is a static class. Here are the different methods
Renderer.clear()
Renderer.rect(x, y, width, height, style?)
Renderer.line(x1, y1, x2, y2, style?)
Renderer.poly(pointArray, style?)
Renderer.circle(x, y, radius, style?)
Renderer.point(x, y, style?)
Renderer.rectSprite(x, y, width, height, texture)
Renderer.circleSprite(x, y, radius, texture)
Renderer.tint(color, x, y, width, height)      // tint a rect width a color

Interface

import { Interface } from 'unrail-engine'

let value = 'some value'

Interface.addItem(() => `Value : ${value}`, position, { CSSproperties })
// position is a string : 'top-left', 'top-right', 'bottom-left', 'bottom-right' or 'custom'
// CSSproperties is an object containing { css-attribute: value }

// Example :
Interface.addItem(() => `Iteration : ${i++}`, 'top-left', { color: '#999' })

Animation

The Unrail Engine comes with a built-in animation system. To use it, simply declare a new Animation :

import { Easing } from 'unrail-engine'
const options = { autostart?: true, loop?: false }
const animation = new Animation(from, to, duration, Easing.linear, options) // duration in ms
Event.onClick(() => animation.start())

The value of the animation is accessible via the property : animation.value.

The default easing function is linear, but others are available in the Easing object. To specify an easing function, you can pass the function in the animation constructor or simply its name if the fonction belong to the Easing object.

The available methods of the animation class are :

  • .start() to begin the animation
  • .pause() to stop the animation
  • .resume() to resume the animation
  • .reset() to reset the animation to its initial state
  • .toggle() to toggle the animation state (pause if the state is play and the inverse)
  • .isRunning returns true if the animation is running, else false

Examples


2021 © Dorian Beauchesne