Skip to content

Releases: kaplayjs/kaplay

4000.0.0-alpha.25

24 Dec 01:32

Choose a tag to compare

[4000.0.0-alpha.25] - 2025-12-23

Added

  • Added the fakeMouseMove event in FakeMouseComp, it will triggers when you move the object - @lajbel
  • Global retrieve() method to get the objects with area within a certain rectangle - @mflerackers

Changed

  • Transforms are now only recalculated when needed. Thus static objects no longer increase computation in the transform phase - @mflerackers
  • Areas are now only recalculated when the area settings or (optional) renderArea has changed - @mflerackers
  • World (transformed) areas are now only recalculated when the area or transform has changed - @mflerackers
  • World bounding boxes are now only recalculated when the world area has changed - @mflerackers
  • Broad stage collision detection spatial structures are now only updated when an object's world bounding box has changed - @mflerackers
  • You can no longer change the position of an object by doing obj.pos.x += 1. You need to assign a new Vec2 or use moveBy instead - @mflerackers
  • The grid broadphase has been rewritten for performance - @mflerackers

Full Changelog: 4000.0.0-alpha.24...4000.0.0-alpha.25

4000.0.0-alpha.24

12 Dec 12:34

Choose a tag to compare

[4000.0.0-alpha.24] - 2025-12-12

Added

  • Added the maxTimeStep and fixedUpdateMode options, as well as
    setFixedSpeed() for more granular control over fixed update and timing -
    @dragoncoder047
  • Added parameterized formatting tags like "[color=red]Red text![/color]" in
    CharTransformFunc for more powerful text formatting options -
    @dragoncoder047
  • Added createRegularPolygon() and createStarPolygon() to create 2D regular
    polytopes - @mflerackers
  • Added createCogPolygon() to create 2D regular cogs - @mflerackers
  • Added getSpriteOutline() that takes a sprite asset and returns a polygon
    showing the outline - @milosilo-dev
  • Added Quadtree for collision detection (only for fixed size screen for now,
    needs expansion) - @mflerackers
  • Added vertical sweep and prune - @mflerackers
  • Added configuration to choose broad phase algorithm - @mflerackers

Fixed

  • Fixed the fakeMouse() component not giving the right position when the
    camera transform was not the identity matrix - @dragoncoder047
  • Fixed tall fonts being cropped - @anthonygood
  • Fixed the sprite animation onEnd() callback being called before the
    animation actually stopped, so if the onEnd callback started a new animation,
    the new animation was instantly stopped - @dragoncoder047
  • Now playMusic() actually uses the requested volume and playback rate given
    in the options - @dragoncoder047

4000.0.0-alpha.23

05 Nov 23:19

Choose a tag to compare

[4000.0.0-alpha.23] - 2025-11-05

Added

  • Added getGamepadAnalogButton() to read the analog value of buttons like the
    triggers - @dragoncoder047

    isGamepadButtonDown("rtrigger"); // -> true/false, 0/1
    getGamepadAnalogButton("rtrigger"); // -> analog value between 0 (not pressed) and 1 (fully pressed)
  • Added chorded button bindings using the Buttons API, so you can bind different
    actions to tab and shift+tab, and handle them like normal. Also works with
    gamepads and mouse! - @dragoncoder047

    kaplay({
        buttons: {
            forward: {
                keyboard: "tab",
                gamepad: "south",
            },
            backward: {
                keyboard: "shift+tab",
                gamepad: "rshoulder+south",
            },
        },
    });
  • Added skew to text formatting, so now italics is possible - @dragoncoder047

  • Added lifetime scopes, a way to define the lifetime of an event handler
    using a specific scope, scene, app or a game object - @lajbel,
    @dragoncoder047

    app.onUpdate(() => {
        // runs until it is cancelled
    });
    
    scene("game", () => {
        const obj = add([]);
    
        obj.onUpdate(() => {
            // runs until obj is destroyed
        });
    
        scene.onUpdate(() => { // or just onUpdate(() => {
            // runs until scene is changed
        });
    });

    All the available handlers in the scopes are GameEventHandlers ones:

    • onKeyDown()
    • onKeyPress()
    • onKeyPressRepeat()
    • onKeyRelease()
    • onCharInput()
    • onMouseDown()
    • onMousePress()
    • onMouseRelease()
    • onMouseMove()
    • onScroll()
    • onTouchStart()
    • onTouchMove()
    • onTouchEnd()
    • onGamepadConnect()
    • onGamepadDisconnect()
    • onGamepadButtonDown()
    • onGamepadButtonPress()
    • onGamepadButtonRelease()
    • onGamepadStick()
    • onButtonDown()
    • onButtonPress()
    • onButtonRelease()
    • onTabHide()
    • onTabShow()

    And this game object handlers may differ when using it with obj and
    scene/app:

    • onFixedUpdate()
    • onUpdate()
    • onDraw()
  • Added app scope for app event handlers - @lajbel

    app.onUpdate(() => {
        // runs until it is cancelled
    });
  • Added KAPLAYOpt.defaultLifetimeScope for setting the default lifetime scope
    used for event handlers - @lajbel

    kaplay({
        defaultLifetimeScope: "app", // default is "scene"
    });
    
    onKeyPress("space", () => {
        // runs until is cancelled
    });
  • Added skew to text formatting, so now italics is possible - @dragoncoder047

Changed

  • (!) Renamed onShow() to onTabShow() and onHide() to onTabHide() -
    @lajbel

  • In addition to being the scene() function, now scene is also a scope for
    scene event handlers - @lajbel

    scene("game", () => {
        scene.onUpdate(() => { // or just onUpdate(() => {
            // runs until scene is changed
        });
    });

Fixed

  • Now pushScene() and popScene() give the arguments to the scene in the same
    way that go() does rather than passing them all to the first argument as an
    array - @dragoncoder047
  • Fixed a flicker due to the fadeIn not setting opacity until the next frame -
    @mflerackers
  • Fixed FPS cap not working correctly - @mflerackers, @dragoncoder047

Full Changelog: 4000.0.0-alpha.22...4000.0.0-alpha.23

4000.0.0-alpha.22

09 Oct 17:35

Choose a tag to compare

4000.0.0-alpha.22 Pre-release
Pre-release

[4000.0.0-alpha.22] - 2025-10-9

Added

  • Added KAPLAYOpt.types, kaplayTypes() and Opt to config specific
    TypeScript Advanced Features (TAF) - @lajbel

    kaplay({
        types: kaplayTypes<
            // Opt<> is optional but recommended to get autocomplete
            Opt<{
                scenes: {}; // define scenes and arguments
                strictScenes: true; // you can only use defined scenes
            }>
        >(),
    });
  • Added TypesOpt.scenes to type scenes and parameters - @lajbel

    const k = kaplay({
        types: kaplayTypes<
            Opt<{
                scenes: {
                    game: [gamemode: "normal" | "hard"];
                    gameOver: [score: number, highScore: number];
                };
            }>
        >(),
    });
    
    // If you trigger autocomplete it shows "game" or "gameOver"
    k.scene("game", (gamemode) => {
        // gamemode is now type "normal" | "hard"
    
        // @ts-expect-error Argument of type 'string' is not assignable
        // to parameter of type 'number'.
        k.go("gameOver", "10", 10); //
    });

    The methods that support this are:

    • scene
    • go
    • onSceneLeave
    • getSceneName
  • Added TypesOpt.strictScenes to make usable scenes just the ones defined -
    @lajbel

    const k = kaplay({
        types: kaplayTypes<
            Opt<{
                scenes: {
                    game: [gamemode: "normal" | "hard"];
                    gameOver: [score: number, highScore: number];
                };
                strictScenes: true;
            }>
        >(),
    });
    
    // @ts-expect-error Argument of type '"hi"' is not assignable to
    // parameter of type '"game" | "gameOver"'.
    k.scene("hi", () => {});
  • Added named animations - @mflerackers

    By giving a name to an animation, you can define more than one animation

    const anim = obj.animation.get("idle");
    anim.animate("pos", [0, 5, 0], { relative: true });
  • Added screenshotToBlob() to get a screenshot as a Blob - @dragoncoder047

  • Added getButtons() to get the input binding buttons definition - @lajbel

  • Added RuleSystem, DecisionTree and StateMachine for enemy AI -
    @mflerackers

  • Added constraint components for distance, translation, rotation, scale and
    transform constraints - @mflerackers

  • Added inverse kinematics constraint components using FABRIK and CCD, the
    latter one can use bone constraints to constrain the angle - @mflerackers

  • Added skew to Mat23, transformation stack, RenderProps, GameObjRaw as well as
    a component - @mflerackers

  • Added texture uniforms, in order to access more than one texture at a time in
    shaders - @mflerackers

Fixed

  • Now error screen should be instantly shown - @lajbel

Changed

  • Now, you can use color(c) with a hexadecimal literal number (ex: 0x00ff00) -
    @lajbel
    // blue frog
    add([
        sprite("bean"),
        color(0x0000ff),
    ]);
  • (!) KAPLAYCtx doesn't use generics anymore. Now, KAPLAYCtxT uses
    them - @lajbel
  • Now, kaplay will return KAPLAYCtx or KAPLAYCtxT depending if it's using
    Advanced TypeScript Features or not - @lajbel
  • loadShader() now also checks for link errors as well as compile errors and
    reports them rather than just silently trying to use a borked shader -
    @dragoncoder047
  • The debug record() function now records with sound enabled like it should -
    @dragoncoder047
  • Now KAPLAYOpt.spriteAtlasPadding is set to 2 by default - @lajbel
  • Transformation and drawing is split now, so the transform can be modified
    before drawing - @mflerackers

Full Changelog: 4000.0.0-alpha.21...4000.0.0-alpha.22

4000.0.0-alpha.21

07 Aug 17:20

Choose a tag to compare

4000.0.0-alpha.21 Pre-release
Pre-release

[4000.0.0-alpha.21] - 2025-08-07

Added

  • Added Prefabs - @mflerackers, @lajbel, @amyspark-ng and other contributors.
  • Added new scene methods pushScene() and popScene(), for stack behaviour in
    scenes - @itzKiwiSky
  • Added throwError() for throwing custom errors to the blue screen, even
    errors KAPLAY can't handle. - @lajbel
  • Added insertionSort() - @dragoncoder047
  • Added a mapping for PS5 (DualSense) gamepads, so now you can bind actions to
    the touchpad press (only works in Chrome for some reason) - @dragoncoder047

Changed

  • Renamed KAPLAYOpt.tagsAsComponents to KAPLAYOpt.tagComponentIds - @lajbel
  • Now moving mouse changes the value of getLastInputDevice() - @amyspark-ng
  • Now GameObjRaw.exists() work for nested objects

Fixed

New Contributors

Full Changelog: 4000.0.0-alpha.20...4000.0.0-alpha.21

4000.0.0-alpha.20

15 Jun 16:49

Choose a tag to compare

4000.0.0-alpha.20 Pre-release
Pre-release

[4000.0.0-alpha.20] - 2025-06-15

Added

  • Now you can use the frames of a sprite in an atlas also as a font -
    @dragoncoder047
  • Improved various doc entries. - All Contributors.

Fixed

  • Fixed AreaComp#onClick() attaching events to app, instead of object, so
    event wasn't being paused with obj.paused - @lajbel
  • Fixed all touch events having a bad transform - @lajbel
  • Fixed sprite scaling not working properly when letterbox - @mflerackers
  • Fixed "add" event running twice in addLevel() tiles - @lajbel
  • Fixed blend component having a wrong ID - @lajbel

Removed

Full Changelog: 4000.0.0-alpha.19...4000.0.0-alpha.20

3001.0.19

15 Jun 16:50

Choose a tag to compare

[3001.0.19] - 2025-06-15

  • Fixed AreaComp#onClick() attaching events to app, instead of object, so
    event wasn't being paused with obj.paused - @lajbel
  • Fixed all touch events having a bad transform - @lajbel

Full Changelog: 3001.0.18...3001.0.19

4000.0.0-alpha.19

16 May 17:51

Choose a tag to compare

4000.0.0-alpha.19 Pre-release
Pre-release

What's Changed

New Contributors

Full Changelog: 4000.0.0-alpha.18...4000.0.0-alpha.19

3001.0.18

16 May 20:01

Choose a tag to compare

[3001.0.18] - 2025-05-16

Fixed

  • Removed beant - @lajbel
  • Fixed TexPacker loading big images - @lajbel, @mflerackers
  • Various fixes and improvements - All Contributors

Full Changelog: 3001.0.17...3001.0.18

3001.0.17

08 May 12:29

Choose a tag to compare

[3001.0.17] - 2025-05-08

Added

  • New way to import globals in JS /dist/types.d.ts - @lajbel

Fixed

  • Removed beant - @lajbel
  • Various fixes and improvements - All Contributors

Full Changelog: 3001.0.16...3001.0.17