Excalibur v0.30.0 Released: Advanced GPU Particles, Interactive Tile Maps, and Performance Enhancements for 2D Game Development

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.

Excalibur v0.30.0 Released
Excalibur v0.30.0 Released

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.width and engine.screen.height as aliases for engine.screen.drawWidth and engine.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(...) and actor.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.forceOnScreen ensures 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.Debug static 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.SparseHashGridCollisionProcessor offers a faster, more efficient collision pair generation mechanism.
  • Pointer System: Improved PointerSystem using 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.CoroutineInstance provides 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.worldToPagePixelRatio API 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 RentalPool type 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 lastWorldPos to 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: true only blocked input events but not state queries like wasHeld(...).
  • Renderer Plugin: Allowed easier definition of custom RendererPlugin by exposing necessary types.
  • Fade Transition: Ensured ex.Fade transitions complete reliably regardless of elapsed time.
  • Collider Stability: Fixed infinite loops in ex.PolygonColliders for degenerate polygons and improved CircleCollider raycasts.
  • 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.Gif to correctly parse certain binary formats.
  • Pixel Ratio Overrides: Fixed the boot ex.Loader to prevent removal of pixel ratio overrides.
  • Raster Options: Ensured ex.RasterOptions extends ex.GraphicsOptions for 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. Use ex.Engine.goToScene(...) instead.
    • ex.GraphicsComponent.show(...) has been removed. Use ex.GraphicsComponent.use(...) instead.
    • ex.EventDispatcher has been removed. Use ex.EventEmitter instead.
  • Configuration Adjustments:
    • ex.Engine.getAntialiasing() and ex.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 to ex.*.
  • Collision Events Targeting:
    • Collision events now exclusively target ex.Collider types instead of sometimes emitting ex.Entity objects.
  • API Parameter Changes:
    • ex.Timer now only accepts an option bag constructor.
    • PreDrawEvent, PostDrawEvent, PreTransformDrawEvent, PostTransformDrawEvent, PreUpdateEvent, and PostUpdateEvent now use elapsedMs instead of delta for the time between frames.
  • Trigger API Modifications:
    • action now returns the triggering Entity instead of Actor.
    • target now works in conjunction with filter instead of overwriting it.
    • EnterTriggerEvent and ExitTriggerEvent now contain an entity: Entity property instead of actor: Actor.
  • Vector and GIF Handling:
    • ex.Vector.normalize() returns a zero-vector instead of (0,1) when normalizing a vector with zero magnitude.
    • The transparentColor constructor argument for ex.Gif has been removed in favor of built-in GIF file mechanisms.
  • Dependency Removal:
    • Removed the core-js dependency, which is no longer necessary for modern browsers. This is a breaking change for projects targeting older browsers.
  • API Consistency and Renaming:
    • ex.Particle and ex.ParticleEmitter APIs have been modernized to align with the latest Excalibur conventions.
    • Renamed properties for clarity and consistency:
      • particleSpritegraphic
      • particleRotationalVelocityangularVelocity
      • fadeFlagfade
      • accelerationacc
      • particleLifelife
      • minVelminSpeed
      • maxVelmaxSpeed
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.ParticleEmitter operations.
  • 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 Entity hasn’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.SpriteFont respects 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.

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

    Comments