Skip to content

Releases: excaliburjs/Excalibur

Excalibur v0.29.3 Release

05 May 16:53
Compare
Choose a tag to compare

excalibur logo

This is a maintenance release with only bug fixes!

Fixes

  • fix: ex.Vector.toAngle() returns angles between [0, 2PI)
  • fix: Make Entity Constructor's components option optional by @muhajirdev in #3027
  • fix: getSceneName use scenes #3022 by @aruru-weed in #3023
  • fix: Loader suppressPlayButton is now respected (0f9e77d)
  • fix: [#3047] Animation glitch cause by uninitialized state by @eonarheim in #3048

New Contributors

  • @muhajirdev made their first contribution in #3026
  • @aruru-weed made their first contribution in #3023
  • Special thanks to @djdenuyl for spotting a critical bug in image rendering! And a very thorough bug report!

Full Changelog: v0.29.2...v0.29.3

Excalibur v0.29.2 Release

07 Apr 21:17
Compare
Choose a tag to compare

excalibur logo

This is a medium-ish release, with a ton of community contributions especially in the bugfix realm!

Features

  • Added ability to configure image wrapping on ex.ImageSource with the new ex.ImageWrapping.Clamp (default), ex.ImageWrapping.Repeat, and ex.ImageWrapping.Mirror.
    const image = new ex.ImageSource('path/to/image.png', {
      filtering: ex.ImageFiltering.Pixel,
      wrapping: {
        x: ex.ImageWrapping.Repeat,
        y: ex.ImageWrapping.Repeat,
      }
    });
  • Added pointer event support to ex.TileMap's and individual ex.Tile's
  • Added pointer event support to ex.IsometricMap's and individual ex.IsometricTile's
  • Added useAnchor parameter to ex.GraphicsGroup to allow users to opt out of anchor based positioning, if set to false all graphics members
    will be positioned with the top left of the graphic at the actor's position.
    const graphicGroup = new ex.GraphicsGroup({
      useAnchor: false,
      members: [
        {
          graphic: heartImage.toSprite(),
          offset: ex.vec(0, 0),
        },
        {
          graphic: heartImage.toSprite(),
          offset: ex.vec(0, 16),
        },
        {
          graphic: heartImage.toSprite(),
          offset: ex.vec(16, 16),
        },
        {
          graphic: heartImage.toSprite(),
          offset: ex.vec(16, 0),
        },
      ],
    });
  • Added simplified ex.coroutine overloads, you need not pass engine as long as you are in an Excalibur lifecycle
    const result = ex.coroutine(function* () {...});
  • Added way to bind 'this' to ex.coroutine overloads, you need not pass engine as long as you are in an Excalibur lifecycle
    const result = ex.coroutine({myThis: 'cool'}, function* () {...});
  • Added optional ex.coroutine timing parameter to schedule when they are updated
    const result = ex.coroutine(engine, function * () {...}, { timing: 'postupdate' })
  • Added GraphicsComponent.bounds which will report the world bounds of the graphic if applicable!
  • Added ex.Vector.EQUALS_EPSILON to configure the ex.Vector.equals(v) threshold
  • Added way to add custom WebGL context lost/recovered handlers for your game
    const game = new ex.Engine({
      handleContextLost: (e) => {...},
      handleContextRestored: (e) => {...}
    })

Fixed

  • Fixed issue where ex.TileMap culling did not work properly when using fixed updates lower than refresh rate
  • Fixed incomplete types for font options in ex.FontSource().toFont(options)
  • Fixed issue with ex.Loader start button position when using CSS transforms
  • Fixed issue where adding scenes with the same name did not work when it was previously removed
  • Fixed issue when WebGL context lost occurs where there was no friendly output to the user
  • Fixed issue where HiDPI scaling could accidentally scale past the 4k mobile limit, if the context would scale too large it will now attempt to recover by backing off.
  • Fixed issue where logo was sometimes not loaded during ex.Loader
  • Fixed issue where unbounded containers would grow infinitely when using the following display modes:
    • DisplayMode.FillContainer
    • DisplayMode.FitContainer
    • DisplayMode.FitContainerAndFill
    • DisplayMode.FitContainerAndZoom
  • Fixed issue where ex.ParticleEmitter z-index did not propagate to particles
  • Fixed incongruent behavior as small scales when setting transform.scale = v and transform.scale.setTo(x, y)
  • Fixed ex.coroutine TypeScript type to include yielding undefined
  • Fixed issue where Firefox on Linux would throw an error when using custom Materials due to unused attributes caused by glsl compiler optimization.
  • Fixed issue where start transition did not work properly if deferred
  • Fixed issue where transitions did not cover the whole screen if camera was zoomed
  • Fixed issue where Color.toHex() produced invalid strings if the channel values are negative or fractional, or if the alpha channel was different than 1

Changed

  • Significant 2x performance improvement to image drawing in Excalibur
  • Simplified ex.Loader viewport/resolution internal configuration
Raw Changes

What's Changed

Read more

Excalibur v0.29.1 Release

23 Feb 14:49
Compare
Choose a tag to compare

excalibur logo

Small release to fix transition bug!

What's Changed

Full Changelog: v0.29.0...v0.29.1

Excalibur v0.29.0 Release

20 Feb 14:28
1b8475c
Compare
Choose a tag to compare

excalibur logo

This is a huge release v0.29.0, we have a lot of big features that bring us closer to v1!

Join the community on discord!

There are breaking changes in this release, please review the migration guide from v0.28.x to v0.29.0

Features

  • Added new ex.Tilemap.getOnScreenTiles() method to help users access onscreen tiles for logic or other concerns.

  • Added ex.FontSource resource type

    const fontSource = new ex.FontSource('/my-font.ttf', 'My Font')
    loader.addResource(fontSource)
    
    game.start(loader).then(() => {
      const font = fontSource.toFont() // returns ex.Font
    })

    Font options can be defined either at the source or at the toFont() call. If defined in both, toFont(options) will
    override the options in the FontSource.

    const fontSource = new ex.FontSource('/my-font.ttf', 'My Font', { 
      filtering: ex.ImageFiltering.Pixel,
      size: 16, // set a default size
    })
    const font = fontSource.toFont({
      // override just the size
      size: 20,
    })
  • Added fullscreen after load feature! You can optionally provide a fullscreenContainer with a string id or an instance of the HTMLElement

    new ex.Loader({
      fullscreenAfterLoad: true,
      fullscreenContainer: document.getElementById('container')
    });
  • Added new ex.Debug static for more convenient debug drawing where you might not have a graphics context accessible to you. This works by batching up all the debug draw requests and flushing them during the debug draw step.

    • ex.Debug.drawRay(ray: Ray, options?: { distance?: number, color?: Color })
    • ex.Debug.drawBounds(boundingBox: BoundingBox, options?: { color?: Color })
    • ex.Debug.drawCircle(center: Vector, radius: number, options?: ...)
    • ex.Debug.drawPolygon(points: Vector[], options?: { color?: Color })
    • ex.Debug.drawText(text: string, pos: Vector)
    • ex.Debug.drawLine(start: Vector, end: Vector, options?: LineGraphicsOptions)
    • ex.Debug.drawLines(points: Vector[], options?: LineGraphicsOptions)
    • drawPoint(point: Vector, options?: PointGraphicsOptions)
  • Experimental ex.coroutine for running code that changes over time, useful for modeling complex animation code. Coroutines return a promise when they are complete. You can think of each yield as a frame.

    • The result of a yield is the current elapsed time
    • You can yield a number in milliseconds and it will wait that long before resuming
    • You can yield a promise and it will wait until it resolves before resuming
      const completePromise = coroutine(engine, function * () {
        let elapsed = 0;
        elapsed = yield 200; // frame 1 wait 200 ms before resuming
        elapsed = yield fetch('./some/data.json'); // frame 2
        elapsed = yield; // frame 3
      });
  • Added additional options in rayCast options

    • ignoreCollisionGroupAll: boolean will ignore testing against anything with the CollisionGroup.All which is the default for all
    • filter: (hit: RayCastHit) => boolean will allow people to do arbitrary filtering on raycast results, this runs very last after all other collision group/collision mask decisions have been made
  • Added additional data side and lastContact to onCollisionEnd and collisionend events

  • Added configuration option to ex.PhysicsConfig to configure composite collider onCollisionStart/End behavior

  • Added configuration option to ex.TileMap({ meshingLookBehind: Infinity }) which allows users to configure how far the TileMap looks behind for matching colliders (default is 10).

  • Added Arcade Collision Solver bias to help mitigate seams in geometry that can cause problems for certain games.

    • ex.ContactSolveBias.None No bias, current default behavior collisions are solved in the default distance order
    • ex.ContactSolveBias.VerticalFirst Vertical collisions are solved first (useful for platformers with up/down gravity)
    • ex.ContactSolveBias.HorizontalFirst Horizontal collisions are solved first (useful for games with left/right predominant forces)
      const engine = new ex.Engine({
        ...
        physics: {
          solver: ex.SolverStrategy.Realistic,
          arcade: {
            contactSolveBias: ex.ContactSolveBias.VerticalFirst
          },
        }
      })
  • Added Graphics opacity on the Actor constructor new ex.Actor({opacity: .5})

  • Added Graphics pixel offset on the Actor constructor new ex.Actor({offset: ex.vec(-15, -15)})

  • Added new new ex.Engine({uvPadding: .25}) option to allow users using texture atlases in their sprite sheets to configure this to avoid texture bleed. This can happen if you're sampling from images meant for pixel art

  • Added new antialias settings for pixel art! This allows for smooth subpixel rendering of pixel art without shimmer/fat-pixel artifacts.

    • Use new ex.Engine({pixelArt: true}) to opt in to all the right defaults to make this work!
  • Added new antialias configuration options to deeply configure how Excalibur does any antialiasing, or you can provide antialiasing: true/antialiasing: false to use the old defaults.

    • Example;
    const game = new ex.Engine({
       antialiasing: {
           pixelArtSampler: false,
           filtering: ex.ImageFiltering.Pixel,
           nativeContextAntialiasing: false,
           canvasImageRendering: 'pixelated'
       }
    })
  • Added new lineHeight property on SpriteFont and Font to manually adjust the line height when rendering text.

  • Added missing dual of ex.GraphicsComponent.add(), you can now ex.GraphicsComponent.remove(name);

  • Added additional options to ex.Animation.fromSpriteSheetCoordinates() you can now pass any valid ex.GraphicOptions to influence the sprite per frame

    const anim = ex.Animation.fromSpriteSheetCoordinates({
      spriteSheet: ss,
      frameCoordinates: [
        {x: 0, y: 0, duration: 100, options: { flipHorizontal: true }},
        {x: 1, y: 0, duration: 100, options: { flipVertical: true }},
        {x: 2, y: 0, duration: 100},
        {x: 3, y: 0, duration: 100}
      ],
      strategy: ex.AnimationStrategy.Freeze
    });
  • Added additional options to ex.SpriteSheet.getSprite(..., options). You can pass any valid ex.GraphicOptions to modify a copy of the sprite from the spritesheet.

    const sprite = ss.getSprite(0, 0, {
      flipHorizontal: true,
      flipVertical: true,
      width: 200,
      height: 201,
      opacity: .5,
      scale: ex.vec(2, 2),
      origin: ex.vec(0, 1),
      tint: ex.Color.Red,
      rotation: 4
    });
  • New simplified way to query entities ex.World.query([MyComponentA, MyComponentB])

  • New way to query for tags on entities ex.World.queryTags(['A', 'B'])

  • Systems can be added as a constructor to a world, if they are the world will construct and pass a world instance to them

    world.add(MySystem);
    ...
    
    class MySystem extends System {
      query: Query;
      constructor(world: World) {
        super()
        this.query = world.query([MyComponent]);
      }
    
      update
    }
  • Added RayCastHitas part of every raycast not just the physics world query!

    • Additionally added the ray distance and the contact normal for the surface
  • Added the ability to log a message once to all log levels

    • debugOnce
    • infoOnce
    • warnOnce
    • errorOnce
    • fatalOnce
  • Added ability to load additional images into ex.Materials!

    const noise = new ex.ImageSource('./noise.avif');
    loader.addResource(noise);
    
    var waterMaterial = game.graphicsContext.createMaterial({
      name: 'water',
      fragmentSource: waterFrag,
      color: ex.Color.fromRGB(55, 0, 200, .6),
      images: {
        u_noise: noise
      }
    });
  • Scene Transition & Loader API, this gives you the ability to have first class support for individual scene resource loading and scene transitions.

    • Add or remove scenes by constructor

    • Add loaders by constructor

    • New ex.DefaultLoader type that allows for easier custom loader creation

    • New ex.Transition type for building custom transitions

    • New scene lifecycle to allow scene specific resource loading

      • onTransition(direction: "in" | "out") {...}
      • onPreLoad(loader: DefaultLoader) {...}
    • New async goToScene() API that allows overriding loaders/transitions between scenes

    • Scenes now can have async onInitialize and async onActivate!

    • New scenes director API that allows upfront definition of scenes/transitions/loaders

    • Example:
      Defining scenes upfront

      const game = new ex.Engine({
        scenes: {
          scene1: {
            scene: scene1,
            transitions: {
              out: new ex.FadeInOut({duration: 1000, direction: 'out', color: ex.Color.Black}),
              in: new ex.FadeInOut({duration: 1000, direction: 'in'})
            }
          },
          scene2: {
            scene: scene2,
            loader: ex.DefaultLoader, // Constructor only option!
            transitions: {
              out: new ex.FadeInOut({duration: 1000, direction: 'out'}),
              in: new ex.FadeInOut({duration: 1000, direction: 'in', color: ex.Color.Black })
            }
          },
        scene3: ex.Scene // Constructor only option!
        } 
      })
      
      // Specify the boot loader & first scene transition from loader
      game.start('scene1',
      {
        inTransition: new ex.FadeInOut({duration: 500, direction: 'in', color: ex.Color.ExcaliburBlue})
        loader: boot,
      });
    • Scene specific input API so that you can add input handlers that only fire whe...
Read more

Excalibur v0.28.7 Release

27 Jan 00:47
Compare
Choose a tag to compare

excalibur logo

Bugfix release! This release is slightly different cut from the branch release/v0.28.x instead of main, this is because features that are not ready to ship are in the mainline currently and will be shipped as part of v0.29.0

  • fix: Add friendly error if canvasElementId missing(#2885)
  • fix: ex.Material no longer does lazy init, requires graphics context
  • fix: Issue with pointer events on screen elements (#2902)

Also big thanks to @jyoung4242! This was his first contribution to Excalibur!

Full Changelog: v0.28.6...v0.28.7

Excalibur v0.28.6 Release

13 Jan 14:11
Compare
Choose a tag to compare

excalibur logo

Another small release! A few bug fixes and some small features. Thanks @mattjennings for being MVP and testing all these bugs!

  • Added arbitrary data storage in isometric tiles, ex.IsometricTile.data this brings it into feature parity with normal ex.Tile.data
  • New graphics events and hooks that allow you to hook into graphics drawing before or after any drawing transformations have been applied
    • Actor.graphics.onPreTransformDraw with the corresponding event .on('pretransformdraw')
    • Actor.graphics.onPostTransformDraw with the corresponding event .on('posttransformdraw')
  • New property and methods overloads to ex.Animation
    • ex.Animation.currentFrameTimeLeft will return the current time in milliseconds left in the current
    • ex.Animation.goToFrame(frameNumber: number, duration?: number) now accepts an optional duration for the target frame
    • ex.Animation.speed can set the speed multiplier on an animation 1 = 1x speed, 2 = 2x speed.

What's Changed

Full Changelog: v0.28.5...v0.28.6

Excalibur v0.28.5 Release

06 Jan 02:19
Compare
Choose a tag to compare

excalibur logo

Another small release! A few bug fixes, QOL improvements, and fixes supporting the new Tiled plugin!

  • Scenes can now have their own background color!
  • Actions emit events on start and complete! Thanks @mattjennings
  • Collision lifecycle methods on Actor! Thanks for the suggestion @mattjennings!

Features

Fixes

Dependencies

  • chore: Update dependency @babel/core to v7.23.7 by @renovate in #2862
  • chore: Update dependency terser-webpack-plugin to v5.3.10 by @renovate in #2864
  • chore: Update dependency typescript to v5.3.3 by @renovate in #2866
  • chore: Update dependency @types/node to v18.19.4 by @renovate in #2863

Full Changelog: v0.28.4...v0.28.5

Excalibur v0.28.4 Release

22 Dec 03:52
Compare
Choose a tag to compare

excalibur logo

Another small release! A few bug fixes and some enhancements to materials!

water-material.mp4

Materials

2 new uniforms

  • u_screen_texture - This is the texture of the screen right before the material draw call
  • u_time_ms - This is the milliseconds since page navigation (performance.now() under the hood)

2 new attribute/varyings

  • a_screenuv - The vertex attribute corresponding to the screen uv relative to the current graphic
  • v_screenuv - The fragment varying corresponding to the screen uv relative to the current graphic

Finally there is a new convenience api for updating shader values in materials. .update(shader => {...})

  game.input.pointers.primary.on('move', evt => {
    heartActor.pos = evt.worldPos;
    swirlMaterial.update(shader => {
      shader.trySetUniformFloatVector('iMouse', evt.worldPos);
    });
  });

What's Changed

Full Changelog: v0.28.3...v0.28.4

Excalibur v0.28.3 Release

12 Dec 15:10
Compare
Choose a tag to compare

excalibur logo

Small release, fixed a couple bugs!

  • Materials were crashing Excalibur if you tried to render different ones at once
  • Raycasting against collision groups wasn't working as expected!

What's Changed

Full Changelog: v0.28.2...v0.28.3

Excalibur v0.28.2 Release

02 Dec 02:40
Compare
Choose a tag to compare

excalibur logo

This was mostly a bug fix release, lots of small fixes! No breaking changes. Notably there are some performance improvements to TileMap by utilizing a QuadTree to help offscreen culling.

Fixes & Features

Dependencies

Dependency

  • chore: Update dependency @babel/core to v7.22.11 by @renovate in #2746
  • chore: Update dependency @fortawesome/fontawesome-free to v6.4.2 by @renovate in #2747
  • chore: Update dependency jasmine-core to v5.1.1 by @renovate in #2749
  • chore: Update dependency serve to v14.2.1 by @renovate in #2751
  • chore: Update dependency node to v18.17.1 by @renovate in #2750
  • chore: Update dependency core-js to v3.32.1 by @renovate in #2748
  • chore: Update dependency eslint to v8.48.0 by @renovate in #2752
  • chore: Update dependency @types/node to v18.17.13 by @renovate in #2760
  • chore: Update dependency eslint-config-prettier to v8.10.0 by @renovate in #2753
  • chore: Update dependency eslint-plugin-jsdoc to v46.5.1 by @renovate in #2754
  • chore: Update coverallsapp/github-action action to v2.2.3 by @renovate in #2777
  • chore: Update dependency @types/jasmine to v4.3.6 by @renovate in #2778
  • chore: Update dependency @types/react-color to v3.0.7 by @renovate in #2779
  • chore: Update dependency @types/webpack-env to v1.18.2 by @renovate in #2780
  • chore: Update dependency core-js to v3.32.2 by @renovate in #2781
  • chore: Update dependency @babel/core to v7.23.0 by @renovate in #2782
  • chore: Update dependency eslint to v8.50.0 by @renovate in #2783
  • chore: Update dependency core-js to v3.33.0 by @renovate in #2786
  • chore: Update dependency eslint-plugin-jsdoc to v46.8.2 by @renovate in #2784
  • chore: Update dependency node to v18.18.0 by @renovate in #2785
  • [chore] Upgrade typescript by @eonarheim in #2798
  • chore: Update dependency @types/webpack-env to v1.18.4 by @renovate in #2797
  • chore: Update dependency @babel/core to v7.23.3 by @renovate in #2795
  • chore: Update dependency @types/react-color to v3.0.10 by @renovate in #2796
  • chore: Update dependency @babel/core to v7.23.5 by @renovate in #2813
  • chore: Update dependency core-js to v3.33.3 by @renovate in #2814
  • chore: Update dependency @types/jasmine to v4.6.4 by @renovate in #2817
  • chore: Update dependency @fortawesome/fontawesome-free to v6.5.1 by @renovate in #2816
  • chore: Update dependency ts-loader to v9.5.1 by @renovate in #2821
  • chore: Update dependency node to v18.19.0 by @renovate in #2820
  • chore: Update dependency eslint to v8.54.0 by @renovate in #2818
  • chore: Update dependency eslint-plugin-jsdoc to v46.9.0 by @renovate in #2819
  • chore: Update dependency rimraf to v5 by @renovate in #2757
  • chore(deps-dev): bump browserify-sign from 4.2.1 to 4.2.2 by @dependabot in #2794
  • chore: Update dependency typescript to v5.3.2 by @renovate in #2823
  • chore: Update dependency eslint-config-prettier to v9 by @renovate in #2755
  • chore: Update dependency replace-in-file to v7 by @renovate in #2724
  • chore: Update dependency webpack to v5.89.0 by @renovate in #2824
  • chore: Update actions/checkout action to v4 by @renovate in #2828
  • chore: Update typescript-eslint monorepo to v6.13.1 by @renovate in #2827
  • chore: Update actions/setup-node action to v4 by @renovate in #2829
  • chore: Update dependency @types/jasmine to v5 by @renovate in #2830
  • chore: Update dependency webpack-cli to v5 by @renovate in #2832
  • chore: Update dependency @types/node to v18.19.1 by @renovate in #2833

New Contributors

Full Changelog: v0.28.0...v0.28.2