Excalibur, the popular open-source 2D game engine for TypeScript, has unveiled its latest release: version 0.30.0. This update is packed with powerful new features, performance enhancements, and critical bug fixes that significantly elevate the game development experience. With advanced GPU particle rendering capabilities and more interactive tile maps, this release aims to deliver a richer, more flexible toolkit for developers looking to build engaging, visually striking games.

New Features
Advanced GPU Particle Implementation
Excalibur now boasts a GPU-accelerated particle system capable of handling 10,000+ particles. This enhancement allows for highly detailed and dynamic visual effects without compromising performance.
const particles = new ex.GpuParticleEmitter({
pos: ex.vec(300, 500),
maxParticles: 10_000,
emitRate: 1000,
radius: 100,
emitterType: ex.EmitterType.Circle,
particle: {
beginColor: ex.Color.Orange,
endColor: ex.Color.Purple,
focus: ex.vec(0, -400),
focusAccel: 1000,
startSize: 100,
endSize: 0,
life: 3000,
minSpeed: -100,
maxSpeed: 100,
angularVelocity: 2,
randomRotation: true,
transform: ex.ParticleTransform.Local
}
});
Enhanced Sprite Management
- SpriteSheet Tiling: Utilize
ex.SpriteSheet.getTiledSprite(...)to effortlessly extract tiling sprites from a sprite sheet. - Alias for Screen Dimensions: Access
engine.screen.widthandengine.screen.heightas aliases forengine.screen.drawWidthandengine.screen.drawHeight.
Convenience Types for Tiling Sprites and Animations
Excalibur introduces ex.TiledSprite and ex.TiledAnimation to simplify the integration of tiled graphics and animations.
const tiledGroundSprite = new ex.TiledSprite({
image: groundImage,
width: game.screen.width,
height: 200,
wrapping: {
x: ex.ImageWrapping.Repeat,
y: ex.ImageWrapping.Clamp
}
});
const tilingAnimation = new ex.TiledAnimation({
animation: cardAnimation,
sourceView: { x: 20, y: 20 },
width: 200,
height: 200,
wrapping: ex.ImageWrapping.Repeat
});
SVG Image Support
Manage vector graphics more efficiently with inline SVG support via ex.ImageSource.fromSvgString('<svg>...</svg>'). This feature ensures crisp scaling and a reduced asset footprint.
const svgImage = ex.ImageSource.fromSvgString('<svg>...</svg>');
Scene Transitions with Slide Effect
Introduce smooth and dynamic scene transitions using the new ex.Slide transition. Scenes can elegantly slide in from any direction, enhancing the narrative flow.
game.goToScene('otherScene', {
destinationIn: new ex.Slide({
duration: 1000,
easingFunction: ex.EasingFunctions.EaseInOutCubic,
slideDirection: 'up'
})
});
Nine-Slice Graphics for Responsive UI
Create scalable and responsive UI elements effortlessly with ex.NineSlice, perfect for menus, panels, and HUD components.
const nineSlice = new ex.NineSlice({
width: 300,
height: 100,
source: inputTile,
sourceConfig: {
width: 64,
height: 64,
topMargin: 5,
leftMargin: 7,
bottomMargin: 5,
rightMargin: 7
},
destinationConfig: {
drawCenter: true,
horizontalStretch: ex.NineSliceStretch.Stretch,
verticalStretch: ex.NineSliceStretch.Stretch
}
});
actor.graphics.add(nineSlice);
Enhanced Action System
- New Actions:
actor.actions.curveTo(...)andactor.actions.curveBy(...)enable curved motion paths for more natural and complex movements. - Flash Action:
actor.actions.flash(...)allows actors to flash a color for a specified duration, useful for visual feedback.
player.actions.rotateTo({ angleRadians: angle, duration: 1000, rotationType });
player.actions.moveTo({ pos: ex.vec(100, 100), duration: 1000 });
player.actions.scaleTo({ scale: ex.vec(2, 2), duration: 1000 });
player.actions.repeatForever(ctx => {
ctx.curveTo({
controlPoints: [cp1, cp2, dest],
duration: 5000,
mode: 'uniform'
});
ctx.curveTo({
controlPoints: [cp2, cp1, start1],
duration: 5000,
mode: 'uniform'
});
});
Mathematical Utilities
New utility functions for numerical and vector operations enhance the precision and flexibility of game mechanics:
ex.lerpAngle(...)ex.lerp(...),ex.inverseLerp(...),ex.remap(...)ex.lerpVector(...),ex.inverseLerpVector(...),ex.remapVector(...)
Interactive Tile Maps
ex.TileMap and ex.IsometricMap now support pointerenter and pointerleave events, enabling more interactive and responsive game worlds.
Bezier Curve Support
Introducing ex.BezierCurve for drawing cubic bezier curves, allowing for more sophisticated graphic designs and animations.
Graphics Enhancements
- Force On Screen:
ex.GraphicsComponent.forceOnScreenensures certain graphics remain visible within the viewport. - Inline Canvas Image Creation:
ex.ImageSource.fromHtmlCanvasElement(...)allows creating images directly from HTML canvas elements.
Developer Tools
- Assertion Utility:
ex.assert()can be used to enforce conditions during development, aiding in debugging and maintaining code integrity. - Improved Coroutine Management: Enhanced coroutine support with
ex.coroutine(...), allowing for better control over asynchronous operations, including nested coroutines and manual start/cancel options.
TypeScript Enhancements
- TypeScript Strictness: Increased TypeScript strictness across various APIs ensures better type safety and developer experience.
Improvements
Action System Enhancements
- Precise Timing: Actions now accept durations in milliseconds, allowing for more accurate timing and synchronization.
- Easing Options: Added easing functions to actions like
moveTo(...)for smoother transitions.
player.actions.rotateTo({ angleRadians: angle, duration: 1000, rotationType });
player.actions.moveTo({ pos: ex.vec(100, 100), duration: 1000 });
player.actions.scaleTo({ scale: ex.vec(2, 2), duration: 1000 });
Angle Interpolation
The new ex.lerpAngle function facilitates smooth transitions between angles, enhancing rotational animations and directional changes.
Debugging Tools
- Refined Debug Methods: New
ex.Debugstatic methods provide enhanced capabilities for visualizing and diagnosing game elements, such as collision boxes and layout constraints.
Performance Optimizations
- WebGL Texture Management: Excalibur now automatically cleans up unused WebGL textures, improving memory usage and stability during long game sessions.
- Image Rendering: Upgraded to
ImageRendererV2, doubling the performance of image rendering tasks. - Component Retrieval: Enhanced
ex.Entity.get()method significantly boosts engine performance by optimizing component access. - Collision Processing: Introduction of
ex.SparseHashGridCollisionProcessoroffers a faster, more efficient collision pair generation mechanism. - Pointer System: Improved
PointerSystemusing a new spatial hash grid data structure enhances pointer event processing speed. - General Allocations Reduction: Numerous optimizations reduce memory allocations in hot paths, such as state/transform stacks and collision calculations, leading to smoother performance.
Coroutine Enhancements
- Coroutine Instances:
ex.CoroutineInstanceprovides better control and management of coroutine lifecycles. - Autostart Control: Option to disable autostart for coroutines, allowing manual initiation and cancellation.
- Nested Coroutines: Support for nested coroutines enables more complex asynchronous workflows.
API Enhancements
- World to Page Pixel Ratio:
ex.Screen.worldToPagePixelRatioAPI returns the ratio between Excalibur pixels and HTML pixels, facilitating seamless scaling of HTML UIs to match game dimensions.
.ui-container {
pointer-events: none;
position: absolute;
transform-origin: 0 0;
transform: scale(
calc(var(--ex-pixel-ratio)),
calc(var(--ex-pixel-ratio))
);
}
Additional Utilities
- RentalPool: A new
RentalPooltype for efficient sparse object pooling. - Vector Utilities:
Vector.angleBetween(...)method added to calculate angles between vectors, aiding in directional calculations and rotations.
const point = ex.vec(100, 100);
const destinationDirection = Math.PI / 4;
const angleToRotate = point.angleBetween(destinationDirection, RotationType.ShortestPath);
expect(point.rotate(angleToRotate).toAngle()).toEqual(destinationDirection);
Bug Fixes
Excalibur v0.30.0 addresses numerous bugs to enhance stability and reliability:
- Particle Emitter: Fixed
ex.ParticleEmitter.clearParticles()to function correctly. - Pointer Positioning: Corrected the pointer’s
lastWorldPosto update accurately when the camera moves. - Collision Events: Standardized collision event targets to consistently reference entities instead of colliders or other types.
- Screenshot Timing: Improved
ex.Engine.screenshot()to ensure images are fully loaded before use in transitions. - Scene Transition Visuals: Resolved a background color inconsistency that occurred briefly during scene transitions.
- Input Handling: Fixed issues where
blockInput: trueonly blocked input events but not state queries likewasHeld(...). - Renderer Plugin: Allowed easier definition of custom
RendererPluginby exposing necessary types. - Fade Transition: Ensured
ex.Fadetransitions complete reliably regardless of elapsed time. - Collider Stability: Fixed infinite loops in
ex.PolygonCollidersfor degenerate polygons and improvedCircleColliderraycasts. - Loader Stability: Prevented the engine from locking up when using an empty loader in
ex.Scene.onPreLoad(loader: ex.DefaultLoader). - Input Events: Addressed issues with scoped input events preserving state incorrectly when switching scenes.
- Key Handling: Ensured all physical keys, including
ex.Keys.Tab, are recognized and handled correctly. - Graphics Opacity: Corrected multiplicative opacity issues when setting actor opacity via
ex.Label. - Loader Resolution: Fixed low-resolution logos in the loader for smaller configured resolutions.
- GIF Parsing: Enhanced
ex.Gifto correctly parse certain binary formats. - Pixel Ratio Overrides: Fixed the boot
ex.Loaderto prevent removal of pixel ratio overrides. - Raster Options: Ensured
ex.RasterOptionsextendsex.GraphicsOptionsfor consistent behavior. - RayCasting Order: Fixed inconsistent ordering in raycasts when using the
ex.SparseHashGridCollisionProcessor. - Scene Transitions: Ensured that providing a loader without a transition does not cause errors.
- Vector Normalization: Updated
ex.Vector.normalize()to return a zero-vector instead of(0,1)when normalizing a zero-magnitude vector. - API Refinements: Various API refinements to disallow invalid combinations of collider parameters and improve type safety.
Breaking Changes
Version 0.30.0 introduces several breaking changes aimed at streamlining the API and improving overall consistency. Developers upgrading to this version should review these changes to adjust their code accordingly.
- Method Renaming and Removal:
ex.Engine.goto(...)has been removed. Useex.Engine.goToScene(...)instead.ex.GraphicsComponent.show(...)has been removed. Useex.GraphicsComponent.use(...)instead.ex.EventDispatcherhas been removed. Useex.EventEmitterinstead.
- Configuration Adjustments:
ex.Engine.getAntialiasing()andex.Engine.setAntialiasing(bool)have been removed. Configure antialiasing via the engine constructor:
const engine = new ex.Engine({
antialiasing: true
});
Or set it directly on the screen:
engine.screen.antialiasing = true;
ex.Physics.*configuration statics have been removed. Configure physics settings through the engine constructor:
const engine = new ex.Engine({
physics: { /* physics config */ }
});
- Namespace and Type Promotions:
ex.Input.*namespace has been removed. Types have been promoted toex.*.
- Collision Events Targeting:
- Collision events now exclusively target
ex.Collidertypes instead of sometimes emittingex.Entityobjects.
- Collision events now exclusively target
- API Parameter Changes:
ex.Timernow only accepts an option bag constructor.PreDrawEvent,PostDrawEvent,PreTransformDrawEvent,PostTransformDrawEvent,PreUpdateEvent, andPostUpdateEventnow useelapsedMsinstead ofdeltafor the time between frames.
- Trigger API Modifications:
actionnow returns the triggeringEntityinstead ofActor.targetnow works in conjunction withfilterinstead of overwriting it.EnterTriggerEventandExitTriggerEventnow contain anentity: Entityproperty instead ofactor: Actor.
- Vector and GIF Handling:
ex.Vector.normalize()returns a zero-vector instead of(0,1)when normalizing a vector with zero magnitude.- The
transparentColorconstructor argument forex.Gifhas been removed in favor of built-in GIF file mechanisms.
- Dependency Removal:
- Removed the
core-jsdependency, which is no longer necessary for modern browsers. This is a breaking change for projects targeting older browsers.
- Removed the
- API Consistency and Renaming:
ex.Particleandex.ParticleEmitterAPIs have been modernized to align with the latest Excalibur conventions.- Renamed properties for clarity and consistency:
particleSprite→graphicparticleRotationalVelocity→angularVelocityfadeFlag→fadeacceleration→accparticleLife→lifeminVel→minSpeedmaxVel→maxSpeed
const emitter = new ex.ParticleEmitter({
width: 10,
height: 10,
radius: 5,
emitterType: ex.EmitterType.Rectangle,
emitRate: 300,
isEmitting: true,
particle: {
transform: ex.ParticleTransform.Global,
opacity: 0.5,
life: 1000,
acc: ex.vec(10, 80),
beginColor: ex.Color.Chartreuse,
endColor: ex.Color.Magenta,
startSize: 5,
endSize: 100,
minSpeed: 100,
maxSpeed: 200,
minAngle: 5.1,
maxAngle: 6.2,
fade: true,
maxSize: 10,
graphic: swordImg.toSprite(),
randomRotation: true,
minSize: 1
}
});
Performance Improvements
Excalibur v0.30.0 introduces numerous performance optimizations to ensure smoother and more efficient game execution:
- PolygonCollider Performance: Enhanced
PolygonCollider.contains(...)by keeping geometry tests in local space. - Image Rendering: Upgraded to
ImageRendererV2, approximately doubling image rendering performance. - Component Retrieval: Optimized
ex.Entity.get()method for faster component access. - Particle Emitter: Significant performance gains in
ex.ParticleEmitteroperations. - Collision Processing: Improved collision narrowphase and solver steps with the
ex.SparseHashGridCollisionProcessor. - Pointer System: Enhanced with a new spatial hash grid data structure for quicker pointer event processing.
- Loop Optimization: Switched from iterators to C-style loops where possible to increase execution speed.
- Object Pooling: Leveraged object pools to reduce allocations and improve memory management.
- Hot Path Allocations: Reduced allocations in critical paths, such as state/transform stacks and collision calculations, to minimize performance bottlenecks.
Developer Experience Enhancements
- Assertions: Introduced
ex.assert()for enforcing conditions during development, aiding in debugging. - TypeScript Strictness: Increased TypeScript strictness across various APIs, enhancing type safety and reducing potential runtime errors.
- Development Warnings: Display warnings when an
Entityhasn’t been added to a scene after a few seconds, preventing potential issues in game logic. - Enhanced Coroutines: Improved coroutine management with better control over execution flow, including support for nested coroutines.
Raw Changes
- Removal of Units: Parameters no longer include units by default, streamlining API usage and reducing potential confusion.
- Improved Type Definitions: Enhanced type definitions to disallow invalid combinations of collider parameters and ensure only default color graphics are added for respective colliders.
- Graphical Consistency: Ensured
ex.SpriteFontrespects scale when measuring text and fixed negative transform issues affecting collision detection.
Conclusion
Excalibur v0.30.0 marks a significant advancement in the engine’s capabilities, offering developers a more powerful, efficient, and flexible toolkit for creating engaging 2D games. The introduction of GPU-accelerated particles, enhanced sprite management, robust performance optimizations, and numerous bug fixes collectively contribute to a more stable and feature-rich development environment.
Developers are highly encouraged to upgrade to Excalibur v0.30.0 to leverage these enhancements and streamline their game development workflows. For more detailed documentation, and migration guides, please refer to the official release notes on GitHub.