kaplay(gopt?: KAPLAYOpt)

Initialize KAPLAY context. The starting point of all KAPLAY games.
// Start KAPLAY with default options (will create a fullscreen canvas under <body>)
kaplay()

// Init with some options
kaplay({
    width: 320,
    height: 240,
    font: "sans-serif",
    canvas: document.querySelector("#mycanvas"),
    background: [ 0, 0, 255, ],
})

// All KAPLAY functions are imported to global after calling kaplay()
add()
onUpdate()
onKeyPress()
vec2()

// If you want to prevent KAPLAY from importing all functions to global and use a context handle for all KAPLAY functions
const k = kaplay({ global: false })

k.add(...)
k.onUpdate(...)
k.onKeyPress(...)
k.vec2(...)

quit(): void

End everything.

KAPLAYOpt<TPlugin, TButtonDef>:

KAPLAY configurations.

width?: number

Width of game.

height?: number

Height of game.

scale?: number

Pixel scale / size.

stretch?: boolean

If stretch canvas to container when width and height is specified

letterbox?: boolean

When stretching if keep aspect ratio and leave black bars on remaining spaces.

debug?: boolean

If register debug buttons (default true)

debugKey?: Key

Key that toggles debug mode

font?: string

Default font (defaults to "monospace").

pixelDensity?: number

Device pixel scale (defaults to 1, high pixel density will hurt performance).

since

crisp?: boolean

Disable antialias and enable sharp pixel display.

canvas?: HTMLCanvasElement

The canvas DOM element to use. If empty will create one.

root?: HTMLElement

The container DOM element to insert the canvas if created. Defaults to document.body.

background?: RGBValue | RGBAValue | string

Background color. E.g. [ 0, 0, 255 ] for solid blue background, or [ 0, 0, 0, 0 ] for transparent background. Accepts RGB value array or string hex codes.

logMax?: number

How many log messages can there be on one screen (default 8).

logTime?: number

How many seconds log messages stay on screen (default 4).

since

hashGridSize?: number

Size of the spatial hash grid for collision detection (default 64).

since

touchToMouse?: boolean

If translate touch events as mouse clicks (default true).

loadingScreen?: boolean

If KAPLAY should render a default loading screen when assets are not fully ready (default true).

since

backgroundAudio?: boolean

If pause audio when tab is not active (default false).

since

gamepads?: Record<string, GamepadDef>

Custom gamepad definitions (see gamepad.json for reference of the format).

since

buttons?: TButtonDef

Defined buttons for input binding.

since

maxFPS?: number

Limit framerate to an amount per second.

since

focus?: boolean

If focus on the canvas on start (default true).

since

global?: boolean

If import all KAPLAY functions to global (default true).

plugins?: TPlugin

List of plugins to import.

burp?: boolean

Enter burp mode.

loadRoot(path?: string): string

Sets the root for all subsequent resource urls.
loadRoot("https://myassets.com/")
loadSprite("bean", "sprites/bean.png") // will resolve to "https://myassets.com/sprites/bean.png"

loadSprite(name: string | null, src: LoadSpriteSrc | LoadSpriteSrc[], options?: LoadSpriteOpt): Asset<SpriteData>

Load a sprite into asset manager, with name and resource url and optional config.
// due to browser policies you'll need a static file server to load local files
loadSprite("bean", "bean.png")
loadSprite("apple", "https://kaboomjs.com/sprites/apple.png")

// slice a spritesheet and add anims manually
loadSprite("bean", "bean.png", {
    sliceX: 4,
    sliceY: 1,
    anims: {
        run: {
            from: 0,
            to: 3,
        },
        jump: {
            from: 3,
            to: 3,
        },
    },
})

loadSpriteAtlas(src: LoadSpriteSrc, data: SpriteAtlasData): Asset<Record>

Load sprites from a sprite atlas.
// See #SpriteAtlasData type for format spec
loadSpriteAtlas("sprites/dungeon.png", {
    "hero": {
        x: 128,
        y: 68,
        width: 144,
        height: 28,
        sliceX: 9,
        anims: {
            idle: { from: 0, to: 3 },
            run: { from: 4, to: 7 },
            hit: 8,
        },
    },
})

const player = add([
    sprite("hero"),
])

player.play("run")

loadSpriteAtlas(src: LoadSpriteSrc, url: string): Asset<Record>

Load sprites from a sprite atlas with URL.
// Load from json file, see #SpriteAtlasData type for format spec
loadSpriteAtlas("sprites/dungeon.png", "sprites/dungeon.json")

const player = add([
    sprite("hero"),
])

player.play("run")

loadAseprite(name: string | null, imgSrc: LoadSpriteSrc, jsonSrc: string | AsepriteData): Asset<SpriteData>

Load a sprite with aseprite spritesheet json (should use "array" in the export options).
loadAseprite("car", "sprites/car.png", "sprites/car.json")

loadPedit(name: string | null, src: string): Asset<SpriteData>

loadBean(name?: string): Asset<SpriteData>

Load default sprite "bean".
loadBean()

// use it right away
add([
    sprite("bean"),
])

loadJSON(name: string | null, url: string): Asset<any>

Load custom JSON data from url.

since

loadSound(name: string | null, src: string | ArrayBuffer | AudioBuffer): Asset<SoundData>

Load a sound into asset manager, with name and resource url.
loadSound("shoot", "/sounds/horse.ogg")
loadSound("shoot", "/sounds/squeeze.mp3")
loadSound("shoot", "/sounds/shoot.wav")

loadMusic(name: string | null, url: string): void

Like loadSound(), but the audio is streamed and won't block loading. Use this for big audio files like background music.
loadMusic("shoot", "/music/bossfight.mp3")

loadFont(name: string, src: string | BinaryData, opt?: LoadFontOpt): Asset<FontData>

Load a font (any format supported by the browser, e.g. ttf, otf, woff).

since

// load a font from a .ttf file
loadFont("frogblock", "fonts/frogblock.ttf")

loadBitmapFont(name: string | null, src: string, gridWidth: number, gridHeight: number, options?: LoadBitmapFontOpt): Asset<BitmapFontData>

Load a bitmap font into asset manager, with name and resource url and information on the layout of the bitmap.

since

// load a bitmap font called "04b03", with bitmap "fonts/04b03.png"
// each character on bitmap has a size of (6, 8), and contains default ASCII_CHARS
loadBitmapFont("04b03", "fonts/04b03.png", 6, 8)

// load a font with custom characters
loadBitmapFont("myfont", "myfont.png", 6, 8, { chars: "☺☻♥♦♣♠" })

loadShader(name: string | null, vert?: string | null, frag?: string | null): Asset<ShaderData>

Load a shader with vertex and fragment code.
// default shaders and custom shader format
loadShader("outline",
`vec4 vert(vec2 pos, vec2 uv, vec4 color) {
    // predefined functions to get the default value by KAPLAY
    return def_vert();
}`,
`vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
    // turn everything blue-ish
    return def_frag() * vec4(0, 0, 1, 1);
}`, false)

loadShaderURL(name: string | null, vert?: string | null, frag?: string | null): Asset<ShaderData>

Load a shader with vertex and fragment code file url.

since

// load only a fragment shader from URL
loadShader("outline", null, "/shaders/outline.glsl", true)

load<T>(l: Promise): Asset<T>

Add a new loader to wait for before starting the game.
load(new Promise((resolve, reject) => {
    // anything you want to do that stalls the game in loading state
    resolve("ok")
}))

loadProgress(): number

Get the global asset loading progress (0.0 - 1.0).

since

getSprite(name: string): Asset | null

Get SpriteData from name.

since

getSound(name: string): Asset | null

Get SoundData from name.

since

getFont(name: string): Asset | null

Get FontData from name.

since

getBitmapFont(name: string): Asset | null

Get BitmapFontData from name.

since

getShader(name: string): Asset | null

Get ShaderData from name.

since

getAsset(name: string): Asset | null

Get custom data from name.

since

SpriteData:

from(src: LoadSpriteSrc, opt?: LoadSpriteOpt): Promise<SpriteData>

fromImage(data: ImageSource, opt?: LoadSpriteOpt): SpriteData

fromURL(url: string, opt?: LoadSpriteOpt): Promise<SpriteData>

add<T>(comps?: CompList | GameObj): GameObj<T>

Assemble a game object from a list of components, and add it to the game

returns

const player = add([
    // List of components, each offers a set of functionalities
    sprite("mark"),
    pos(100, 200),
    area(),
    body(),
    health(8),
    // Plain strings are tags, a quicker way to let us define behaviors for a group
    "player",
    "friendly",
    // Components are just plain objects, you can pass an object literal as a component.
    {
        dir: LEFT,
        dead: false,
        speed: 240,
    },
])

// .jump is provided by body()
player.jump()

// .moveTo is provided by pos()
player.moveTo(300, 200)

// .onUpdate() is on every game object, it registers an event that runs every frame
player.onUpdate(() => {
    // .move() is provided by pos()
    player.move(player.dir.scale(player.speed))
})

// .onCollide is provided by area()
player.onCollide("tree", () => {
    destroy(player)
})

make<T>(comps?: CompList): GameObj<T>

Create a game object like add(), but not adding to the scene.

since

const label = make([
    text("oh hi"),
])

add([
    rect(label.width, label.height),
    color(0, 0, 255),
    children(label),
])

readd(obj: GameObj): void

Remove and re-add the game obj, without triggering add / destroy events.
// Common way to use this is to have one sprite overlap another sprite, and use readd() to have the bottom sprite on top of the other.

// Create two sprites.
const greenBean = add([
    sprite("bean"),
    pos(200,140),
    color(255, 255, 255),
    area(),
]);

// This bean will overlap the green bean.
const purpleBean = add([
    sprite("bean"),
    pos(230,140),
    color(255, 0, 255),
    area(),
]);

// Example 1: simply call readd() on the target you want on top.
readd(greenBean);

// Example 2: using onClick() or other functions with readd().
// If you comment out the first example, and use this readd() with a function like onClick(), you
can keep switching which sprite is above the other ( click on edge of face ).

purpleBean.onClick(() => {
    readd(greenBean)
});

greenBean.onClick(() => {
    readd(purpleBean)
});

get(tag: Tag | Tag[], opts?: GetOpt): GameObj[]

Get a list of all game objs with certain tag.
// get a list of all game objs with tag "bomb"
const allBombs = get("bomb")

// To get all objects use "*"
const allObjs = get("*")

// Recursively get all children and descendents
const allObjs = get("*", { recursive: true })

query(opt: QueryOpt): GameObj[]

Get a list of game objects in an advanced way.
const bean = k.add(["friend", "bean"]);
const bean2 = k.add(["friend", "bean"]);
const bag = k.add(["friend", "bag"]);

// get bean
query({
    include: "bean",
}) // will return [bean, bean2];

// get all friends excluding bean
query({
    include: "friend",
    exclude: "bean",
}); // will return [bag]

destroy(obj: GameObj): void

Remove the game obj.
// every time bean collides with anything with tag "fruit", remove it
bean.onCollide("fruit", (fruit) => {
    destroy(fruit)
})

destroyAll(tag: Tag): void

Remove all game objs with certain tag.
// destroy all objects with tag "bomb" when you click one
onClick("bomb", () => {
    destroyAll("bomb")
})

GameObjRaw:

Base interface of all game objects.

add<T>(comps?: CompList | GameObj): GameObj<T>

Add a child.

since

readd<T>(obj: GameObj): GameObj<T>

Remove and re-add the game obj, without triggering add / destroy events.

remove(obj: GameObj): void

Remove a child.

since

removeAll(tag: Tag): void

Remove all children with a certain tag.

since

get(tag: Tag | Tag[], opts?: GetOpt): GameObj[]

Get a list of all game objs with certain tag.

since

query(opt: QueryOpt): GameObj[]

Get a list of all game objs with certain properties.

since

children: GameObj[]

Get all children game objects.

since

tags: string[]

Get the tags of a game object.

since

fixedUpdate(): void

Update this game object and all children game objects.

since

update(): void

Update this game object and all children game objects.

since

draw(): void

Draw this game object and all children game objects.

since

drawInspect(): void

Draw debug info in inspect mode

since

is(tag: Tag | Tag[]): boolean

If there's certain tag(s) on the game obj.

use(comp: Comp | Tag): void

Add a component or tag.

unuse(comp: Tag): void

Remove a tag or a component with its id.

on(event: string, action: (args: any)=>void): KEventController

Register an event.

trigger(event: string, args: any): void

Trigger an event.

destroy(): void

Remove the game obj from scene.

c(id: Tag): Comp | null

Get state for a specific comp.

inspect(): GameObjInspect

Gather debug info of all comps.

onAdd(action: ()=>void): KEventController

Register an event that runs when the game obj is added to the scene.

onUpdate(action: ()=>void): KEventController

Register an event that runs every frame as long as the game obj exists.

since

onDraw(action: ()=>void): KEventController

Register an event that runs every frame as long as the game obj exists (this is the same as `onUpdate()`, but all draw events are run after all update events).

since

onDestroy(action: ()=>void): KEventController

Register an event that runs when the game obj is destroyed.

since

exists(): boolean

If game obj is attached to the scene graph.

isAncestorOf(obj: GameObj): boolean

Check if is an ancestor (recursive parent) of another game object

since

transform: Mat4

Calculated transform matrix of a game object.

since

hidden: boolean

If draw the game obj (run "draw" event or not).

paused: boolean

If update the game obj (run "update" event or not).

id: GameObjID | null

A unique number ID for each game object.

canvas: FrameBuffer | null

The canvas to draw this game object on

since

GameObj<T>: GameObjRaw & MergeComps

The basic unit of object in KAPLAY. The player, a butterfly, a tree, or even a piece of text.

pos(x: number, y: number): PosComp

Set the position of a Game Object.
// This game object will draw a "bean" sprite at (100, 200)
add([
    pos(100, 200),
    sprite("bean"),
])

pos(xy: number): PosComp

pos(p: Vec2): PosComp

scale(x: number, y: number): ScaleComp

Set the scale of a Game Object.
// scale uniformly with one value
add([
    sprite("bean"),
	   scale(3),
])
// scale with x & y values. In this case, scales more horizontally.
add([
    sprite("bean"),
	   scale(3, 1),
])
 // scale with vec2(x,y).
bean.scale = vec2(2,4)

scale(xy: number): ScaleComp

scale(s: Vec2): ScaleComp

rotate(a?: number): RotateComp

Rotates a Game Object (in degrees).

param

color(r: number, g: number, b: number): ColorComp

Sets the color of a Game Object (rgb 0-255).
// blue frog
add([
    sprite("bean"),
    color(0, 0, 255)
])

color(c: Color): ColorComp

color(rgb: [number, number, number]): ColorComp

color(c: string): ColorComp

opacity(o?: number): OpacityComp

Sets the opacity of a Game Object (0.0 - 1.0).
const bean = add([
    sprite("bean"),
    opacity(0.5) // Make bean 50% transparent
])

// Make bean invisible
bean.opacity = 0

// Make bean fully visible
bean.opacity = 1

sprite(spr: string | SpriteData | Asset, options?: SpriteCompOpt): SpriteComp

Attach and render a sprite to a Game Object.
// minimal setup
add([
    sprite("bean"),
])

// with options
const bean = add([
    sprite("bean", {
        // start with animation "idle"
        anim: "idle",
    }),
])

// play / stop an anim
bean.play("jump")
bean.stop()

// manually setting a frame
bean.frame = 3

text(txt?: string, options?: TextCompOpt): TextComp

Attach and render a text to a Game Object.

param

// a simple score counter
const score = add([
    text("Score: 0"),
    pos(24, 24),
    { value: 0 },
])

player.onCollide("coin", () => {
    score.value += 1
    score.text = "Score:" + score.value
})

// with options
add([
    pos(24, 24),
    text("ohhi", {
        size: 48, // 48 pixels tall
        width: 320, // it'll wrap to next line when width exceeds this value
        font: "sans-serif", // specify any font you loaded or browser built-in
    }),
])

polygon(pts: Vec2[], opt?: PolygonCompOpt): PolygonComp

Attach and render a polygon to a Game Object.

since

// Make a square the hard way
add([
    pos(80, 120),
    polygon([vec2(0,0), vec2(50,0), vec2(50,50), vec2(0,50)]),
    outline(4),
    area(),
])

rect(w: number, h: number, opt?: RectCompOpt): RectComp

Attach and render a rectangle to a Game Object.
const obstacle = add([
    pos(80, 120),
    rect(20, 40),
    outline(4),
    area(),
])

circle(radius: number, opt?: CircleCompOpt): CircleComp

Attach and render a circle to a Game Object.
add([
    pos(80, 120),
    circle(16),
])

uvquad(w: number, h: number): UVQuadComp

Attach and render a UV quad to a Game Object.
add([
    uvquad(width(), height()),
    shader("spiral"),
])

area(): AreaComp

Attach a collider area from shape and enables collision detection in a Game Object.
// Automatically generate area information from the shape of render
const player = add([
    sprite("bean"),
    area(),
])

// Die if player collides with another game obj with tag "tree"
player.onCollide("tree", () => {
    destroy(player)
    go("lose")
})

// Check for collision manually every frame instead of registering an event
player.onUpdate(() => {
    if (player.isColliding(bomb)) {
        score += 1
    }
})

area(options: AreaCompOpt): AreaComp

anchor(o: Anchor | Vec2): AnchorComp

Anchor point for render (default "topleft").
// set anchor to "center" so it'll rotate from center
add([
    rect(40, 10),
    rotate(45),
    anchor("center"),
])

z(z: number): ZComp

Determines the draw order for objects on the same layer. Object will be drawn on top if z value is bigger.
const bean = add([
   sprite("bean"),
   pos(100, 100),
   z(10), // Bean has a z value of 10
])

// Mark has a z value of 20, so he will always be drawn on top of bean
const mark = add([
  sprite("mark"),
  pos(100, 100),
  z(20),
])

bean.z = 30 // Bean now has a higher z value, so it will be drawn on top of mark

layer(name: string): LayerComp

Determines the layer for objects. Object will be drawn on top if the layer index is higher.
// Define layers
layers(["background", "game", "foreground"], "game")

const bean = add([
    sprite("bean"),
    pos(100, 100),
    layer("background"),
])

// Mark is in a higher layer, so he will be drawn on top of bean
const mark = add([
    sprite("mark"),
    pos(100, 100),
    layer("game"),
])

bean.layer("foreground") // Bean is now in the foreground layer and will be drawn on top of mark

outline(width?: number, color?: Color, opacity?: number, join?: LineJoin, miterLimit?: number, cap?: LineCap): OutlineComp

Give obj an outline.

particles(popt: ParticlesOpt, eopt: EmitterOpt): ParticlesComp

Attach a particle emitter to a Game Object.

param

// beansplosion

// create the emitter
const emitter = add([
    pos(center()),
    particles({
        max: 100,
        speed: [75, 100],
        lifeTime: [0.75,1.0],
        angle: [0, 360],
        opacities: [1.0, 0.0],
        texture: getSprite("bean").tex,   // texture of a sprite
        quads: getSprite("bean").frames,  // frames of a sprite
    }, {
        direction: 0,
        spread: 360,
    }),
])

onUpdate(() => {
    emitter.emit(1)
})

since

body(options?: BodyCompOpt): BodyComp

Physical body that responds to gravity. Requires "area" and "pos" comp. This also makes the object "solid".
// bean jumpy
const bean = add([
    sprite("bean"),
    // body() requires "pos" and "area" component
    pos(),
    area(),
    body(),
])

// when bean is grounded, press space to jump
// check out #BodyComp for more methods
onKeyPress("space", () => {
    if (bean.isGrounded()) {
        bean.jump()
    }
})

// run something when bean falls and hits a ground
bean.onGround(() => {
    debug.log("oh no!")
})

surfaceEffector(options: SurfaceEffectorCompOpt): SurfaceEffectorComp

Applies a force on a colliding object in order to make it move along the collision tangent vector. Good for conveyor belts.
loadSprite("belt", "/sprites/jumpy.png")

// conveyor belt
add([
    pos(center()),
    sprite("belt"),
    rotate(90),
    area(),
    body({ isStatic: true }),
    surfaceEffector({
        speed: 50,
    })
])

since

areaEffector(options: AreaEffectorCompOpt): AreaEffectorComp

Applies a force on a colliding object. Good to apply anti-gravity, wind or water flow.

since

pointEffector(options: PointEffectorCompOpt): PointEffectorComp

Applies a force on a colliding object directed towards this object's origin. Good to apply magnetic attraction or repulsion.

since

buoyancyEffector(options: BuoyancyEffectorCompOpt): BuoyancyEffectorComp

Applies an upwards force (force against gravity) to colliding objects depending on the fluid density and submerged area. Good to apply constant thrust.

since

constantForce(opts: ConstantForceCompOpt): ConstantForceComp

Applies a constant force to the object. Good to apply constant thrust.

since

doubleJump(numJumps?: number): DoubleJumpComp

Enables double jump. Requires "body" component.

since

move(direction: number | Vec2, speed: number): EmptyComp

Move towards a direction infinitely, and destroys when it leaves game view. Requires "pos" component.
// enemy throwing feces at player
const projectile = add([
    sprite("feces"),
    pos(enemy.pos),
    area(),
    move(player.pos.angle(enemy.pos), 1200),
    offscreen({ destroy: true }),
])

offscreen(opt?: OffScreenCompOpt): OffScreenComp

Control the behavior of object when it goes out of view.

since

add([
    pos(player.pos),
    sprite("bullet"),
    offscreen({ destroy: true }),
    "projectile",
])

follow(obj: GameObj | null, offset?: Vec2): FollowComp

Follow another game obj's position.
const bean = add(...)

add([
  sprite("bag"),
  pos(),
  follow(bean) // Follow bean's position
])
``````js
const target = add(...)

const mark = add([
  sprite("mark"),
  pos(),
  follow(target, vec2(32, 32)) // Follow target's position with an offset
])

mark.follow.offset = vec2(64, 64) // Change the offset

shader(id: string, uniform?: Uniform | ()=>Uniform): ShaderComp

Custom shader.

textInput(hasFocus?: boolean, maxInputLength?: number): TextInputComp

Get input from the user and store it in the nodes text property, displaying it with the text component and allowing other functions to access it.
const obj = add([
    text(""),
    textInput(),
])

obj.hasFocus = false
debug.log(obj.text) // oh no i cant see my new text since it was disabled

timer(): TimerComp

Enable timer related functions like wait(), loop(), tween() on the game object.
const obj = add([
    timer(),
])

obj.wait(2, () => { ... })
obj.loop(0.5, () => { ... })
obj.tween(obj.pos, mousePos(), 0.5, (p) => obj.pos = p, easings.easeOutElastic)

fixed(): FixedComp

Make object unaffected by camera or parent object transforms, and render at last.
// this will be be fixed on top left and not affected by camera
const score = add([
    text(0),
    pos(12, 12),
    fixed(),
])

stay(scenesToStay?: string[]): StayComp

Don't get destroyed on scene switch. Only works in objects attached to root.
player.onCollide("bomb", () => {
    // spawn an explosion and switch scene, but don't destroy the explosion game obj on scene switch
    add([
        sprite("explosion", { anim: "burst", }),
        stay(),
        lifespan(1),
    ])
    go("lose", score)
})

health(hp: number, maxHP?: number): HealthComp

Handles health related logic and events.
const player = add([
    health(3),
])

player.onCollide("bad", (bad) => {
    player.hurt(1)
    bad.hurt(1)
})

player.onCollide("apple", () => {
    player.heal(1)
})

player.on("hurt", () => {
    play("ouch")
})

// triggers when hp reaches 0
player.on("death", () => {
    destroy(player)
    go("lose")
})

lifespan(time: number, options?: LifespanCompOpt): EmptyComp

Destroy the game obj after certain amount of time
// spawn an explosion, destroy after 1 seconds, start fading away after 0.5 second
add([
    sprite("explosion", { anim: "burst", }),
    lifespan(1, { fade: 0.5 }),
])

named(name: string): NamedComp

Names an object.

since

state(initialState: string, stateList?: string[]): StateComp

Finite state machine.

since

const enemy = add([
    pos(80, 100),
    sprite("robot"),
    state("idle", ["idle", "attack", "move"]),
])

// this callback will run once when enters "attack" state
enemy.onStateEnter("attack", () => {
    // enter "idle" state when the attack animation ends
    enemy.play("attackAnim", {
        // any additional arguments will be passed into the onStateEnter() callback
        onEnd: () => enemy.enterState("idle", rand(1, 3)),
    })
    checkHit(enemy, player)
})

// this will run once when enters "idle" state
enemy.onStateEnter("idle", (time) => {
    enemy.play("idleAnim")
    wait(time, () => enemy.enterState("move"))
})

// this will run every frame when current state is "move"
enemy.onStateUpdate("move", () => {
    enemy.follow(player)
    if (enemy.pos.dist(player.pos) < 16) {
        enemy.enterState("attack")
    }
})

state(initialState: string, stateList: string[], transitions: Record): StateComp

state() with pre-defined transitions.

since

const enemy = add([
    pos(80, 100),
    sprite("robot"),
    state("idle", ["idle", "attack", "move"], {
        "idle": "attack",
        "attack": "move",
        "move": [ "idle", "attack" ],
    }),
])

// this callback will only run once when enter "attack" state from "idle"
enemy.onStateTransition("idle", "attack", () => {
    checkHit(enemy, player)
})

fadeIn(time: number): Comp

Fade object in. Uses opacity for finding what to fade into and to set opacity during fade animation.

since

deprecated

mask(maskType?: Mask): MaskComp

Mask all children object render.

since

tile(opt?: TileCompOpt): TileComp

A tile on a tile map.

since

agent(opt?: AgentCompOpt): AgentComp

An agent which can finds it way on a tilemap.

since

animate(opt?: AnimateCompOpt): AnimateComp

A component to animate properties.

since

sentry(candidates: SentryCandidates, opt?: SentryCompOpt): SentryComp

A sentry which reacts to objects coming into view.

since

patrol(opts: PatrolCompOpt): PatrolComp

A patrol which can follow waypoints to a goal.

since

pathfinder(opts: PathfinderCompOpt): PathfinderComp

A navigator pathfinder which can calculate waypoints to a goal.

since

Comp:

id?: Tag

Component ID (if left out won't be treated as a comp).

require?: Tag[]

What other comps this comp depends on.

add?(): void

Event that runs when host game obj is added to scene.

fixedUpdate?(): void

Event that runs at a fixed frame rate.

update?(): void

Event that runs every frame.

draw?(): void

Event that runs every frame after update.

destroy?(): void

Event that runs when obj is removed from scene.

inspect?(): string | null

Debug info for inspect mode.

drawInspect?(): void

Draw debug info in inspect mode

since

CircleCompOpt:

Options for the circle component.

fill?: boolean

If fill the circle (useful if you only want to render outline with outline component).

OpacityComp:

The opacity component.

opacity: number

Opacity of the current object.

fadeIn(time?: number, easeFunc?: EaseFunc): TweenController

Fade in at the start.

fadeOut(time?: number, easeFunc?: EaseFunc): TweenController

Fade out at the start.

PolygonComp:

The polygon component.

since

pts: Vec2[]

Points in the polygon.

radius?: number | number[]

The radius of each corner.

colors?: Color[]

The color of each vertex.

uv?: Vec2[]

The uv of each vertex.

since

tex?: Texture

The texture used when uv coordinates are present.

since

PolygonCompOpt: Omit<DrawPolygonOpt, pts>

Options for the polygon component.

RectComp:

The rect component.

width: number

Width of rectangle.

height: number

Height of rectangle.

radius?: number | [number, number, number, number]

The radius of each corner.

RectCompOpt:

Options for the rect component.

radius?: number | [number, number, number, number]

Radius of the rectangle corners.

fill?: boolean

If fill the rectangle (useful if you only want to render outline with outline() component).

SpriteComp:

The sprite component.

sprite: string

Name of the sprite.

width: number

Width for sprite.

height: number

Height for sprite.

frame: number

Current frame in the entire spritesheet.

animFrame: number

Current frame in relative to the animation that is currently playing.

quad: Quad

The rectangular area of the texture to render.

play(anim: string, options?: SpriteAnimPlayOpt): void

Play a piece of anim.

stop(): void

Stop current anim.

numFrames(): number

Get total number of frames.

getCurAnim(): SpriteCurAnim | null

Get the current animation data.

since

curAnim(): string | undefined

Get current anim name.

deprecated

hasAnim(name: string): boolean

Check if object's sprite has an animation.

getAnim(name: string): SpriteAnim | null

Get an animation.

animSpeed: number

Speed multiplier for all animations (for the actual fps for an anim use .play("anim", { speed: 10 })).

flipX: boolean

Flip texture horizontally.

flipY: boolean

Flip texture vertically.

onAnimStart(action: (anim: string)=>void): KEventController

Register an event that runs when an animation is played.

onAnimEnd(action: (anim: string)=>void): KEventController

Register an event that runs when an animation is ended.

SpriteCompOpt:

Options for the sprite component.

frame?: number

If the sprite is loaded with multiple frames, or sliced, use the frame option to specify which frame to draw.

tiled?: boolean

If provided width and height, don't stretch but instead render tiled.

width?: number

Stretch sprite to a certain width.

height?: number

Stretch sprite to a certain height.

anim?: string

Play an animation on start.

animSpeed?: number

Speed multiplier for all animations (for the actual fps for an anim use .play("anim", { speed: 10 })).

flipX?: boolean

Flip texture horizontally.

flipY?: boolean

Flip texture vertically.

quad?: Quad

The rectangular sub-area of the texture to render, default to full texture `quad(0, 0, 1, 1)`.

fill?: boolean

If fill the sprite (useful if you only want to render outline with outline() component).

TextComp:

The text component.

text: string

The text to render.

font: string | BitmapFontData

The font to use.

width: number

Width of text.

align: TextAlign

Text alignment ("left", "center" or "right", default "left").

since

textTransform: CharTransform | CharTransformFunc

Transform the pos, scale, rotation or color for each character based on the index or char.

since

textStyles: Record<string, CharTransform | CharTransformFunc>

Stylesheet for styled chunks, in the syntax of "this is a [style]text[/style] word".

since

TextCompOpt:

Options for the text component.

size?: number

Height of text.

font?: string | BitmapFontData

The font to use.

width?: number

Wrap text to a certain width.

align?: TextAlign

Text alignment ("left", "center" or "right", default "left").

since

transform?: CharTransform | CharTransformFunc

Transform the pos, scale, rotation or color for each character based on the index or char.

since

styles?: Record<string, CharTransform | CharTransformFunc>

Stylesheet for styled chunks, in the syntax of "this is a [style]text[/style] word".

since

FixedComp:

The fixed component.

fixed: boolean

If the obj is unaffected by camera

PosComp:

The pos component.

pos: Vec2

Object's current world position.

move(xVel: number, yVel: number): void

Move how many pixels per second. If object is 'solid', it won't move into other 'solid' objects.

move(vel: Vec2): void

moveBy(dx: number, dy: number): void

Move how many pixels, without multiplying dt, but still checking for 'solid'.

moveTo(dest: Vec2, speed?: number): void

Move to a spot with a speed (pixels per second), teleports if speed is not given.

moveTo(x: number, y: number, speed?: number): void

screenPos(): Vec2 | null

Get the position of the object on the screen.

worldPos(): Vec2 | null

Get the position of the object relative to the root.

toScreen(this: GameObj, p: Vec2): Vec2

Transform a local point (relative to this) to a screen point (relative to the camera)

toWorld(this: GameObj, p: Vec2): Vec2

Transform a local point (relative to this) to a world point (relative to the root)

since

fromScreen(this: GameObj, p: Vec2): Vec2

Transform a screen point (relative to the camera) to a local point (relative to this)

since

fromWorld(this: GameObj, p: Vec2): Vec2

Transform a world point (relative to the root) to a local point (relative to this)

since

toOther(this: GameObj, other: GameObj, p: Vec2): Vec2

Transform a point relative to this to a point relative to other

since

fromOther(this: GameObj, other: GameObj, p: Vec2): Vec2

Transform a point relative to other to a point relative to this

since

SentryComp:

The sentry component.

onObjectsSpotted(cb: (objects: GameObj[])=>void): KEventController

Attaches an event handler which is called when objects of interest are spotted.

param

isWithinFieldOfView(obj: GameObj, direction?: Vec2, fieldOfView?: number): boolean

Returns true if the object is within the field of view.

param

hasLineOfSight(obj: GameObj): boolean

Returns true if there is a line of sight to the object.

param

TileCompOpt:

isObstacle?: boolean

If the tile is an obstacle in pathfinding.

cost?: number

How much a tile is cost to traverse in pathfinding (default 0).

edges?: Edge[]

If the tile has hard edges that cannot pass in pathfinding.

offset?: Vec2

Position offset when setting `tilePos`.

Options for the tile component.

HealthComp:

The health component.

hurt(n?: number): void

Decrease HP by n (defaults to 1).

heal(n?: number): void

Increase HP by n (defaults to 1).

hp(): number

Current health points.

setHP(hp: number): void

Set current health points.

maxHP(): number | null

Max amount of HP.

setMaxHP(hp: number): void

Set max amount of HP.

onHurt(action: (amount?: number)=>void): KEventController

Register an event that runs when hurt() is called upon the object.

since

onHeal(action: (amount?: number)=>void): KEventController

Register an event that runs when heal() is called upon the object.

since

onDeath(action: ()=>void): KEventController

Register an event that runs when object's HP is equal or below 0.

since

LifespanCompOpt:

The lifespan component.

fade?: number

Fade out duration (default 0 which is no fade out).

StateComp:

The state component.

state: string

Current state.

enterState(state: string, args: any): void

Enter a state, trigger onStateEnd for previous state and onStateEnter for the new State state.

onStateTransition(from: string, to: string, action: ()=>void): KEventController

Register event that runs once when a specific state transition happens. Accepts arguments passed from `enterState(name, ...args)`.

since

onStateEnter(state: string, action: (args: any)=>void): KEventController

Register event that runs once when enters a specific state. Accepts arguments passed from `enterState(name, ...args)`.

onStateEnd(state: string, action: ()=>void): KEventController

Register an event that runs once when leaves a specific state.

onStateUpdate(state: string, action: ()=>void): KEventController

Register an event that runs every frame when in a specific state.

onStateDraw(state: string, action: ()=>void): KEventController

Register an event that runs every frame when in a specific state.

StayComp:

The stay component.

stay: boolean

If the obj should not be destroyed on scene switch.

scenesToStay?: string[]

Array of scenes that the obj will stay on.

TextInputComp:

The stay component.

hasFocus: boolean

Enable the text input array from being modified by user input.

TimerComp:

The timer component.

wait(time: number, action?: ()=>void): TimerController

Run the callback after n seconds.

loop(time: number, action: ()=>void): KEventController

Run the callback every n seconds.

since

tween<V>(from: V, to: V, duration: number, setValue: (value: V)=>void, easeFunc?: (t: number)=>number): TweenController

Tweeeeen! Note that this doesn't specifically mean tweening on this object's property, this just registers the timer on this object, so the tween will cancel with the object gets destroyed, or paused when obj.paused is true.

since

AreaComp:

The area component.

area:

shape: Shape | null

If we use a custom shape over render shape.

cursor: Cursor | null

Cursor on hover.

Collider area info.

collisionIgnore: Tag[]

If this object should ignore collisions against certain other objects.

since

isClicked(): boolean

If was just clicked on last frame.

checkCollision(other: GameObj): Collision | null

Check collision with another game obj.

since

getCollisions(): Collision[]

Get all collisions currently happening.

since

isColliding(o: GameObj): boolean

If is currently colliding with another game obj.

isOverlapping(o: GameObj): boolean

If is currently overlapping with another game obj (like isColliding, but will return false if the objects are just touching edges).

onClick(f: ()=>void, btn?: MouseButton): void

Register an event runs when clicked.

since

onHover(action: ()=>void): KEventController

Register an event runs once when hovered.

since

onHoverUpdate(action: ()=>void): KEventController

Register an event runs every frame when hovered.

since

onHoverEnd(action: ()=>void): KEventController

Register an event runs once when unhovered.

since

onCollide(tag: Tag, f: (obj: GameObj, col?: Collision)=>void): void

Register an event runs once when collide with another game obj with certain tag.

since

onCollide(f: (obj: GameObj, col?: Collision)=>void): void

Register an event runs once when collide with another game obj.

since

onCollideUpdate(tag: Tag, f: (obj: GameObj, col?: Collision)=>void): KEventController

Register an event runs every frame when collide with another game obj with certain tag.

since

onCollideUpdate(f: (obj: GameObj, col?: Collision)=>void): KEventController

Register an event runs every frame when collide with another game obj.

since

onCollideEnd(tag: Tag, f: (obj: GameObj)=>void): KEventController

Register an event runs once when stopped colliding with another game obj with certain tag.

since

onCollideEnd(f: (obj: GameObj)=>void): void

Register an event runs once when stopped colliding with another game obj.

since

hasPoint(p: Vec2): boolean

If has a certain point inside collider.

resolveCollision(obj: GameObj): void

Push out from another solid game obj if currently overlapping.

localArea(): Shape

Get the geometry data for the collider in local coordinate space.

since

worldArea(): Polygon

Get the geometry data for the collider in world coordinate space.

screenArea(): Polygon

Get the geometry data for the collider in screen coordinate space.

AreaCompOpt:

Options for the area component.

shape?: Shape

The shape of the area (currently only Rect and Polygon is supported).
add([
    sprite("butterfly"),
    pos(100, 200),
    // a triangle shape!
    area({ shape: new Polygon([vec2(0), vec2(100), vec2(-100, 100)]) }),
])

scale?: number | Vec2

Area scale.

cursor?: Cursor

Cursor on hover.

collisionIgnore?: Tag[]

If this object should ignore collisions against certain other objects.

since

BodyComp:

The body component.

vel: Vec2

Object current velocity.

since

drag: number

How much velocity decays (velocity *= (1 - drag) every frame).

since

isStatic: boolean

If object is static, won't move, and all non static objects won't move past it.

jumpForce: number

Initial speed in pixels per second for jump().

mass: number

Mass of the body, decides how much a non-static body should move when resolves with another non-static body. (default 1).

since

stickToPlatform?: boolean

If object should move with moving platform (default true).

since

curPlatform(): GameObj | null

Current platform landing on.

isGrounded(): boolean

If currently landing on a platform.

since

isFalling(): boolean

If currently falling.

since

isJumping(): boolean

If currently rising.

since

addForce(force: Vec2): void

Applies a force

param

jump(force?: number): void

Upward thrust.

onPhysicsResolve(action: (col: Collision)=>void): KEventController

Register an event that runs when a collision is resolved.

since

onBeforePhysicsResolve(action: (col: Collision)=>void): KEventController

Register an event that runs before a collision would be resolved.

since

onGround(action: ()=>void): KEventController

Register an event that runs when the object is grounded.

since

onFall(action: ()=>void): KEventController

Register an event that runs when the object starts falling.

since

onFallOff(action: ()=>void): KEventController

Register an event that runs when the object falls off platform.

since

onHeadbutt(action: ()=>void): KEventController

Register an event that runs when the object bumps into something on the head.

since

onLand(action: (obj: GameObj)=>void): KEventController

Register an event that runs when an object lands on this object.

since

onHeadbutted(action: (obj: GameObj)=>void): KEventController

Register an event that runs when the object is bumped by another object head.

BodyCompOpt:

Options for the body component.

drag?: number

How much velocity decays (velocity *= (1 - drag) every frame).

since

jumpForce?: number

Initial speed in pixels per second for jump().

isStatic?: boolean

If object is static, won't move, and all non static objects won't move past it.

since

stickToPlatform?: boolean

If object should move with moving platform (default true).

since

mass?: number

Mass of the body, decides how much a non-static body should move when resolves with another non-static body. (default 1).

since

DoubleJumpComp:

The doubleJump component.

numJumps: number

Number of jumps allowed.

doubleJump(force?: number): void

Performs double jump (the initial jump only happens if player is grounded).

onDoubleJump(action: ()=>void): KEventController

Register an event that runs when the object performs the second jump when double jumping.

AnchorComp:

The anchor component.

anchor: Anchor | Vec2

Anchor point for render.

LayerComp:

The layer component.

layerIndex(): number | null

Get the index of the current layer the object is assigned to.

returns

layer(): string | null

Get the name of the current layer the object is assigned to.

returns

layer(name: string):

Set the name of the layer the object should be assigned to.

OffScreenComp:

The offscreen component.

isOffScreen(): boolean

If object is currently out of view.

onExitScreen(action: ()=>void): KEventController

Register an event that runs when object goes out of view.

onEnterScreen(action: ()=>void): KEventController

Register an event that runs when object enters view.

OffScreenCompOpt:

Options for offscreen component.

hide?: boolean

If hide object when out of view.

pause?: boolean

If pause object when out of view.

destroy?: boolean

If destroy object when out of view.

distance?: number

The distance when out of view is triggered (default 200).

since

RotateComp:

The rotate component.

angle: number

Angle in degrees.

rotateBy(angle: number): void

Rotate in degrees.

rotateTo(s: number): void

Rotate to a degree (like directly assign to .angle)

since

ScaleComp:

The scale component.

scale: Vec2

The current scale of the object

returnsThe current scale of the object as a

scaleTo(s: number): void

Set the scale of the object to a number

scaleTo(s: Vec2): void

Set the scale of the object to a Vec2

scaleTo(sx: number, sy: number): void

Set the scale of the object to a number for x and y

scaleBy(s: number): void

Scale the object by a number

scaleBy(s: Vec2): void

Scale the object by a Vec2

scaleBy(sx: number, sy: number): void

Scale the object by a number for x and y

ZComp:

The z component.

z: number

Defines the z-index of this game obj

MergeComps<T>: Omit<MergeObj, Bug parsing TypeOperator>

A type to merge the components of a game object, omitting the default component properties.

CompList<T>: Array<T | Tag>

A component list.

EmptyComp:

id: string

&
Comp

A component without own properties.

LevelComp:

A level component.

spawn(sym: string, p: Vec2): GameObj | null

Spawn a tile from a symbol defined previously.

spawn(sym: string, x: number, y: number): GameObj | null

spawn<T>(obj: CompList, p: Vec2): GameObj | null

Spawn a tile from a component list.

returns

spawn<T>(sym: CompList, x: number, y: number): GameObj | null

levelWidth(): number

Total width of level in pixels.

getAt(tilePos: Vec2): GameObj[]

Get all game objects that's currently inside a given tile.

raycast(origin: Vec2, direction: Vec2): RaycastResult

Raycast all game objects on the given path.

tile2Pos(tilePos: Vec2): Vec2

Convert tile position to pixel position.

pos2Tile(pos: Vec2): Vec2

Convert pixel position to tile position.

getTilePath(from: Vec2, to: Vec2, opts?: PathFindOpt): Vec2[] | null

Find the path to navigate from one tile to another tile.

returns

getPath(from: Vec2, to: Vec2, opts?: PathFindOpt): Vec2[] | null

Find the path to navigate from one tile to another tile.

returns

getSceneName(): string | null

Gets the name of the current scene. Returns null if no scene is active.

since

scene(id: SceneName, def: SceneDef): void

Define a scene.

go(id: SceneName, args: any): void

Go to a scene, passing all rest args to scene callback.

layers(layers: string[], defaultLayer: string): void

Define the layer names. Should be called before any objects are made.

onGamepadConnect(action: (gamepad: KGamepad)=>void): void

Register an event that runs when a gamepad is connected.

since

onGamepadDisconnect(action: (gamepad: KGamepad)=>void): void

Register an event that runs when a gamepad is disconnected.

since

onClick(tag: Tag, action: (a: GameObj)=>void): KEventController

Register an event that runs when game objs with certain tags are clicked (required to have the area() component).

since

// click on any "chest" to open
onClick("chest", (chest) => chest.open())

onClick(action: ()=>void): KEventController

Register an event that runs when users clicks.
// click on anywhere to go to "game" scene
onClick(() => go("game"))

since

onKeyDown(key: Key | Key[], action: (key: Key)=>void): KEventController

Register an event that runs every frame when a key is held down.
// move left by SPEED pixels per frame every frame when left arrow key is being held down
onKeyDown("left", () => {
    bean.move(-SPEED, 0)
})

since

onKeyDown(action: (key: Key)=>void): KEventController

Register an event that runs every frame when any key is held down.

since

onKeyPress(key: Key | Key[], action: (key: Key)=>void): KEventController

Register an event that runs when user presses certain keys.
// .jump() once when "space" is just being pressed
onKeyPress("space", () => {
    bean.jump()
});

onKeyPress(["up", "space"], () => {
    bean.jump()
});

since

onKeyPress(action: (key: Key)=>void): KEventController

Register an event that runs when user presses any key.
// Call restart() when player presses any key
onKeyPress((key) => {
    debug.log(`key pressed ${key}`)
    restart()
})

since

onKeyPressRepeat(k: Key | Key[], action: (k: Key)=>void): KEventController

Register an event that runs when user presses certain keys (also fires repeatedly when the keys are being held down).
// delete last character when "backspace" is being pressed and held
onKeyPressRepeat("backspace", () => {
    input.text = input.text.substring(0, input.text.length - 1)
})

since

onKeyRelease(k: Key | Key[], action: (k: Key)=>void): KEventController

Register an event that runs when user release certain keys.

since

onCharInput(action: (ch: string)=>void): KEventController

Register an event that runs when user inputs text.

since

// type into input
onCharInput((ch) => {
    input.text += ch
})

onMouseDown(button: MouseButton | MouseButton[], action: (m: MouseButton)=>void): KEventController

Register an event that runs every frame when certain mouse buttons are being held down.

since

onMouseDown(action: (m: MouseButton)=>void): KEventController

onMousePress(action: (m: MouseButton)=>void): KEventController

Register an event that runs when user clicks mouse.

since

onMousePress(button: MouseButton | MouseButton[], action: (m: MouseButton)=>void): KEventController

onMouseRelease(action: (m: MouseButton)=>void): KEventController

Register an event that runs when user releases mouse.

since

onMouseRelease(button: MouseButton | MouseButton[], action: (m: MouseButton)=>void): KEventController

onMouseMove(action: (pos: Vec2, delta: Vec2)=>void): KEventController

Register an event that runs whenever user move the mouse.

since

onTouchStart(action: (pos: Vec2, t: Touch)=>void): KEventController

Register an event that runs when a touch starts.

since

onTouchMove(action: (pos: Vec2, t: Touch)=>void): KEventController

Register an event that runs whenever touch moves.

since

onTouchEnd(action: (pos: Vec2, t: Touch)=>void): KEventController

Register an event that runs when a touch ends.

since

onScroll(action: (delta: Vec2)=>void): KEventController

Register an event that runs when mouse wheel scrolled.
// Zoom camera on scroll
onScroll((delta) => {
    const zoom = delta.y / 500
    camScale(camScale().add(zoom))
})

since

onGamepadButtonDown(btn: KGamepadButton | KGamepadButton[], action: (btn: KGamepadButton, gamepad: KGamepad)=>void): KEventController

Register an event that runs every frame when certain gamepad buttons are held down.

since

onGamepadButtonDown(action: (btn: KGamepadButton, gamepad: KGamepad)=>void): KEventController

Register an event that runs every frame when any gamepad buttons are held down.

since

onGamepadButtonPress(btn: KGamepadButton | KGamepadButton[], action: (btn: KGamepadButton, gamepad: KGamepad)=>void): KEventController

Register an event that runs when user presses certain gamepad button.

since

onGamepadButtonPress(action: (btn: KGamepadButton, gamepad: KGamepad)=>void): KEventController

Register an event that runs when user presses any gamepad button.

since

onGamepadButtonRelease(btn: KGamepadButton | KGamepadButton[], action: (btn: KGamepadButton, gamepad: KGamepad)=>void): KEventController

Register an event that runs when user releases certain gamepad button

since

onGamepadButtonRelease(action: (btn: KGamepadButton, gamepad: KGamepad)=>void): KEventController

Register an event that runs when user releases any gamepad button.

since

onGamepadStick(stick: GamepadStick, action: (value: Vec2, gameepad: KGamepad)=>void): KEventController

Register an event that runs when the gamepad axis exists.

since

onButtonPress(btn: TButton | TButton[], action: (btn: TButton)=>void): KEventController

Register an event that runs when user press a defined button (like "jump") on any input (keyboard, gamepad).

since

onButtonRelease(btn: TButton | TButton[], action: (btn: TButton)=>void): KEventController

Register an event that runs when user release a defined button (like "jump") on any input (keyboard, gamepad).

since

onButtonDown(btn: TButton | TButton[], action: (btn: TButton)=>void): KEventController

Register an event that runs when user press a defined button (like "jump") on any input (keyboard, gamepad).

since

onButtonDown(action: (btn: TButton)=>void): KEventController

isTouchscreen(): boolean

Is currently on a touch screen device.

since

mousePos(): Vec2

Get current mouse position (without camera transform).

isKeyDown(k?: Key | Key[]): boolean

If any or certain key(s) are currently down.
// Any key down

let lastKeyTime = time()
let triedToWakeUp = false

onUpdate(() => {
    if (isKeyDown()) {
        lastKeyTime = time()
        triedToWakeUp = false
        return
    }

    if (triedToWakeUp || time() - lastKeyTime < 5) return

    debug.log("Wake up!")
    triedToWakeUp = true
})

// Certain key down
// equivalent to the calling bean.move() in an onKeyDown("left")

onUpdate(() => {
    if (isKeyDown("left")) {
        bean.move(-SPEED, 0)
    }
})

// Certain keys down

let isMoving = false

onUpdate(() => {
    isMoving = isKeyDown(["left", "right"])
})

since

isKeyPressed(k?: Key | Key[]): boolean

If any or certain key(s) are just pressed last frame.
onUpdate(() => {
    if (!isKeyPressed()) return // early return as no key was pressed

    if (isKeyPressed("space")) debug.log("Pressed the jump key")
    if (isKeyPressed(["left", "right"])) debug.log("Pressed any of the move keys")
})

since

isKeyPressedRepeat(k?: Key | Key[]): boolean

If any or certain key(s) are just pressed last frame (also fires repeatedly when the keys are being held down).
let heldKeys = new Set()

onUpdate(() => {
    if (isKeyPressedRepeat("space")) {
        pressedOrHeld(["space"], 'the jump key')
    } else if (isKeyPressedRepeat(["left", "right"])) {
        pressedOrHeld(["left", "right"], 'any of the move keys')
    } else if (isKeyPressedRepeat()) {
        pressedOrHeld(["any"], 'any key')
    }
})

onKeyRelease((key) => wait(0.1, () => {
    heldKeys.delete(key)
    heldKeys.delete("any")
}))

// log message if pressed only or held as well
function pressedOrHeld(keys, string) {
    debug.log(`Pressed${keys.some(key => heldKeys.has(key)) ? ' and held' : ''} ${string}`)
    keys.forEach((key) => {
        if (key == "any" || isKeyDown(key)) heldKeys.add(key)
    })
}

since

isKeyReleased(k?: Key | Key[]): boolean

If any or certain key(s) are just released last frame.
onUpdate(() => {
    if (!isKeyReleased()) return // early return as no key was released

    if (isKeyReleased("space")) debug.log("Released the jump key")
    if (isKeyReleased(["left", "right"])) debug.log("Released any of the move keys")
})

since

isMouseDown(button?: MouseButton | MouseButton[]): boolean

If mouse buttons are currently down.

since

isMousePressed(button?: MouseButton | MouseButton[]): boolean

If mouse buttons are just clicked last frame.

since

isMouseReleased(button?: MouseButton | MouseButton[]): boolean

If mouse buttons are just released last frame.

since

isGamepadButtonPressed(btn?: KGamepadButton | KGamepadButton[]): boolean

If certain gamepad buttons are just pressed last frame

since

isGamepadButtonDown(btn?: KGamepadButton | KGamepadButton): boolean

If certain gamepad buttons are currently held down.

since

isGamepadButtonReleased(btn?: KGamepadButton | KGamepadButton[]): boolean

If certain gamepad buttons are just released last frame.

since

isButtonPressed(button?: TButton | TButton[]): boolean

If any or certain bound button(s) are just pressed last frame on any input (keyboard, gamepad).
onUpdate(() => {
    if (!isButtonPressed()) return // early return as no button was pressed

    if (isButtonPressed("jump")) debug.log("Player jumped")
    if (isButtonPressed(["left", "right"])) debug.log("Player moved")
})

since

isButtonDown(button?: TButton | TButton[]): boolean

If any or certain bound button(s) are currently held down on any input (keyboard, gamepad).
onUpdate(() => {
    if (!isButtonDown()) return // early return as no button is held down

    if (isButtonDown("jump")) debug.log("Player is jumping")
    if (isButtonDown(["left", "right"])) debug.log("Player is moving")
})

since

isButtonReleased(button?: TButton | TButton[]): boolean

If any or certain bound button(s) are just released last frame on any input (keyboard, gamepad).
onUpdate(() => {
    if (!isButtonReleased()) return // early return as no button was released

    if (isButtonReleased("jump")) debug.log("Player stopped jumping")
    if (isButtonReleased(["left", "right"])) debug.log("Player stopped moving")
})

since

getButton(button: Bug parsing TypeOperator): ButtonBinding

Get a input binding from a button name.

since

setButton(button: string, def: ButtonBinding): void

Set a input binding for a button name.

since

pressButton(button: TButton): void

Press a button virtually.

since

// press "jump" button
pressButton("jump"); // triggers onButtonPress, starts onButtonDown
releaseButton("jump"); // triggers onButtonRelease, stops onButtonDown

releaseButton(button: TButton): void

Release a button virtually.

since

// press "jump" button
pressButton("jump"); // triggers onButtonPress, starts onButtonDown
releaseButton("jump"); // triggers onButtonRelease, stops onButtonDown

getGamepadStick(stick: GamepadStick): Vec2

Get stick axis values from a gamepad.

since

charInputted(): string[]

List of characters inputted since last frame.

since

Key: f1 | f2 | f3 | f4 | f5 | f6 | f7 | f8 | f9 | f10 | f11 | f12 | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | + | = | q | w | e | r | t | y | u | i | o | p | [ | ] | \ | a | s | d | f | g | h | j | k | l | ; | ' | z | x | c | v | b | n | m | , | . | / | escape | backspace | enter | tab | control | alt | meta | space | | left | right | up | down | shift | string &

A key.

MouseButton: left | right | middle | back | forward

A mouse button.

KGamepadButton: north | east | south | west | ltrigger | rtrigger | lshoulder | rshoulder | select | start | lstick | rstick | dpad-up | dpad-right | dpad-down | dpad-left | home | capture

A gamepad button.

KEventController:

A controller for all events in KAPLAY.
// Create a new event
const logHi = onUpdate(() => {
   debug.log("hi");
});

// Pause the event
logHi.paused = true;

// Cancel the event
logHi.cancel();

paused: boolean

If the event is paused

cancel(): void

Cancel the event

join(events: KEventController[]): KEventController

replace(oldEv: KEventController, newEv: KEventController): KEventController

on<Ev>(event: Ev, tag: Tag, action: (obj: GameObj, args: TupleWithoutFirst)=>void): KEventController

Register an event on all game objs with certain tag.
// a custom event defined by body() comp
// every time an obj with tag "bomb" hits the floor, destroy it and addKaboom()
on("ground", "bomb", (bomb) => {
    destroy(bomb)
    addKaboom(bomb.pos)
})

// a custom event can be defined manually
// by passing a name and a callback function
on("talk", (message, posX, posY) => {
    add([
     text(message),
     pos(posX, posY - 100)
    ])
})
onKeyPress("space", () => {
   // the trigger method on game objs can be used to trigger a custom event
   npc.trigger("talk", "Hello World!", npc.pos.x, npc.pos.y)
})

onUpdate(tag: Tag, action: (obj: GameObj)=>void): KEventController

Register an event that runs every frame (~60 times per second) for all game objs with certain tag.

since

// move every "tree" 120 pixels per second to the left, destroy it when it leaves screen
// there'll be nothing to run if there's no "tree" obj in the scene
onUpdate("tree", (tree) => {
    tree.move(-120, 0)
    if (tree.pos.x < 0) {
        destroy(tree)
    }
})

onUpdate(action: ()=>void): KEventController

Register an event that runs every frame (~60 times per second).

since

// This will run every frame
onUpdate(() => {
    debug.log("ohhi")
})

onDraw(tag: Tag, action: (obj: GameObj)=>void): KEventController

Register an event that runs every frame (~60 times per second) for all game objs with certain tag (this is the same as onUpdate but all draw events are run after update events, drawXXX() functions only work in this phase).

since

onDraw(action: ()=>void): KEventController

Register an event that runs every frame (~60 times per second) (this is the same as onUpdate but all draw events are run after update events, drawXXX() functions only work in this phase).

since

onDraw(() => {
    drawLine({
        p1: vec2(0),
        p2: mousePos(),
        color: rgb(0, 0, 255),
    })
})

onAdd(tag: Tag, action: (obj: GameObj)=>void): KEventController

onAdd(action: (obj: GameObj)=>void): KEventController

onDestroy(tag: Tag, action: (obj: GameObj)=>void): KEventController

onDestroy(action: (obj: GameObj)=>void): KEventController

onLoad(action: ()=>void): void

Register an event that runs when all assets finished loading.

since

const bean = add([
    sprite("bean"),
])

// certain assets related data are only available when the game finishes loading
onLoad(() => {
    debug.log(bean.width)
})

onLoading(action: (progress: number)=>void): void

Register an event that runs every frame when assets are initially loading. Can be used to draw a custom loading screen.

since

onError(action: (err: Error)=>void): void

Register a custom error handler. Can be used to draw a custom error screen.

since

onResize(action: ()=>void): void

Register an event that runs when the canvas resizes.

since

onCleanup(action: ()=>void): void

Cleanup function to run when quit() is called.

since

onCollide(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision)=>void): KEventController

Register an event that runs once when 2 game objs with certain tags collides (required to have area() component).

since

onCollide("sun", "earth", () => {
    addExplosion()
})

onCollideUpdate(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision)=>void): KEventController

Register an event that runs every frame when 2 game objs with certain tags collides (required to have area() component).

since

onCollideUpdate("sun", "earth", () => {
    runWorldEndTimer()
})

onCollideEnd(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision)=>void): KEventController

Register an event that runs once frame when 2 game objs with certain tags stops colliding (required to have area() component).

since

onCollideEnd("bean", "earth", () => {
    worldEnd()
})

onHover(tag: Tag, action: (a: GameObj)=>void): KEventController

Register an event that runs once when game objs with certain tags are hovered (required to have area() component).

since

onHoverUpdate(tag: Tag, onHover: (a: GameObj)=>void): KEventController

Register an event that runs every frame when game objs with certain tags are hovered (required to have area() component).
// Rotate bean 90 degrees per second when hovered
onHoverUpdate("bean", (bean) => {
  bean.angle += dt() * 90
})

since

onHoverEnd(tag: Tag, action: (a: GameObj)=>void): KEventController

Register an event that runs once when game objs with certain tags are unhovered (required to have area() component).

since

onHide(action: ()=>void): KEventController

Register an event that runs when tab is hidden.

since

onShow(action: ()=>void): KEventController

Register an event that runs when tab is shown.

since

onSceneLeave(action: (newScene?: string)=>void): KEventController

Register an event that runs when current scene ends.

since

KEventHandler<EventMap>:

on<Name>(name: Name, action: (args: EventMap[Name])=>void): KEventController

onOnce<Name>(name: Name, action: (args: EventMap[Name])=>void): KEventController

next<Name>(name: Name): Promise<Bug parsing UnknownKeyword>

trigger<Name>(name: Name, args: EventMap[Name]): void

remove<Name>(name: Name): void

KEventController:

A controller for all events in KAPLAY.
// Create a new event
const logHi = onUpdate(() => {
   debug.log("hi");
});

// Pause the event
logHi.paused = true;

// Cancel the event
logHi.cancel();

paused: boolean

If the event is paused

cancel(): void

Cancel the event

join(events: KEventController[]): KEventController

replace(oldEv: KEventController, newEv: KEventController): KEventController

width(): number

Get the width of game.

height(): number

Get the height of game.

center(): Vec2

Get the center point of view.
// add bean to the center of the screen
add([
    sprite("bean"),
    pos(center()),
    // ...
])

dt(): number

Get the delta time since last frame.
// rotate bean 100 deg per second
bean.onUpdate(() => {
    bean.angle += 100 * dt()
})

fixedDt(): number

Get the fixed delta time since last frame.

restDt(): number

Get the rest delta time since last frame.

time(): number

Get the total time since beginning.

since

isFocused(): boolean

If the game canvas is currently focused.

since

shake(intensity?: number): void

Camera shake.

param

// shake intensively when bean collides with a "bomb"
bean.onCollide("bomb", () => {
    shake(120)
})

camPos(pos: Vec2): Vec2

Get / set camera position.
// camera follows player
player.onUpdate(() => {
    camPos(player.pos)
})

camPos(x: number, y: number): Vec2

camScale(scale: Vec2): Vec2

Get / set camera scale.

camRot(angle?: number): number

Get / set camera rotation.

camFlash(flashColor: Color, fadeOutTime: number): TimerController

Flash the camera.

toScreen(p: Vec2): Vec2

Transform a point from world position (relative to the root) to screen position (relative to the screen).

since

toWorld(p: Vec2): Vec2

Transform a point from screen position (relative to the screen) to world position (relative to the root).

setBackground(r: number, g: number, b: number, alpha: number): void

setCursor(style: Cursor): void

Set cursor style.

since

// Change between cursor styles

// Reset cursor to default at start of every frame
onUpdate(() => setCursor("default"));

button.onHover((c) => {
   // change cursor to pointer when hovering over button
    setCursor("pointer")
})

// Hide the only cursor at start (useful for fakeMouse)
setCursor("none");

getCursor(): Cursor

Get current cursor style.

since

setCursorLocked(locked: boolean): void

Lock / unlock cursor. Note that you cannot lock cursor within 1 second after user unlocking the cursor with the default unlock gesture (typically the esc key) due to browser policy.

since

setFullscreen(f?: boolean): void

Enter / exit fullscreen mode. (note: mouse position is not working in fullscreen mode at the moment)
// toggle fullscreen mode on "f"
onKeyPress("f", (c) => {
    setFullscreen(!isFullscreen())
})

canvas: HTMLCanvasElement

The canvas DOM KAPLAY is currently using.

VERSION: string

Current KAPLAY library version.

since

wait(n: number, action?: ()=>void): TimerController

Run the callback after n seconds.
// 3 seconds until explosion! Runnn!
wait(3, () => {
    explode()
})

// wait() returns a PromiseLike that can be used with await
await wait(1)

loop(t: number, action: ()=>void): KEventController

Run the callback every n seconds.
// spawn a butterfly at random position every 1 second
loop(1, () => {
    add([
        sprite("butterfly"),
        pos(rand(vec2(width(), height()))),
        area(),
        "friend",
    ])
})

TimerController:

paused: boolean

If the event handler is paused.

cancel(): void

Cancel the event handler.

onEnd(action: ()=>void): void

Register an event when finished.

then(action: ()=>void): TimerController

TweenController: TimerController &

finish(): void

Finish the tween now and cancel.

Event controller for tween.

Color:

0-255 RGBA color.

r: number

Red (0-255.

g: number

Green (0-255).

b: number

Blue (0-255).

fromHex(hex: string | number): Color

Create color from hex string or literal.
Color.fromHex(0xfcef8d)
Color.fromHex("#5ba675")
Color.fromHex("d46eb3")

since

fromHSL(h: number, s: number, l: number): Color

lighten(a: number): Color

Lighten the color (adds RGB by n).

darken(a: number): Color

Darkens the color (subtracts RGB by n).

mult(other: Color): Color

lerp(dest: Color, t: number): Color

Linear interpolate to a destination color.

since

toHSL(): [number, number, number]

Convert color into HSL format.

since

eq(other: Color): boolean

toHex(): string

Return the hex string of color.

since

toArray(): Array<number>

Return the color converted to an array.

since

Vec2Args: [number, number] | [number] | [Vec2] | [number | Vec2] | []

Possible arguments for a Vec2.

Vec2:

A 2D vector.

x: number

The x coordinate

y: number

The y coordinate

fromAngle(deg: number): Vec2

Create a new Vec2 from an angle in degrees

fromArray(arr: Array): Vec2

Create a new Vec2 from an array

clone(): Vec2

Clone the vector

add(args: Vec2Args): Vec2

Returns the addition with another vector.

sub(args: Vec2Args): Vec2

Returns the subtraction with another vector.

scale(args: Vec2Args): Vec2

Scale by another vector. or a single number

dist(args: Vec2Args): number

Get distance between another vector

sdist(args: Vec2Args): number

Get squared distance between another vector

slen(): number

Get squared length of the vector

since

unit(): Vec2

Get the unit vector (length of 1).

normal(): Vec2

Get the perpendicular vector.

reflect(normal: Vec2): Vec2

Get the reflection of a vector with a normal.

since

project(on: Vec2): Vec2

Get the projection of a vector onto another vector.

since

reject(on: Vec2): Vec2

Get the rejection of a vector onto another vector.

since

dot(p2: Vec2): number

Get the dot product with another vector.

cross(p2: Vec2): number

Get the cross product with another vector.

since

angle(args: Vec2Args): number

Get the angle of the vector in degrees.

angleBetween(args: Vec2Args): number

Get the angle between this vector and another vector.

since

lerp(dest: Vec2, t: number): Vec2

Linear interpolate to a destination vector (for positions).

slerp(dest: Vec2, t: number): Vec2

Spherical linear interpolate to a destination vector (for rotations).

since

isZero(): boolean

If the vector (x, y) is zero.

since

toFixed(n: number): Vec2

To n precision floating point.

transform(m: Mat4): Vec2

Multiply by a Mat4.

since

eq(other: Vec2): boolean

ShapeType: Point | Circle | Line | Rect | Polygon | Ellipse

UniformValue: number | Vec2 | Color | Mat4 | number[] | Vec2[] | Color[]

Uniform: Record<UniformKey, UniformValue>

raycast(origin: Vec2, direction: Vec2, exclude?: string[]): RaycastResult

rand(): number

Get a random number between 0 - 1.

rand<T>(n: T): T

Get a random value between 0 and the given value.
// a random number between 0 - 8
rand(8)

// a random point on screen
rand(vec2(width(), height()))

// a random color
rand(rgb(255, 255, 255))

rand<T>(a: T, b: T): T

Get a random value between the given bound.
rand(50, 100)
rand(vec2(20), vec2(100))

// spawn something on the right side of the screen but with random y value within screen height
add([
    pos(width(), rand(0, height())),
])

randi(n: number): number

rand() but floored to integer.
randi(10) // returns 0 to 9

randi(a: number, b: number): number

rand() but floored to integer.
randi(0, 3) // returns 0, 1, or 2

randi(): number

rand() but floored to integer.
randi() // returns either 0 or 1

randSeed(seed?: number): number

Get / set the random number generator seed.
randSeed(Date.now())

vec2(x: number, y: number): Vec2

Create a 2d vector.
// { x: 0, y: 0 }
vec2()

// { x: 10, y: 10 }
vec2(10)

// { x: 100, y: 80 }
vec2(100, 80)

// move to 150 degrees direction with by length 10
player.pos = pos.add(Vec2.fromAngle(150).scale(10))

vec2(xy: number): Vec2

rgb(r: number, g: number, b: number): Color

Create a color from RGB values (0 - 255).
// update the color of the sky to light blue
sky.color = rgb(0, 128, 255)

rgb(hex: string): Color

Create a color from hex string.

since

sky.color = rgb("#ef6360")

rgb(): Color

Same as rgb(255, 255, 255).

hsl2rgb(hue: number, saturation: number, lightness: number): Color

Convert HSL color (all values in 0.0 - 1.0 range) to RGB color.

since

// animate rainbow color
onUpdate("rainbow", (obj) => {
    obj.color = hsl2rgb(wave(0, 1, time()), 0.6, 0.6)
})

quad(x: number, y: number, w: number, h: number): Quad

Rectangle area (0.0 - 1.0).

choose<T>(lst: T[]): T

Choose a random item from a list.
// decide the best fruit randomly
const bestFruit = choose(["apple", "banana", "pear", "watermelon"])

chooseMultiple<T>(lst: T[], count: number): T[]

Choose multiple random items from a list.

since

shuffle<T>(lst: T[]): T[]

Shuffle an array.

since

chance(p: number): boolean

rand(1) <= p
// every frame all objs with tag "unlucky" have 50% chance die
onUpdate("unlucky", (o) => {
    if (chance(0.5)) {
        destroy(o)
    }
})

lerp<V>(from: V, to: V, t: number): V

Linear interpolation.

tween<V>(from: V, to: V, duration: number, setValue: (value: V)=>void, easeFunc?: (t: number)=>number): TweenController

Tweeeeeeeening!

since

// tween bean to mouse position
tween(bean.pos, mousePos(), 1, (p) => bean.pos = p, easings.easeOutBounce)

// tween() returns a then-able that can be used with await
await tween(bean.opacity, 1, 0.5, (val) => bean.opacity = val, easings.easeOutQuad)

easings: Record<EaseFuncs, EaseFunc>

A collection of easing functions for tweening.

since

easingSteps(steps: number, position: StepPosition): number

Steps easing. Eases in discontinious steps.

since

easingLinear(keys: Vec2[]): number

Linear easing with keyframes

since

easingCubicBezier(p1: Vec2, p2: Vec2): number

Bezier easing. Both control points need x to be within 0 and 1.

since

map(v: number, l1: number, h1: number, l2: number, h2: number): number

Map a value from one range to another range.

mapc(v: number, l1: number, h1: number, l2: number, h2: number): number

Map a value from one range to another range, and clamp to the dest range.

wave(lo: number, hi: number, t: number, func?: (x: number)=>number): number

Interpolate between 2 values (Optionally takes a custom periodic function, which default to Math.sin).
// bounce color between 2 values as time goes on
onUpdate("colorful", (c) => {
    c.color.r = wave(0, 255, time())
    c.color.g = wave(0, 255, time() + 1)
    c.color.b = wave(0, 255, time() + 2)
})

deg2rad(deg: number): number

Convert degrees to radians.

rad2deg(rad: number): number

Convert radians to degrees.

clamp(n: number, min: number, max: number): number

Return a value clamped to an inclusive range of min and max.

evaluateQuadratic(pt1: Vec2, pt2: Vec2, pt3: Vec2, t: number): Vec2

Evaluate the quadratic Bezier at the given t

evaluateBezier(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2

Evaluate the cubic Bezier at the given t

since

evaluateBezierFirstDerivative(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2

Evaluate the first derivative of a cubic Bezier at the given t

evaluateBezierSecondDerivative(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2

Evaluate the second derivative of a cubic bezier at the given t

since

evaluateCatmullRom(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2

Evaluate the Catmull-Rom spline at the given t

since

evaluateCatmullRomFirstDerivative(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2

Evaluate the first derivative of a Catmull-Rom spline at the given t

since

curveLengthApproximation(curve: (t: number)=>Vec2, entries: number, detail: number): number

Returns a function. entries is the amount of entries in the LUT. detail is the sampling granularity of each segment recorded in the LUT. This new function either returns the length for a given t, or t for a given length, depending on the inverse parameter.

since

normalizedCurve(curve: (t: number)=>Vec2): Vec2

Returns a new curve which is normalized. This new curve has constant speed curve is any curve in t (non-constant between 0 and 1) returns a curve in s (constant between 0 and 1)

since

testLinePoint(l: Line, pt: Vec2): boolean

Check if a line and a point intersect.

testLineLine(l1: Line, l2: Line): Vec2 | null

Check if 2 lines intersects, if yes returns the intersection point.

testLineCircle(l: Line, circle: Circle): boolean

Check if a line and a circle intersect.

testRectRect(r1: Rect, r2: Rect): boolean

Check if 2 rectangle overlaps.

testRectLine(r: Rect, l: Line): boolean

Check if a line and a rectangle overlaps.

testRectPoint(r: Rect, pt: Vec2): boolean

Check if a point is inside a rectangle.

testCirclePolygon(c: Circle, p: Polygon): boolean

Check if a circle and polygon intersect linewise.

Vec2:

A 2D vector.

x: number

The x coordinate

y: number

The y coordinate

fromAngle(deg: number): Vec2

Create a new Vec2 from an angle in degrees

fromArray(arr: Array): Vec2

Create a new Vec2 from an array

clone(): Vec2

Clone the vector

add(args: Vec2Args): Vec2

Returns the addition with another vector.

sub(args: Vec2Args): Vec2

Returns the subtraction with another vector.

scale(args: Vec2Args): Vec2

Scale by another vector. or a single number

dist(args: Vec2Args): number

Get distance between another vector

sdist(args: Vec2Args): number

Get squared distance between another vector

slen(): number

Get squared length of the vector

since

unit(): Vec2

Get the unit vector (length of 1).

normal(): Vec2

Get the perpendicular vector.

reflect(normal: Vec2): Vec2

Get the reflection of a vector with a normal.

since

project(on: Vec2): Vec2

Get the projection of a vector onto another vector.

since

reject(on: Vec2): Vec2

Get the rejection of a vector onto another vector.

since

dot(p2: Vec2): number

Get the dot product with another vector.

cross(p2: Vec2): number

Get the cross product with another vector.

since

angle(args: Vec2Args): number

Get the angle of the vector in degrees.

angleBetween(args: Vec2Args): number

Get the angle between this vector and another vector.

since

lerp(dest: Vec2, t: number): Vec2

Linear interpolate to a destination vector (for positions).

slerp(dest: Vec2, t: number): Vec2

Spherical linear interpolate to a destination vector (for rotations).

since

isZero(): boolean

If the vector (x, y) is zero.

since

toFixed(n: number): Vec2

To n precision floating point.

transform(m: Mat4): Vec2

Multiply by a Mat4.

since

eq(other: Vec2): boolean

Color:

0-255 RGBA color.

r: number

Red (0-255.

g: number

Green (0-255).

b: number

Blue (0-255).

fromHex(hex: string | number): Color

Create color from hex string or literal.
Color.fromHex(0xfcef8d)
Color.fromHex("#5ba675")
Color.fromHex("d46eb3")

since

fromHSL(h: number, s: number, l: number): Color

lighten(a: number): Color

Lighten the color (adds RGB by n).

darken(a: number): Color

Darkens the color (subtracts RGB by n).

mult(other: Color): Color

lerp(dest: Color, t: number): Color

Linear interpolate to a destination color.

since

toHSL(): [number, number, number]

Convert color into HSL format.

since

eq(other: Color): boolean

toHex(): string

Return the hex string of color.

since

toArray(): Array<number>

Return the color converted to an array.

since

Collision:

Collision resolution data.

source: GameObj

The first game object in the collision.

target: GameObj

The second game object in the collision.

normal: Vec2

The contact normal.

distance: Vec2

The length of the displacement.

displacement: Vec2

The displacement source game object have to make to avoid the collision.

resolved: boolean

If the collision is resolved.

hasOverlap(): boolean

If the 2 objects have any overlap, or they're just touching edges.

since

reverse(): Collision

Get a new collision with reversed source and target relationship.

isTop(): boolean

If the collision happened (roughly) on the top side.

isBottom(): boolean

If the collision happened (roughly) on the bottom side.

isLeft(): boolean

If the collision happened (roughly) on the left side.

isRight(): boolean

If the collision happened (roughly) on the right side.

Edge: left | right | top | bottom

EaseFuncs: linear | easeInSine | easeOutSine | easeInOutSine | easeInQuad | easeOutQuad | easeInOutQuad | easeInCubic | easeOutCubic | easeInOutCubic | easeInQuart | easeOutQuart | easeInOutQuart | easeInQuint | easeOutQuint | easeInOutQuint | easeInExpo | easeOutExpo | easeInOutExpo | easeInCirc | easeOutCirc | easeInOutCirc | easeInBack | easeOutBack | easeInOutBack | easeInElastic | easeOutElastic | easeInOutElastic | easeInBounce | easeOutBounce | easeInOutBounce

The list of easing functions available.

EaseFunc(t: number): number

A function that takes a time value and returns a new time value.

Texture:

src: null | ImageSource

fromImage(ctx: GfxCtx, img: ImageSource, opt?: TextureOpt): Texture

update(img: ImageSource, x?: number, y?: number): void

free(): void

Frees up texture memory. Call this once the texture is no longer being used to avoid memory leaks.

initGfx(gl: WebGLRenderingContext, opts?: ):

gl: WebGLRenderingContext

onDestroy(action: ()=>Bug parsing UnknownKeyword): void

ColorArgs: [Color] | [Color, number] | RGBValue | RGBAValue | [string] | [number[]] | []

DrawBezierOpt: DrawCurveOpt &

pt1: Vec2

The first point.

pt2: Vec2

The the first control point.

pt3: Vec2

The the second control point.

pt4: Vec2

The second point.

DrawCircleOpt: Omit &

radius: number

Radius of the circle.

start?: number

Starting angle.

fill?: boolean

If fill the shape with color (set this to false if you only want an outline).

gradient?: [Color, Color]

Use gradient instead of solid color.

since

resolution?: number

Multiplier for circle vertices resolution (default 1)

anchor?: Anchor | Vec2

The anchor point, or the pivot point. Default to "topleft".

How the circle should look like.

CharTransformFunc(idx: number, ch: string): CharTransform

A function that returns a character transform config. Useful if you're generating dynamic styles.

DrawLineOpt: Omit &

p1: Vec2

Starting point of the line.

p2: Vec2

Ending point of the line.

width?: number

The width, or thickness of the line,

How the line should look like.

DrawLinesOpt: Omit &

pts: Vec2[]

The points that should be connected with a line.

width?: number

The width, or thickness of the lines,

radius?: number | number[]

The radius of each corner.

join?: LineJoin

Line join style (default "none").

cap?: LineCap

Line cap style (default "none").

miterLimit?: number

Maximum miter length, anything longer becomes bevel.

How the lines should look like.

DrawRectOpt: RenderProps &

width: number

Width of the rectangle.

height: number

Height of the rectangle.

gradient?: [Color, Color]

Use gradient instead of solid color.

since

horizontal?: boolean

If the gradient should be horizontal.

since

fill?: boolean

If fill the shape with color (set this to false if you only want an outline).

radius?: number | number[]

The radius of each corner.

anchor?: Anchor | Vec2

The anchor point, or the pivot point. Default to "topleft".

How the rectangle should look like.

DrawSpriteOpt: RenderProps &

sprite: string | SpriteData | Asset

The sprite name in the asset manager, or the raw sprite data.

frame?: number

If the sprite is loaded with multiple frames, or sliced, use the frame option to specify which frame to draw.

width?: number

Width of sprite. If `height` is not specified it'll stretch with aspect ratio. If `tiled` is set to true it'll tiled to the specified width horizontally.

height?: number

Height of sprite. If `width` is not specified it'll stretch with aspect ratio. If `tiled` is set to true it'll tiled to the specified width vertically.

tiled?: boolean

When set to true, `width` and `height` will not scale the sprite but instead render multiple tiled copies of them until the specified width and height. Useful for background texture pattern etc.

flipX?: boolean

If flip the texture horizontally.

flipY?: boolean

If flip the texture vertically.

quad?: Quad

The sub-area to render from the texture, by default it'll render the whole `quad(0, 0, 1, 1)`

anchor?: Anchor | Vec2

The anchor point, or the pivot point. Default to "topleft".

pos?: Vec2

The position

How the sprite should look like.

DrawTriangleOpt: RenderProps &

p1: Vec2

First point of triangle.

p2: Vec2

Second point of triangle.

p3: Vec2

Third point of triangle.

fill?: boolean

If fill the shape with color (set this to false if you only want an outline).

radius?: number

The radius of each corner.

How the triangle should look like.

SpriteAnim: number |

from: number

The starting frame.

to: number

The end frame.

loop?: boolean

If this anim should be played in loop.

pingpong?: boolean

When looping should it move back instead of go to start frame again.

speed?: number

This anim's speed in frames per second.

Frame-based animation configuration.

SpriteAnims: Record<string, SpriteAnim>

A dict of name <-> animation.

LoadSpriteOpt:

Sprite loading configuration.

sliceX?: number

If the defined area contains multiple sprites, how many frames are in the area hozizontally.

sliceY?: number

If the defined area contains multiple sprites, how many frames are in the area vertically.

slice9?: NineSlice

9 slice sprite for proportional scaling.

since

frames?: Quad[]

Individual frames.

since

anims?: SpriteAnims

Animation configuration.

NineSlice:

left: number

The width of the 9-slice's left column.

right: number

The width of the 9-slice's right column.

top: number

The height of the 9-slice's top row.

bottom: number

The height of the 9-slice's bottom row.

SpriteData:

from(src: LoadSpriteSrc, opt?: LoadSpriteOpt): Promise<SpriteData>

fromImage(data: ImageSource, opt?: LoadSpriteOpt): SpriteData

fromURL(url: string, opt?: LoadSpriteOpt): Promise<SpriteData>

SpriteAtlasEntry: LoadSpriteOpt &

x: number

X position of the top left corner.

y: number

Y position of the top left corner.

width: number

Sprite area width.

height: number

Sprite area height.

A sprite in a sprite atlas.

BinaryHeap<T>:

insert(item: T): void

Insert an item into the binary heap

remove(): T | null

Remove the smallest item from the binary heap in case of a min heap or the greatest item from the binary heap in case of a max heap

clear(): void

Remove all items

swap(index1: number, index2: number): void

length(): number

Returns the amount of items

KEventHandler<EventMap>:

on<Name>(name: Name, action: (args: EventMap[Name])=>void): KEventController

onOnce<Name>(name: Name, action: (args: EventMap[Name])=>void): KEventController

next<Name>(name: Name): Promise<Bug parsing UnknownKeyword>

trigger<Name>(name: Name, args: EventMap[Name]): void

remove<Name>(name: Name): void

AudioPlayOpt:

Audio play configurations.

paused?: boolean

If audio should start out paused.

since

loop?: boolean

If audio should be played again from start when its ended.

volume?: number

Volume of audio. 1.0 means full volume, 0.5 means half volume.

speed?: number

Playback speed. 1.0 means normal playback speed, 2.0 means twice as fast.

detune?: number

Detune the sound. Every 100 means a semitone.
// play a random note in the octave
play("noteC", {
    detune: randi(0, 12) * 100,
})

seek?: number

The start time, in seconds.

pan?: number

The stereo pan of the sound. -1.0 means fully from the left channel, 0.0 means centered, 1.0 means fully right. Defaults to 0.0.

AudioPlay:

play(time?: number): void

Start playing audio.

since

seek(time: number): void

Seek time.

since

stop(): void

Stop the sound.

since

paused: boolean

If the sound is paused.

since

speed: number

Playback speed of the sound. 1.0 means normal playback speed, 2.0 means twice as fast.

detune: number

Detune the sound. Every 100 means a semitone.
// tune down a semitone
music.detune = -100

// tune up an octave
music.detune = 1200

volume: number

Volume of the sound. 1.0 means full volume, 0.5 means half volume.

pan?: number

The stereo pan of the sound. -1.0 means fully from the left channel, 0.0 means centered, 1.0 means fully right. Defaults to 0.0.

loop: boolean

If the audio should start again when it ends.

time(): number

The current playing time (not accurate if speed is changed).

onEnd(action: ()=>void): KEventController

Register an event that runs when audio ends.

since

then(action: ()=>void): KEventController

AnimateOpt:

duration: number

Duration of the animation in seconds

loops?: number

Loops, Default is undefined aka infinite

direction?: TimeDirection

Behavior when reaching the end of the animation. Default is forward.

easing?: EaseFunc

Easing function. Default is linear time.

interpolation?: Interpolation

Interpolation function. Default is linear interpolation.

timing?: number[]

Timestamps in percent for the given keys, if omitted, keys are equally spaced.

easings?: EaseFunc[]

Easings for the given keys, if omitted, easing is used.

AnimateCompOpt:

followMotion?: boolean

Changes the angle so it follows the motion, requires the rotate component

relative?: boolean

The animation is added to the base values of pos, angle, scale and opacity instead of replacing them

AnimateComp:

animate<T>(name: string, keys: T[], opts: AnimateOpt): void

Animates a property on this object.

param

unanimate(name: string): void

Removes the animation from the given property.

param

unanimateAll(): void

Removes the animations from all properties

onAnimateFinished(cb: ()=>void): KEventController

Attaches an event handler which is called when all the animation channels have finished.

param

onAnimateChannelFinished(cb: (name: string)=>void): KEventController

Attaches an event handler which is called when an animation channels has finished.

param

base: BaseValues

Base values for relative animation

ForceMode: constant | inverseLinear | inverseSquared

GameObjEventNames: update | draw | add | destroy | collide | collideUpdate | collideEnd | hurt | heal | death | beforePhysicsResolve | physicsResolve | ground | fall | fallOff | headbutt | doubleJump | exitView | enterView | animStart | animEnd | navigationNext | navigationEnded | navigationStarted | targetReached | patrolFinished | objectSpotted | animateChannelFinished | animateFinished | spatialMapChanged | navigationMapInvalid | navigationMapChanged

Game: ReturnType<initGame>

_k: KAPLAYInternal

Internal data that should not be accessed directly.

addKaboom(pos: Vec2, opt?: BoomOpt): GameObj

Add an explosion

Defined<T>: Bug parsing ConditionalType

Expand<T>: Bug parsing ConditionalType

MergeObj<T>: Expand<UnionToIntersection>

KGamepad:

index: number

The order of the gamepad in the gamepad list.

isPressed(b: KGamepadButton): boolean

If certain button is pressed.

isDown(b: KGamepadButton): boolean

If certain button is held down.

isReleased(b: KGamepadButton): boolean

If certain button is released.

getStick(stick: GamepadStick): Vec2

Get the value of a stick.

A KAPLAY gamepad

GameObjInspect: Record<Tag, string | null>

Inspect info for a game object.

SpriteAnimPlayOpt:

Sprite animation configuration when playing.

loop?: boolean

If this anim should be played in loop.

pingpong?: boolean

When looping should it move back instead of go to start frame again.

speed?: number

This anim's speed in frames per second.

onEnd?(): void

Runs when this animation ends.

TexFilter: nearest | linear

Texture scaling filter. "nearest" is mainly for sharp pixelated scaling, "linear" means linear interpolation.

DrawUVQuadOpt: RenderProps &

width: number

Width of the UV quad.

height: number

Height of the UV quad.

flipX?: boolean

If flip the texture horizontally.

flipY?: boolean

If flip the texture vertically.

tex?: Texture

The texture to sample for this quad.

quad?: Quad

The texture sampling area.

anchor?: Anchor | Vec2

The anchor point, or the pivot point. Default to "topleft".

DrawEllipseOpt: RenderProps &

radiusX: number

The horizontal radius.

radiusY: number

The vertical radius.

start?: number

Starting angle.

fill?: boolean

If fill the shape with color (set this to false if you only want an outline).

gradient?: [Color, Color]

Use gradient instead of solid color.

since

resolution?: number

Multiplier for circle vertices resolution (default 1)

anchor?: Anchor | Vec2

The anchor point, or the pivot point. Default to "topleft".

How the ellipse should look like.

DrawPolygonOpt: RenderProps &

pts: Vec2[]

The points that make up the polygon

fill?: boolean

If fill the shape with color (set this to false if you only want an outline).

indices?: number[]

Manual triangulation.

offset?: Vec2

The center point of transformation in relation to the position.

radius?: number | number[]

The radius of each corner.

colors?: Color[]

The color of each vertex.

since

uv?: Vec2[]

The uv of each vertex.

since

tex?: Texture

The texture if uv are supplied.

since

triangulate?: boolean

Triangulate concave polygons.

since

How the polygon should look like.

Outline:

width?: number

The width, or thickness of the line.

color?: Color

The color of the line.

opacity?: number

Opacity (overrides fill opacity).

since

join?: LineJoin

Line join.

since

miterLimit?: number

Miter limit. If the length of the miter divided by the line width exceeds this limit, the style is converted to a bevel.

since

cap?: LineCap

Line cap.

since

Mask: intersect | subtract

App: ReturnType<initApp>

initAppGfx(gopt: KAPLAYOpt, ggl: GfxCtx):

ggl:

gl: WebGLRenderingContext

onDestroy(action: ()=>Bug parsing UnknownKeyword): void

initGame():

events: KEventHandler<>

root: GameObj<TimerComp>

scenes: Record<SceneName, SceneDef>

initApp(opt: ):

state:

dt: number

events: KEventHandler<>

dt(): number

run(fixedUpdate: ()=>void, update: (processInput: ()=>void, resetInput: ()=>void)=>void): void

setButton(btn: string, binding: ButtonBinding): void

onResize(action: ()=>void): KEventController

onKeyDown: (action: (key: Key)=>void)=>KEventController & (key: Key | Key[], action: (key: Key)=>void)=>KEventController

onKeyPress: (action: (key: Key)=>void)=>KEventController & (key: Key | Key[], action: (key: Key)=>void)=>KEventController

onKeyPressRepeat: (action: (key: Key)=>void)=>KEventController & (key: Key | Key[], action: (key: Key)=>void)=>KEventController

onKeyRelease: (action: (key: Key)=>void)=>KEventController & (key: Key | Key[], action: (key: Key)=>void)=>KEventController

onMouseDown: (action: (m: MouseButton)=>void)=>KEventController & (mouse: MouseButton | MouseButton[], action: (m: MouseButton)=>void)=>KEventController

onMousePress: (action: (m: MouseButton)=>void)=>KEventController & (mouse: MouseButton | MouseButton[], action: (m: MouseButton)=>void)=>KEventController

onMouseRelease: (action: (m: MouseButton)=>void)=>KEventController & (mouse: MouseButton | MouseButton[], action: (m: MouseButton)=>void)=>KEventController

onMouseMove(f: (pos: Vec2, dpos: Vec2)=>void): KEventController

onCharInput(action: (ch: string)=>void): KEventController

onTouchStart(f: (pos: Vec2, t: Touch)=>void): KEventController

onTouchMove(f: (pos: Vec2, t: Touch)=>void): KEventController

onTouchEnd(f: (pos: Vec2, t: Touch)=>void): KEventController

onScroll(action: (delta: Vec2)=>void): KEventController

onHide(action: ()=>void): KEventController

onShow(action: ()=>void): KEventController

onGamepadButtonDown: (action: (btn: KGamepadButton, gamepad: KGamepad)=>void)=>KEventController & (btn: KGamepadButton, action: (btn: KGamepadButton, gamepad: KGamepad)=>void)=>KEventController

onGamepadButtonPress: (action: (btn: KGamepadButton, gamepad: KGamepad)=>void)=>KEventController & (btn: KGamepadButton | KGamepadButton[], action: (btn: KGamepadButton, gamepad: KGamepad)=>void)=>KEventController

onGamepadButtonRelease: (action: (btn: KGamepadButton, gamepad: KGamepad)=>void)=>KEventController & (btn: KGamepadButton | KGamepadButton[], action: (btn: KGamepadButton, gamepad: KGamepad)=>void)=>KEventController

onGamepadStick(stick: GamepadStick, action: (value: Vec2, gp: KGamepad)=>void): KEventController

onButtonPress: (action: (btn: string)=>void)=>KEventController & (btn: string | string, action: (btn: string)=>void)=>KEventController

onButtonDown: (action: (btn: string)=>void)=>KEventController & (btn: string | string, action: (btn: string)=>void)=>KEventController

onButtonRelease: (action: (btn: string)=>void)=>KEventController & (btn: string | string, action: (btn: string)=>void)=>KEventController

events: KEventHandler<>

DrawTextOpt: RenderProps &

text: string

The text to render.

font?: string | FontData | Asset | BitmapFontData | Asset

The name of font to use.

size?: number

The size of text (the height of each character).

align?: TextAlign

Text alignment (default "left")

since

width?: number

The maximum width. Will wrap word around if exceed.

lineSpacing?: number

The gap between each line (only available for bitmap fonts).

since

letterSpacing?: number

The gap between each character (only available for bitmap fonts).

since

anchor?: Anchor | Vec2

The anchor point, or the pivot point. Default to "topleft".

transform?: CharTransform | CharTransformFunc

Transform the pos, scale, rotation or color for each character based on the index or char (only available for bitmap fonts).

since

styles?: Record<string, CharTransform | CharTransformFunc>

Stylesheet for styled chunks, in the syntax of "this is a [stylename]styled[/stylename] word" (only available for bitmap fonts).

since

How the text should look like.

TextAlign: center | left | right

How the text should be aligned.

drawSprite(options: DrawSpriteOpt): void

Draw a sprite.
drawSprite({
    sprite: "bean",
    pos: vec2(100, 200),
    frame: 3,
})

drawText(options: DrawTextOpt): void

Draw a piece of text.
drawText({
    text: "oh hi",
    size: 48,
    font: "sans-serif",
    width: 120,
    pos: vec2(100, 200),
    color: rgb(0, 0, 255),
})

drawRect(options: DrawRectOpt): void

Draw a rectangle.
drawRect({
    width: 120,
    height: 240,
    pos: vec2(20, 20),
    color: YELLOW,
    outline: { color: BLACK, width: 4 },
})

drawLine(options: DrawLineOpt): void

Draw a line.
drawLine({
    p1: vec2(0),
    p2: mousePos(),
    width: 4,
    color: rgb(0, 0, 255),
})

drawLines(options: DrawLinesOpt): void

Draw lines.
drawLines({
    pts: [ vec2(0), vec2(0, height()), mousePos() ],
    width: 4,
    pos: vec2(100, 200),
    color: rgb(0, 0, 255),
})

drawCurve(curve: (t: number)=>Vec2, opt: DrawCurveOpt): void

Draw a curve.
drawCurve(t => evaluateBezier(a, b, c, d, t)
{
    width: 2,
    color: rgb(0, 0, 255),
})

drawBezier(opt: DrawBezierOpt): void

Draw a cubic Bezier curve.
drawBezier({
    pt1: vec2(100, 100),
    pt2: vec2(200, 100),
    pt3: vec2(200, 200),
    pt4: vec2(100, 200),
    width: 2,
    color: GREEN
})

drawTriangle(options: DrawTriangleOpt): void

Draw a triangle.
drawTriangle({
    p1: vec2(0),
    p2: vec2(0, height()),
    p3: mousePos(),
    pos: vec2(100, 200),
    color: rgb(0, 0, 255),
})

drawCircle(options: DrawCircleOpt): void

Draw a circle.
drawCircle({
    pos: vec2(100, 200),
    radius: 120,
    color: rgb(255, 255, 0),
})

drawEllipse(options: DrawEllipseOpt): void

Draw an ellipse.
drawEllipse({
    pos: vec2(100, 200),
    radiusX: 120,
    radiusY: 120,
    color: rgb(255, 255, 0),
})

drawPolygon(options: DrawPolygonOpt): void

Draw a convex polygon from a list of vertices.
drawPolygon({
    pts: [
        vec2(-12),
        vec2(0, 16),
        vec2(12, 4),
        vec2(0, -2),
        vec2(-8),
    ],
    pos: vec2(100, 200),
    color: rgb(0, 0, 255),
})

drawUVQuad(options: DrawUVQuadOpt): void

Draw a rectangle with UV data.

drawFormattedText(text: FormattedText): void

Draw a piece of formatted text from formatText().

since

// text background
const txt = formatText({
    text: "oh hi",
})

drawRect({
    width: txt.width,
    height: txt.height,
})

drawFormattedText(txt)

drawMasked(content: ()=>void, mask: ()=>void): void

Whatever drawn in content will only be drawn if it's also drawn in mask (mask will not be rendered).

since

drawSubtracted(content: ()=>void, mask: ()=>void): void

Subtract whatever drawn in content by whatever drawn in mask (mask will not be rendered).

since

pushTransform(): void

Push current transform matrix to the transform stack.
pushTransform()

// these transforms will affect every render until popTransform()
pushTranslate(120, 200)
pushRotate(time() * 120)
pushScale(6)

drawSprite("bean")
drawCircle(vec2(0), 120)

// restore the transformation stack to when last pushed
popTransform()

popTransform(): void

Pop the topmost transform matrix from the transform stack.

pushTranslate(x: number, y: number): void

Translate all subsequent draws.
pushTranslate(100, 100)

// this will be drawn at (120, 120)
drawText({
    text: "oh hi",
    pos: vec2(20, 20),
})

pushScale(x: number, y: number): void

Scale all subsequent draws.

pushScale(args: Vec2Args | [undefined] | [undefined, undefined]): void

pushRotate(angle?: number): void

Rotate all subsequent draws.

pushMatrix(mat?: Mat4): void

Apply a transform matrix, ignore all prior transforms.

since

usePostEffect(name: string, uniform?: Uniform | ()=>Uniform): void

Apply a post process effect from a shader name.

since

loadShader("invert", null, `
vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
    vec4 c = def_frag();
    return vec4(1.0 - c.r, 1.0 - c.g, 1.0 - c.b, c.a);
}
`)

usePostEffect("invert")

formatText(options: DrawTextOpt): FormattedText

Format a piece of text without drawing (for getting dimensions, etc).

since

// text background
const txt = formatText({
    text: "oh hi",
})

drawRect({
    width: txt.width,
    height: txt.height,
})

drawFormattedText(txt)

makeCanvas(w: number, h: number): Canvas

Create a canvas to draw stuff offscreen.

since

Cursor: string | auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | grab | grabbing | all-scroll | col-resize | row-resize | n-resize | e-resize | s-resize | w-resize | ne-resize | nw-resize | se-resize | sw-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | zoom-int | zoom-out

Anchor: topleft | top | topright | left | center | right | botleft | bot | botright

Shape: Rect | Line | Point | Circle | Ellipse | Polygon

CharTransform:

Describes how to transform each character.

pos?: Vec2

Offset to apply to the position of the text character. Shifts the character's position by the specified 2D vector.

scale?: Vec2 | number

Scale transformation to apply to the text character's current scale. When a number, it is scaled uniformly. Given a 2D vector, it is scaled independently along the X and Y axis.

angle?: number

Increases the amount of degrees to rotate the text character.

color?: Color

Color transformation applied to the text character. Multiplies the current color with this color.

opacity?: number

Opacity multiplication applied to the text character. For example, an opacity of 0.4 with 2 set in the transformation, the resulting opacity will be 0.8 (0.4 × 2).

LevelOpt:

pos?: Vec2

Position of the first block.

tiles:

Definition of each tile.

wildcardTile?(sym: string, pos: Vec2): CompList | null | undefined

Called when encountered a symbol not defined in "tiles".

GetOpt:

recursive?: boolean

Recursively get all children and their descendants.

liveUpdate?: boolean

Live update the returned list every time object is added / removed.

QueryOpt:

include?: string | string[]

All objects which include all or any of these tags, depending on includeOp.

includeOp?: and | or

Selects the operator to use. Defaults to and.

exclude?: string | string[]

All objects which do not have all or any of these tags, depending on excludeOp.

excludeOp?: and | or

Selects the operator to use. Defaults to and.

distance?: number

All objects which are near or far to the position of this, depending on distanceOp.

distanceOp?: near | far

Selects the operator to use. Defaults to near.

visible?: boolean

All objects visible from this standpoint.

hierarchy?: children | siblings | ancestors | descendants

All objects in the given group. Defaults to children.

play(src: string | SoundData | Asset | MusicData | Asset, options?: AudioPlayOpt): AudioPlay

Play a piece of audio.

returns

// play a one off sound
play("wooosh")

// play a looping soundtrack (check out AudioPlayOpt for more options)
const music = play("OverworldlyFoe", {
    volume: 0.8,
    loop: true
})

// using the handle to control (check out AudioPlay for more controls / info)
music.paused = true
music.speed = 1.2

burp(options?: AudioPlayOpt): AudioPlay

Yep. Plays a burp sound.

volume(v?: number): number

Sets global volume.
// makes everything quieter
volume(0.5)

audioCtx: AudioContext

Get the underlying browser AudioContext.

addLevel(map: string[], options: LevelOpt): GameObj

Construct a level based on symbols.
addLevel([
    "                          $",
    "                          $",
    "           $$         =   $",
    "  %      ====         =   $",
    "                      =    ",
    "       ^^      = >    =   &",
    "===========================",
], {
    // define the size of tile block
    tileWidth: 32,
    tileHeight: 32,
    // define what each symbol means, by a function returning a component list (what will be passed to add())
    tiles: {
        "=": () => [
            sprite("floor"),
            area(),
            body({ isStatic: true }),
        ],
        "$": () => [
            sprite("coin"),
            area(),
            pos(0, -9),
        ],
        "^": () => [
            sprite("spike"),
            area(),
            "danger",
        ],
    }
})

getData<T>(key: string, def?: T): T | null

Get data from local storage, if not present can set to a default value.

setData(key: string, data: any): void

Set data from local storage.

screenshot(): string

Take a screenshot and get the data url of the image.

returns

download(filename: string, dataurl: string): void

Trigger a file download from a url.

since

downloadText(filename: string, text: string): void

Trigger a text file download.

since

downloadJSON(filename: string, data: any): void

Trigger a json download from a .

since

downloadBlob(filename: string, blob: Blob): void

Trigger a file download from a blob.

since

record(frameRate?: number): Recording

Start recording the canvas into a video. If framerate is not specified, a new frame will be captured each time the canvas changes.

returns

since

Recording:

Screen recording control handle.

pause(): void

Pause the recording.

resume(): void

Resume the recording.

stop(): Promise<Blob>

Stop the recording and get the video data as mp4 Blob.

since

download(filename?: string): void

Stop the recording and downloads the file as mp4. Trying to resume later will lead to error.

debug: Debug

The Debug interface for debugging stuff.
// pause the whole game
debug.paused = true

// enter inspect mode
debug.inspect = true

Debug:

paused: boolean

Pause the whole game.

inspect: boolean

Draw bounding boxes of all objects with `area()` component, hover to inspect their states.

showLog: boolean

Show the debug log or not.

fps(): number

Current frames per second.

numFrames(): number

Total number of frames elapsed.

since

drawCalls(): number

Number of draw calls made last frame.

stepFrame(): void

Step to the next frame. Useful with pausing.

log(msg: any): void

Log some text to on screen debug log.

error(msg: any): void

Log an error message to on screen debug log.

curRecording: Recording | null

The recording handle if currently in recording mode.

since

numObjects(): number

Get total number of objects.

since

plug<T>(plugin: KAPLAYPlugin): KAPLAYCtx & T

Import a plugin.

KAPLAYPlugin<T>(k: KAPLAYCtx): T | (args: any)=>(k: KAPLAYCtx)=>T

A plugin for KAPLAY.
// a plugin that adds a new function to KAPLAY
const myPlugin = (k) => ({
   myFunc: () => {
      k.debug.log("hello from my plugin")
  }
})

// use the plugin
kaplay({
  plugins: [ myPlugin ]
})

// now you can use the new function
myFunc()

LEFT: Vec2

Left directional vector vec2(-1, 0).

UP: Vec2

Up directional vector vec2(0, -1).

DOWN: Vec2

Down directional vector vec2(0, 1).

RED: Color

Red color.

BLUE: Color

Blue color.

CYAN: Color

Cyan color.

ButtonsDef: Record<string, ButtonBinding>

A buttons definition for an action (jump, walk-left, run).
kaplay logo

Misc