Excalibur v0.25.2 Released!

Published on Saturday, January 22nd, 2022

Excalibur Text Logo

After the winter break, the team has put out a new release of [email protected] with a lot of improvements to the core engine and plugins! Check the roadmap for our current plans.

Check out the new version on npm!

> npm install [email protected]

"Winter holiday, when developers work on their side projects" - Anonymous Coworker

Dev Tools

> npm install @excaliburjs/dev-tools

We've built a brand new tool to help debug Excalibur games! Check it out!. This tool lets you see information about the the Excalibur engine, scenes, actors, clocks, and more!

Debugging why things aren't working has historically been pretty difficult. This plugin will greatly assist in the game development cycle. Nearly everything is available and configurable.

It's pretty low effort to install into your game:

import { DevTool } from '@excaliburjs/dev-tools';

const game = new ex.Engine({...});
const devtool = new DevTool(game);

Dev Tools Screenshot

Tiled Updates

> npm install @excaliburjs/plugin-tiled

The Tiled plugin now implicitly adds a z-index to each layer (which can be overridden) which means things will look as you expect in Excalibur as they do in the Tiled editor.

Set the starting layer z (defaults to -1) and get gaming!

const map = new TiledMapResource('path/to/map.tmx', { firstLayerZIndex: -2 });

Renderer Performance Improvements

The performance gains were achieved through some core renderer refactors and identifying places where expensive calculations could be cached!

This is huge, we stay above 30fps in the 4000 actor benchmark, and we have dramatic improvement in average fps in both cases!

Excalibur benchmark

This benchmark was performed on my Surface Book 2 with the power plugged in, in Chrome.

A number of improvements were made to Excalibur in the graphics systems to get to this performance. The big factors to this improvement were:

  1. Avoiding recalculation of graphics transforms and other expensive operations when they can be cached
  2. Refactoring the renderer to be simpler and to use index buffers to share geometry vertices.
  3. Rendering batches at the actual maximum for the batch renderer
  4. Avoid recreating Matrix types, they are somewhat expensive to create then garbage collect

Post Processing

The postprocessor improvements allow custom WebGL shaders, this can produce some cool effects! (Minimally modified from this ShaderToy)

Excalibur example running with CRT television postprocessor

To produce the above effect Excalibur has a new built in ScreenShader type for doing quick shaders meant for the whole screen.

class CrtPostProcessor implements ex.PostProcessor {
private _shader: ex.ScreenShader;
initialize(gl: WebGLRenderingContext): void {
const crtEffectSource = document.getElementById("modified-crt-shader-source").innerText;
this._shader = new ex.ScreenShader(crtEffectSource);

getLayout(): ex.VertexLayout {
return this._shader.getLayout();

getShader(): ex.Shader {
return this._shader.getShader();

game.graphicsContext.addPostProcessor(new CrtPostProcessor());

Renderer Improvements

Renderer Design

When v0.25.0 was released, it was a "monolithic" renderer design, meaning everything Excalibur could possibly draw was built into a single renderer and shader program. This became fairly onerous fairly quickly. And as the old adage goes "you don't know how to build something until you've built it twice"

With v0.25.2 each type of drawing is split internally into separate renderer plugins, while this does come with some overhead when switching shader programs, the simplicity, maintainability, and extensibility benefits are a boon.

Image Filtering

Excalibur now allows you the ability to control the WebGL image filtering mode both implicitly and explicitly. Really this means Excalibur will try to pick a smart default, but allows overrides

Explicitly when loading ex.ImageSource:

const myImage = new ex.ImageSource('path/to/image', false, ex.ImageFiltering.Pixel);

Implicitly if the ex.EngineOption antialiasing property is set:

Custom Renderer Plugins

Excalibur knows how to draw many types graphics to the screen by default comes with those pre-installed into the ExcaliburGraphicsContext. However, you may have a unique requirement to provide custom WebGL commands into Excalibur, this can be done with a custom renderer plugin.

A custom renderer can be registered with Excalibur and draw in any draw routine! Read more in the docs

const game = new ex.Engine({...});

export class MyCustomRenderer extends ex.RendererPlugin {
public readonly type = 'myrenderer';

game.start().then(() => {
// register
game.graphicsContext.register(new MyCustomRenderer());

// call from a graphics callback or event
const actor = new ex.Actor({...});
actor.graphics.onPostDraw = (graphicsContext) => {
graphicsContext.draw<MyCustomRenderer>('myrenderer', ...);


We've had a lot of community engagement this iteration, especially through the issues and github discussions. Lots of good issues, and lots of cool things in the show and tell

Big thanks to everyone: @ivasilov @luttje @tsanyqudsi @lampewebdev @joshuadoan @berkayyildiz @simon-jaeger @YJDoc2 @JumpLink

The Future

We are progressing at full speed toward the v1 vision, there is still a lot to do but the end is in sight. Here are a few things that I'm personally really excited for:

This was a point release, but despite that a lot of exciting things were added! Looking forward to v0.26.0!


Help support me on Github Sponsors or Patreon

Become a Patron!