KAPLAY v4000 Alpha 22
lajbel, 10/9/2025, from sponges factory
Hey! lajbel here to introduce you the 4000.0.0-alpha.22 and this new blog format, where we gonna talk about the specific releases in the KAPLAY repository.
To install it, you can use:
npm install kaplay@4000.0.0-alpha.22
There’s a new super cool thing called Advanced TypeScript features, a new API that will let you use TypeScript in a more powerful way, getting autocomplete in places where before it has been impossible, until now:

In the other side, we got constraints, a way to restrict the movement of game objects.

A lot of more was added, like improvements in Animation API, new AI methods and new ways to transform objects (with skew). Thanks to all contributors helping with KAPLAY. I’ll leave you with the full changelog.
[4000.0.0-alpha.22] - 2025-10-9
Added
-
Added
KAPLAYOpt.types,kaplayTypes()andOptto config specific TypeScript Advanced Features (TAF) - @lajbelkaplay({ 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.scenesto type scenes and parameters - @lajbelconst 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:
-
Added
TypesOpt.strictScenesto make usable scenes just the ones defined - @lajbelconst 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 aBlob- @dragoncoder047 -
Added
getButtons()to get the input binding buttons definition - @lajbel -
Added
RuleSystem,DecisionTreeandStateMachinefor 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), ]); - (!)
KAPLAYCtxdoesn’t use generics anymore. Now,KAPLAYCtxTuses them - @lajbel - Now,
kaplaywill returnKAPLAYCtxorKAPLAYCtxTdepending 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.spriteAtlasPaddingis set to2by default - @lajbel - Transformation and drawing is split now, so the transform can be modified before drawing - @mflerackers