Changelog for v3001

[unreleased]

[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

[3001.0.18] - 2025-05-16

Fixed

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

[3001.0.17] - 2025-05-08

Added

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

Fixed

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

[3001.0.16] - 2025-04-18

Fixed

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

[3001.0.15] - 2025-04-18

Fixed

  • Various fixes and improvements - All contributors

[3001.0.14] - 2025-04-18

Fixed

  • Various fixes and improvements - All contributors

[3001.0.13] - 2025-04-18

Fixed

  • Various fixes and improvements - All contributors

[3001.0.12] - 2025-04-12

Fixed

[3001.0.11] - 2025-04-12

Added

  • Added CSS Colors! 🎨 - @lajbel (based on @dragoncoder047 idea)

    color("slateblue");
    color("red");
    color("wheat");
    color("tomato"); // yum!
  • Added loadHappy() font to load a default font, happy :D - @lajbel

    kaplay({ font: "happy" });
    loadHappy();
    
    add([text("ohhi")]);

Fixed

[3001.0.10] - 2025-03-22

Added

  • Added new option in LoadSpriteOpt for loading sprites in an individual spritesheet - @chqs-git

    loadSprite("player", "sprites/player.png", {
        singular: true,
    });
  • Frame option for load animations with singular frames - @dragoncoder047

    loadSpriteAtlas("/examples/sprites/dungeon.png", {
        wizard: {
            x: 128,
            y: 140,
            width: 144,
            height: 28,
            sliceX: 9,
            anims: {
                bouncy: {
                    frames: [8, 5, 0, 3, 2, 3, 0, 5],
                    speed: 10,
                    loop: true,
                },
            },
        },
    });
    
    add([sprite("wizard", { anim: "bouncy" }), pos(100, 100)]);

Fixed

  • Args were not being passed to global trigger() - @lajbel
  • AreaComp.onClick now returns the correct type, KEventController, instead of void - @lajbel
  • Lifespan was using async - @lajbel
  • Wrong calculation in Vector.dot() - @andrenanninga
  • Fixed pointer lock undefined catch error for non-promise version - @imaginarny

[3001.0.9] - 2025-01-15

Added

  • (examples) Added a new particle example! - @lajbel

Changed

Fixed

[3001.0.8] - 2025-01-15

Fixed

  • Fixed a bug where alpha channel wasn’t correctly setted - @mflerackers

[3001.0.7] - 2025-01-15

Added

  • Added kaplay({ spriteAtlasPadding }) for setting the space between the sprites in the sprite atlas - @marianyp
kaplay({
    spriteAtlasPadding: 10, // 10 pixels of space between each sprite
});

Changed

  • Now you cannot pass parameters that are not a component or string to .use(). Otherwise it will throw an error - @lajbel

Fixed

  • Fixed a bug where font atlas were working strange - @mflerackers

[3001.0.6] “Santa Events” - 2024-12-27

Added

  • Added trigger(event, tag, ...args) for global triggering events on a specific tag - @lajbel

    trigger("shoot", "target", 140);
    
    on("shoot", "target", (obj, score) => {
        obj.destroy();
        debug.log(140); // every bomb was 140 score points!
    });
  • Added { override?: true } in CharTransform for overridding text styles - @dragoncoder047

    add([
        pos(100, 150),
        text("With override: Hello [foo]styled[/foo] text", {
            transform: {
                color: BLACK, // Default text color for every character
            },
            styles: {
                foo: {
                    color: RED, // [foo] will be red
                    override: true, // will override the black def color
                },
            },
        }),
    ]);
  • Added TextCompOpt.identAll boolean to indent every new line - @dragoncoder047

  • Added TypeScript definition for all App Events and missing Game Object Events - @lajbel

Fixed

[3001.0.5] - 2024-12-18

Added

Changed

Deprecated

Fixed

  • Fixed artifacts present in some TrueType fonts
  • Fixed .use() and .unuse() with area components

[3001.0.0] - 2024-10-31

Added

  • Added getTreeRoot() to get the game’s root object, which is the parent of all other objects

    // get the root object
    const root = getTreeRoot();
    root.add(); // same as add()
    root.get(); // same as get()
  • Added Buttons API for using Input bindings, onButtonPress(), onButtonRelease(), onButtonDown(), and it’s corresponding boolean versions, isButtonPressed(), isButtonDown() and isButtonReleased()

    kaplay({
        // bind your buttons
        buttons: {
            jump: {
                keyboard: ["space", "up"],
                keyboardCode: "Space", // you can also use key codes
                gamepad: ["south"],
            },
        },
    });
    
    onButtonPress("jump", () => {
        player.jump();
    });
  • Added getButton(btn) and setButton(btn) to get and set button bindings

    // ["space", "up"]
    debug.log(getButton("jump").keyboard);
    
    // change the jump button in keyboard to "w"
    setButton("jump", {
        keyboard: ["w"],
        // gamepad binding is not changed
    });
  • Added getLastInputDeviceType() to get what was the last pressed device

    onButtonPress(() => {
        const lastInputDevice = getLastInputDeviceType(); // keyboard, mouse or gamepad
        // change icons, etc
    });
  • Added pressButton(btn) and releaseButton(btn) to simulate button press and release

    pressButton("jump"); // triggers onButtonPress and starts onButtonDown
    releaseButton("jump"); // triggers onButtonRelease and stops onButtonDown
  • Added GameObjRaw.tags to get a game object’s tags

    const obj = add([sprite("bean"), "enemy", "dangerous"]);
    
    // get the tags
    debug.log(obj.tags); // ["enemy", "dangerous"]
  • Added the animate() component to animate the properties of an object using keyframes. Check out Animation Example

    // prop to animate, frames, options
    rotatingBean.animate("angle", [0, 360], {
        duration: 2,
        direction: "forward",
    });
  • Readded layers() and the layer() component

    Before the z() component, there was a layer() component that allowed you to control the draw order of objects. It was removed in v3000, but now it’s back from the void.

    // define the layers
    layers(
        [
            "bg",
            "game",
            "ui",
            // the default layer
        ],
        "game",
    );
    
    // use the layer component
    add([sprite("bg"), layer("bg")]);
  • Added SpriteComp.hasAnim() to check if an animation exists

    const obj = add([sprite("bean", { anim: "walk" })]);
    
    // check if an animation exists
    debug.log(obj.hasAnim("walk")); // true
  • Added SpriteComp.getAnim() for get any animation data

    loadSprite("bean", "bean.png", {
        sliceX: 4,
        sliceY: 1,
        anims: {
            walk: {
                from: 0,
                to: 3,
            },
        },
    });
    
    const obj = add([sprite("bean")]);
    
    // get the animation data
    debug.log(obj.getAnim("walk")); // { from: 0, to: 3 }
  • Added SpriteComp.getCurAnim() to get the current animation data

    const obj = add([sprite("bean", { anim: "walk" })]);
    
    // get the current animation name
    debug.log(obj.getCurAnim().name); // "walk"
  • Added camFlash() to flash the screen

    camFlash(0.5, 0.5, 0.5, 0.5);
  • Added support for radius in individual corners for RectComp,radius

    add([
        rect(100, 100, {
            radius: [10, 20, 30, 40],
        }),
    ]);
  • Added loadMusic() to load streaming audio (doesn’t block in loading screen)

    loadMusic("bgm", "bgm.mp3");
    
    // play the music
    play("bgm");
  • Added Vec2.fromArray() to convert an array to a Vec2

    const point = Vec2.fromArray([100, 200]); // vec2(100, 200);
  • Added Vec2.toArray() to convert a Vec2 to an array

    const point = vec2(100, 200);
    const arr = point.toArray(); // [100, 200]
  • Added chooseMultiple() to choose a random element from an array

    const numbers = [1, 2, 3, 4, 5];
    const random = chooseMultiple(numbers, 3); // [3, 1, 5]
  • Added shuffle() to shuffle an array

    const numbers = [1, 2, 3, 4, 5];
    shuffle(numbers); // [3, 1, 5, 2, 4]
  • Added KAPLAYOpt.debugKey for customizing the key used to toggle debug mode

    kaplay({
        debugKey: "l",
    });
  • Added compatibility with custom properties in debug mode

    const obj = add([
        sprite("bean"),
        {
            health: 100, // on debug.inspect
            damage: 10, // on debug.inspect
            hp() {
                this.health -= this.damage;
            }, // not on debug.inspect
        },
    ]);
    
    // see the custom properties in debug mode
    debug.inspect = true;
  • Added effector components: areaEffector(), buoyancyEffector(), pointEffector(), surfaceEffector()

  • Added constantForce() component

  • Added pathfinder() component to calculate a list of waypoints on a graph

  • Added patrol() component to move along a list of waypoints

  • Added sentry() component to notify when certain objects are in sight

  • Added NavMesh class for pathfinding on a mesh

  • Added particles() component to emit and draw particles

  • Added SpriteComp.animFrame to get the frame of the current animation (not on the spritesheet)

  • Added outline(), shader(), and area() properties to debug.inspect

  • Added getSceneName() to get the current scene name

  • Added Color.toArray() to convert a color to an array

  • Added raycast and LevelComp.raycast method to level

  • Added support for textured polygons

  • Added support for concave polygon drawing

  • Added support for arrays in uniforms

  • Added support for texture larger than 2048x2048

  • Added support for gravity direction

  • Added line join (bevel, miter, round) and line caps (square, round)

  • Added quadratic bezier and Catmull-Rom evaluation

  • Added evaluation of the first and second derivatives for all splines

  • Added higher order easing functions linear, steps and cubic-bezier

Changed

  • Now collision checks are only done if there’s area objects

  • Now you can use arrays in all input handlers

    onKeyPress(["w", "up"], () => {
        player.jump();
    });
  • Now gamepad events return what gamepad triggered the action

    onGamepadButtonPress("south", (btn, gp) => {
        console.log(gp.index); // gamepad number on navigator's gamepad list
    });
  • Now ScaleComp and SpriteComp uses setters/getters for it’s state

    const obj = add([sprite("bean"), scale(2)]);
    
    // set it with = syntax
    obj.scale = vec2(3, 4);
    obj.sprite = "bag";
  • Now you can type get() with a type parameter and passing component types

    const player = get<BodyComp>("player");
  • Now you can pass an AudioBuffer to loadSound()

  • Now debug.log() accepts multiple argument of any type, like console.log()

  • Now Key also accepts a string as an acceptable value

  • Now text() component doesn’t require to pass a string

  • Now camScale() and camPos() accept only 1 number as parameter

  • Now shake() can be called without args

  • Now loadShader() and loadShaderURL() accepts null for unused parameters

  • Now RectCompOpt accepts a array of numbers for radius

Deprecated

Removed

  • (!) Removed compatibility to use two KAPLAY frames in the same page
  • (!) Many TypeScript definitions were fixed, if you use TypeScript now maybe you see new errors that make your code strict
  • Fix error screen not showing with not Error object
  • Fix error where debug screen was scaling bad the blue rectangles
  • Fix error where error screen was not showing when the error was thrown in a input event
  • Fix error where fonts was cropped in the bottom
  • Fix an error where stay() object loose their input events on scene change
kaplay logo