kaboomjs
Start
Debug
NOTE: Kaboom.js is no longer maintained. See GitHub for more.Kaboom.js is a Javascript game programming library that helps you make games fast and fun.
// start the game
kaboom()

// define gravity
setGravity(2400)

// load a default sprite
loadBean()

// add character to screen, from a list of components
const player = add([
    sprite("bean"),  // renders as a sprite
    pos(120, 80),    // position in world
    area(),          // has a collider
    body(),          // responds to physics and gravity
])

// jump when player presses "space" key
onKeyPress("space", () => {
    // .jump() is provided by the body() component
    player.jump()
})

Play with it yourself or check out the examples in the Playground!

Start
kaboom(options?: KaboomOpt<T>)
Initialize kaboom context. The starting point of all kaboom games.
// Start kaboom with default options (will create a fullscreen canvas under <body>)
kaboom()

// Init with some options (check out #KaboomOpt for full options list)
kaboom({
    width: 320,
    height: 240,
    font: "sans-serif",
    canvas: document.querySelector("#mycanvas"),
    background: [ 0, 0, 255, ],
})

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

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

k.add(...)
k.onUpdate(...)
k.onKeyPress(...)
k.vec2(...)
Game Obj
add(comps?: CompList<T> | GameObj<T>) => GameObj<T>
Assemble a game object from a list of components, and add it to the game
returns
The added game object that contains all properties and methods each component offers.
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(comps?: CompList<T>) => GameObj<T>
Create a game object like add(), but not adding to the scene.
since
v3000.1
const label = make([
    text("oh hi"),
])

add([
    rect(label.width, label.height),
    color(0, 0, 255),
    children(label),
])
readd(obj: GameObj)
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 })
destroy(obj: GameObj)
Remove the game obj.
// every time bean collides with anything with tag "fruit", remove it
bean.onCollide("fruit", (fruit) => {
    destroy(fruit)
})
destroyAll(tag: Tag)
Remove all game objs with certain tag.
// destroy all objects with tag "bomb" when you click one
onClick("bomb", () => {
    destroyAll("bomb")
})
Components
pos(x: number, y: number) => PosComp
Position
// 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
pos() => PosComp
scale(x: number, y: number) => ScaleComp
Scale.
scale(xy: number) => ScaleComp
scale(s: Vec2) => ScaleComp
scale() => ScaleComp
Scale the game obj.
// 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)
rotate(a: number) => RotateComp
Rotation (in degrees).
color(r: number, g: number, b: number) => ColorComp
Sets color (rgb 0-255).
// blue frog
add([
    sprite("bean"),
    color(0, 0, 255)
])
color(c: Color) => ColorComp
color(rgb: unknown) => ColorComp
color(c: string) => ColorComp
color() => ColorComp
opacity(o?: number) => OpacityComp
Sets opacity (0.0 - 1.0).
sprite(spr: string | SpriteData, options?: SpriteCompOpt) => SpriteComp
Render as a sprite.
// 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
Render as text.
// 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
Render as a polygon.
since
v3000.2
// 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
Render as a rectangle.
// i don't know, could be an obstacle or something
add([
    pos(80, 120),
    rect(20, 40),
    outline(4),
    area(),
])
circle(radius: number) => CircleComp
Render as a circle.
add([
    pos(80, 120),
    circle(16),
])
uvquad(w: number, h: number) => UVQuadComp
Render as a UV quad.
add([
    uvquad(width(), height()),
    shader("spiral"),
])
area() => AreaComp
Generates collider area from shape and enables collision detection.
// 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
Define collider area and enables collision detection.
add([
    sprite("flower"),
    // Scale to 0.6 of the generated area
    area({ scale: 0.6 }),
    // If we want the area scale to be calculated from the center
    anchor("center"),
])

add([
    sprite("bean"),
    // Define area with custom shape
    area({ shape: new Polygon([vec2(0), vec2(100), vec2(-100, 100)]) }),
])
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.
outline(width?: number, color?: Color) => OutlineComp
Give obj an outline.
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!")
})
doubleJump(numJumps?: number) => DoubleJumpComp
Enables double jump. Requires "body" component.
since
v3000.0
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
v2000.2
add([
    pos(player.pos),
    sprite("bullet"),
    offscreen({ destroy: true }),
    "projectile",
])
follow(obj: GameObj | null, offset?: Vec2) => FollowComp
Follow another game obj's position.
shader(id: string, uniform?: Uniform | (() => Uniform)) => ShaderComp
Custom shader.
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.
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 }),
])
state(initialState: string, stateList?: string[]) => StateComp
Finite state machine.
since
v2000.1
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<string, string | string[]>) => StateComp
state() with pre-defined transitions.
since
v2000.2
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.
since
v3000.0
mask(maskType?: Mask) => MaskComp
Mask all children object render.
since
v3000.2
drawon(canvas: FrameBuffer) => Comp
tile(opt: TileCompOpt) => TileComp
A tile on a tile map.
since
v3000.0
agent(opt?: AgentCompOpt) => AgentComp
An agent which can finds it way on a tilemap.
since
v3000.0
Events
on(event: string, tag: Tag, action: (obj: GameObj, args: ...) => void) => EventController
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) => EventController
Register an event that runs every frame (~60 times per second) for all game objs with certain tag.
since
v2000.1
// 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) => EventController
Register an event that runs every frame (~60 times per second).
since
v2000.1
// This will run every frame
onUpdate(() => {
    debug.log("ohhi")
})
onDraw(tag: Tag, action: (obj: GameObj) => void) => EventController
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
v2000.1
onDraw(action: () => void) => EventController
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
v2000.1
onDraw(() => {
    drawLine({
        p1: vec2(0),
        p2: mousePos(),
        color: rgb(0, 0, 255),
    })
})
onAdd(tag: Tag, action: (obj: GameObj) => void) => EventController
onAdd(action: (obj: GameObj) => void) => EventController
onDestroy(tag: Tag, action: (obj: GameObj) => void) => EventController
onDestroy(action: (obj: GameObj) => void) => EventController
onLoad(action: () => void)
Register an event that runs when all assets finished loading.
since
v2000.1
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)
Register an event that runs every frame when assets are initially loading. Can be used to draw a custom loading screen.
since
v3000.0
onError(action: (err: Error) => void)
Register a custom error handler. Can be used to draw a custom error screen.
since
v3000.0
onResize(action: () => void)
Register an event that runs when the canvas resizes.
since
v3000.0
onCleanup(action: () => void)
Cleanup function to run when quit() is called.
since
v3000.0
onGamepadConnect(action: (gamepad: KGamePad) => void)
Register an event that runs when a gamepad is connected.
since
v3000.0
onGamepadDisconnect(action: (gamepad: KGamePad) => void)
Register an event that runs when a gamepad is disconnected.
since
v3000.0
onCollide(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision) => void) => EventController
Register an event that runs once when 2 game objs with certain tags collides (required to have area() component).
since
v2000.1
onCollide("sun", "earth", () => {
    addExplosion()
})
onCollideUpdate(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision) => void) => EventController
Register an event that runs every frame when 2 game objs with certain tags collides (required to have area() component).
since
v3000.0
onCollideUpdate("sun", "earth", () => {
    runWorldEndTimer()
})
onCollideEnd(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision) => void) => EventController
Register an event that runs once frame when 2 game objs with certain tags stops colliding (required to have area() component).
since
v3000.0
onCollideEnd("bean", "earth", () => {
    worldEnd()
})
onClick(tag: Tag, action: (a: GameObj) => void) => EventController
Register an event that runs when game objs with certain tags are clicked (required to have the area() component).
since
v2000.1
// click on any "chest" to open
onClick("chest", (chest) => chest.open())
onClick(action: () => void) => EventController
Register an event that runs when users clicks.
since
v2000.1
// click on anywhere to go to "game" scene
onClick(() => go("game"))
onHover(tag: Tag, action: (a: GameObj) => void) => EventController
Register an event that runs once when game objs with certain tags are hovered (required to have area() component).
since
v3000.0
onHoverUpdate(tag: Tag, onHover: (a: GameObj) => void) => EventController
Register an event that runs every frame when game objs with certain tags are hovered (required to have area() component).
since
v3000.0
onHoverEnd(tag: Tag, action: (a: GameObj) => void) => EventController
Register an event that runs once when game objs with certain tags are unhovered (required to have area() component).
since
v3000.0
onKeyDown(key: Key, action: (key: Key) => void) => EventController
Register an event that runs every frame when a key is held down.
since
v2000.1
// move left by SPEED pixels per frame every frame when left arrow key is being held down
onKeyDown("left", () => {
    bean.move(-SPEED, 0)
})
onKeyDown(action: (key: Key) => void) => EventController
Register an event that runs every frame when any key is held down.
since
v2000.1
onKeyPress(key: Key, action: (key: Key) => void) => EventController
Register an event that runs when user presses certain key.
since
v2000.1
// .jump() once when "space" is just being pressed
onKeyPress("space", () => {
    bean.jump()
})
onKeyPress(action: (key: Key) => void) => EventController
Register an event that runs when user presses any key.
since
v2000.1
// Call restart() when player presses any key
onKeyPress(() => {
    restart()
})
onKeyPressRepeat(k: Key, action: (k: Key) => void) => EventController
Register an event that runs when user presses certain key (also fires repeatedly when they key is being held down).
since
v2000.1
// delete last character when "backspace" is being pressed and held
onKeyPressRepeat("backspace", () => {
    input.text = input.text.substring(0, input.text.length - 1)
})
onKeyPressRepeat(action: (k: Key) => void) => EventController
onKeyRelease(k: Key, action: (k: Key) => void) => EventController
Register an event that runs when user releases certain key.
since
v2000.1
onKeyRelease(action: (k: Key) => void) => EventController
onCharInput(action: (ch: string) => void) => EventController
Register an event that runs when user inputs text.
since
v2000.1
// type into input
onCharInput((ch) => {
    input.text += ch
})
onMouseDown(action: (m: MouseButton) => void) => EventController
Register an event that runs every frame when a mouse button is being held down.
since
v2000.1
onMouseDown(button: MouseButton, action: (m: MouseButton) => void) => EventController
onMousePress(action: (m: MouseButton) => void) => EventController
Register an event that runs when user clicks mouse.
since
v2000.1
onMousePress(button: MouseButton, action: (m: MouseButton) => void) => EventController
onMouseRelease(action: (m: MouseButton) => void) => EventController
Register an event that runs when user releases mouse.
since
v2000.1
onMouseRelease(button: MouseButton, action: (m: MouseButton) => void) => EventController
onMouseMove(action: (pos: Vec2, delta: Vec2) => void) => EventController
Register an event that runs whenever user move the mouse.
since
v2000.1
onTouchStart(action: (pos: Vec2, t: Touch) => void) => EventController
Register an event that runs when a touch starts.
since
v2000.1
onTouchMove(action: (pos: Vec2, t: Touch) => void) => EventController
Register an event that runs whenever touch moves.
since
v2000.1
onTouchEnd(action: (pos: Vec2, t: Touch) => void) => EventController
Register an event that runs when a touch ends.
since
v2000.1
onScroll(action: (delta: Vec2) => void) => EventController
Register an event that runs when mouse wheel scrolled.
since
v3000.0
onHide(action: () => void) => EventController
Register an event that runs when tab is hidden.
since
v3000.2
onShow(action: () => void) => EventController
Register an event that runs when tab is shown.
since
v3000.2
onGamepadButtonDown(btn: GamepadButton, action: (btn: GamepadButton) => void) => EventController
Register an event that runs every frame when certain gamepad button is held down.
since
v3000.0
onGamepadButtonDown(action: (btn: GamepadButton) => GamepadButton) => EventController
Register an event that runs every frame when any gamepad button is held down.
since
v3000.0
onGamepadButtonPress(btn: GamepadButton, action: (btn: GamepadButton) => void) => EventController
Register an event that runs when user presses certain gamepad button.
since
v3000.0
onGamepadButtonPress(action: (btn: GamepadButton) => GamepadButton) => EventController
Register an event that runs when user presses any gamepad button.
since
v3000.0
onGamepadButtonRelease(btn: GamepadButton, action: (btn: GamepadButton) => void) => EventController
Register an event that runs when user releases any gamepad button.
since
v3000.0
onGamepadButtonRelease(action: (btn: GamepadButton) => void) => EventController
Register an event that runs when user releases certain gamepad button.
since
v3000.0
onGamepadStick(stick: GamepadStick, action: (value: Vec2) => void) => EventController
Register an event that runs when the gamepad axis exists.
since
v3000.0
onSceneLeave(action: (newScene?: string) => void) => EventController
Register an event that runs when current scene ends.
since
v3000.0
Assets
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<string, SpriteData>>
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<string, SpriteData>>
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
v3000.0
loadSound(name: string | null, src: string | ArrayBuffer) => 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)
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
v3000.0
// 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 infomation on the layout of the bitmap.
since
v3000.0
// 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, frag?: string) => 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 kaboom
    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, frag?: string) => Asset<ShaderData>
Load a shader with vertex and fragment code file url.
since
v3000.0
// load only a fragment shader from URL
loadShader("outline", null, "/shaders/outline.glsl", true)
load(l: Promise<T>) => 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
v3000.0
getSprite(name: string) => Asset<SpriteData> | void
Get SpriteData from name.
since
v3000.0
getSound(name: string) => Asset<SoundData> | void
Get SoundData from name.
since
v3000.0
getFont(name: string) => Asset<FontData> | void
Get FontData from name.
since
v3000.0
getBitmapFont(name: string) => Asset<BitmapFontData> | void
Get BitmapFontData from name.
since
v3000.0
getShader(name: string) => Asset<ShaderData> | void
Get ShaderData from name.
since
v3000.0
getAsset(name: string) => Asset<any> | void
Get custom data from name.
since
v3000.0
type
Asset
loaded: boolean
loaded(data: D) => Asset<D>
data: D | null
error: Error | null
onLoad(action: (data: D) => void) => Asset<D>
onError(action: (err: Error) => void) => Asset<D>
onFinish(action: () => void) => Asset<D>
then(action: (data: D) => void) => Asset<D>
catch(action: (err: Error) => void) => Asset<D>
finally(action: () => void) => Asset<D>
tex: Texture
frames: Quad[]
anims: SpriteAnims
width: number
since
v3000.2
height: number
since
v3000.2
slice9: NineSlice | null
from(src: LoadSpriteSrc, opt?: LoadSpriteOpt) => Promise<SpriteData>
fromImage(data: ImageSource, opt?: LoadSpriteOpt) => SpriteData
fromURL(url: string, opt?: LoadSpriteOpt) => Promise<SpriteData>
buf: AudioBuffer
fromArrayBuffer(buf: ArrayBuffer) => Promise<SoundData>
fromURL(url: string) => Promise<SoundData>
Info
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()
})
time() => number
Get the total time since beginning.
isFocused() => boolean
If the game canvas is currently focused.
since
v2000.1
isTouchscreen() => boolean
Is currently on a touch screen device.
since
v3000.0
mousePos() => Vec2
Get current mouse position (without camera transform).
mouseDeltaPos() => Vec2
How much mouse moved last frame.
isKeyDown(k?: Key) => boolean
If certain key is currently down.
since
v2000.1
// equivalent to the calling bean.move() in an onKeyDown("left")
onUpdate(() => {
    if (isKeyDown("left")) {
        bean.move(-SPEED, 0)
    }
})
isKeyPressed(k?: Key) => boolean
If certain key is just pressed last frame.
since
v2000.1
isKeyPressedRepeat(k?: Key) => boolean
If certain key is just pressed last frame (also fires repeatedly when the key is being held down).
since
v2000.1
isKeyReleased(k?: Key) => boolean
If certain key is just released last frame.
since
v2000.1
isMouseDown(button?: MouseButton) => boolean
If a mouse button is currently down.
since
v2000.1
isMousePressed(button?: MouseButton) => boolean
If a mouse button is just clicked last frame.
since
v2000.1
isMouseReleased(button?: MouseButton) => boolean
If a mouse button is just released last frame.
since
v2000.1
isMouseMoved() => boolean
If mouse moved last frame.
since
v2000.1
isGamepadButtonPressed(btn?: GamepadButton) => boolean
If a gamepad button is just pressed last frame
since
v3000.0
isGamepadButtonDown(btn?: GamepadButton) => boolean
If a gamepad button is currently held down.
since
v3000.0
isGamepadButtonReleased(btn?: GamepadButton) => boolean
If a gamepad button is just released last frame.
since
v3000.0
getGamepadStick(stick: GamepadStick) => Vec2
Get stick axis values from a gamepad.
since
v3000.2
charInputted() => string[]
List of characters inputted since last frame.
since
v3000.0
shake(intensity: number)
Camera shake.
// 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
camPos() => Vec2
camScale(scale: Vec2) => Vec2
Get / set camera scale.
camScale(x: number, y: number) => Vec2
camScale() => Vec2
camRot(angle?: number) => number
Get / set camera rotation.
toScreen(p: Vec2) => Vec2
Transform a point from world position to screen position.
toWorld(p: Vec2) => Vec2
Transform a point from screen position to world position.
setGravity(g: number)
Set gravity.
getGravity() => number
Get gravity.
setBackground(color: Color, alpha?: number)
Set background color.
setBackground(r: number, g: number, b: number, alpha?: number)
getBackground() => Color
Get background color.
getGamepads() => KGamePad[]
Get connected gamepads.
since
v3000.0
setCursor(style: Cursor)
Set cursor style (check Cursor type for possible values). Cursor will be reset to "default" every frame so use this in an per-frame action.
since
v3000.0
button.onHover((c) => {
    setCursor("pointer")
})
getCursor() => Cursor
Get current cursor style.
since
v3000.0 ```
setCursorLocked(locked: boolean)
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
v3000.0
isCursorLocked() => boolean
Get if cursor is currently locked.
since
v3000.0 ```
setFullscreen(f?: boolean)
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())
})
isFullscreen() => boolean
If currently in fullscreen mode.
Timer
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) => EventController
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",
    ])
})
Audio
play(src: string | SoundData | Asset<SoundData> | MusicData | Asset<MusicData>, options?: AudioPlayOpt) => AudioPlay
Play a piece of audio.
returns
A control handle.
// 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.
volume(v?: number) => number
Sets global volume.
// makes everything quieter
volume(0.5)
audioCtx: AudioContext
Get the underlying browser AudioContext.
Math
rand() => number
Get a random number between 0 - 1.
rand(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(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(p: Vec2) => Vec2
vec2(xy: number) => Vec2
vec2() => 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
v3000.2
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
v2000.1
// 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(lst: T[]) => T
Choose a random item from a list.
// decide the best fruit randomly
const bestFruit = choose(["apple", "banana", "pear", "watermelon"])
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(from: V, to: V, t: number) => V
Linear interpolation.
tween(from: V, to: V, duration: number, setValue: (value: V) => void, easeFunc?: (t: number) => number) => TweenController
Tweeeeeeeening!
since
v3000.0
// 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
v3000.0
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.
evaluateBezier(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number) => Vec2
Evaluate the Bezier at the given t
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: Point) => boolean
Check if a point is inside a rectangle.
testCirclePolygon(c: Circle, p: Polygon) => boolean
Check if a circle and polygon intersect linewise.
type
Line
p1: Vec2
p2: Vec2
transform(m: Mat4) => Line
bbox() => Rect
area() => number
clone() => Line
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
type
Rect
pos: Vec2
width: number
height: number
fromPoints(p1: Vec2, p2: Vec2) => Rect
center() => Vec2
points() => unknown
transform(m: Mat4) => Polygon
bbox() => Rect
area() => number
clone() => Rect
distToPoint(p: Vec2) => number
sdistToPoint(p: Vec2) => number
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
type
Circle
center: Vec2
radius: number
transform(m: Mat4) => Ellipse
bbox() => Rect
area() => number
clone() => Circle
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
center: Vec2
radiusX: number
radiusY: number
transform(m: Mat4) => Ellipse
bbox() => Rect
area() => number
clone() => Ellipse
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
pts: Vec2[]
transform(m: Mat4) => Polygon
bbox() => Rect
area() => number
clone() => Polygon
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
type
Vec2
x: number
y: number
LEFT: Vec2
RIGHT: Vec2
UP: Vec2
DOWN: Vec2
fromAngle(deg: number) => Vec2
clone() => Vec2
add(p: Vec2) => Vec2
Returns the addition with another vector.
add(x: number, y: number) => Vec2
sub(p: Vec2) => Vec2
Returns the subtraction with another vector.
sub(x: number, y: number) => Vec2
scale(p: Vec2) => Vec2
Scale by another vector, or a single number.
scale(s: number) => Vec2
scale(sx: number, sy: number) => Vec2
dot(p: Vec2) => number
Get the dot product with another vector.
cross(p2: Vec2) => number
Get the cross product with another vector.
since
v3000.0
dist(p: Vec2) => number
Get distance between another vector.
sdist(p: Vec2) => number
Get squared distance between another vector.
since
v3000.0
len() => number
slen() => number
Get squared length of a vector.
since
v3000.0
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
v3000.0
project(on: Vec2) => Vec2
Get the projection of a vector onto another vector.
since
v3000.0
reject(on: Vec2) => Vec2
Get the rejection of a vector onto another vector.
since
v3000.0
angle(p: Vec2) => number
Get the angle of the vector from p towards this.
angleBetween(args: ...) => number
Get the angle between this vector and another vector.
since
v3000.0
lerp(p: Vec2, t: number) => Vec2
Linear interpolate to a destination vector (for positions).
slerp(p: Vec2, t: number) => Vec2
Spherical linear interpolate to a destination vector (for rotations).
since
v3000.0
isZero() => boolean
If both x and y is 0.
since
v3000.0
toFixed(n: number) => Vec2
To n precision floating point.
transform(n: Mat4) => Vec2
Multiply by a Mat4.
since
v3000.0
bbox() => Rect
eq(p: Vec2) => boolean
type
Color
0-255 RGBA color.
r: number
Red (0-255).
g: number
Green (0-255).
b: number
Blue (0-255).
fromArray(arr: number[]) => Color
fromHSL(h: number, s: number, l: number) => Color
fromHex(hex: number | string) => Color
Create color from hex string or literal.
since
v3000.0
Color.fromHex(0xfcef8d)
Color.fromHex("#5ba675")
Color.fromHex("d46eb3")
RED: Color
GREEN: Color
BLUE: Color
YELLOW: Color
MAGENTA: Color
CYAN: Color
WHITE: Color
BLACK: Color
clone() => Color
lighten(n: number) => Color
Lighten the color (adds RGB by n).
darken(n: number) => Color
Darkens the color (subtracts RGB by n).
invert() => Color
mult(other: Color) => Color
lerp(dest: Color, t: number) => Color
Linear interpolate to a destination color.
since
v3000.0
eq(c: Color) => boolean
toHSL() => unknown
Convert color into HSL format.
since
v3000.2
toHex() => string
Return the hex string of color.
since
v3000.0
type
Mat4
m: number[]
translate(p: Vec2) => Mat4
translate(p: Vec2) => Mat4
scale(s: Vec2) => Mat4
scale(s: Vec2) => Mat4
rotateX(a: number) => Mat4
rotateY(a: number) => Mat4
rotateZ(a: number) => Mat4
clone() => Mat4
mult(other: Mat4) => Mat4
multVec2(p: Vec2) => Vec2
rotate(a: number) => Mat4
getTranslation() => Vec2
getScale() => Vec2
getRotation() => number
getSkew() => Vec2
invert() => Mat4
type
Quad
x: number
y: number
w: number
h: number
scale(q: Quad) => Quad
pos() => Vec2
clone() => Quad
eq(q: Quad) => boolean
type
RNG
seed: number
gen() => number
genNumber(a: number, b: number) => number
genVec2(a: Vec2, b?: Vec2) => Vec2
genColor(a: Color, b: Color) => Color
genAny(args: ...) => T
Scene
scene(id: SceneName, def: SceneDef)
Define a scene.
go(id: SceneName, args: ...)
Go to a scene, passing all rest args to scene callback.
Level
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(),
            solid(),
        ],
        "$": () => [
            sprite("coin"),
            area(),
            pos(0, -9),
        ],
        "^": () => [
            sprite("spike"),
            area(),
            "danger",
        ],
    }
})
Data
getData(key: string, def?: T) => T
Get data from local storage, if not present can set to a default value.
setData(key: string, data: any)
Set data from local storage.
Draw
drawSprite(options: DrawSpriteOpt)
Draw a sprite.
drawSprite({
    sprite: "bean",
    pos: vec2(100, 200),
    frame: 3,
})
drawText(options: DrawTextOpt)
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)
Draw a rectangle.
drawRect({
    width: 120,
    height: 240,
    pos: vec2(20, 20),
    color: YELLOW,
    outline: { color: BLACK, width: 4 },
})
drawLine(options: DrawLineOpt)
Draw a line.
drawLine({
    p1: vec2(0),
    p2: mousePos(),
    width: 4,
    color: rgb(0, 0, 255),
})
drawLines(options: DrawLinesOpt)
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)
Draw a curve.
drawCurve(t => evaluateBezier(a, b, c, d, t)
 {
    width: 2,
    color: rgb(0, 0, 255),
})
drawBezier(opt: DrawBezierOpt)
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)
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)
Draw a circle.
drawCircle({
    pos: vec2(100, 200),
    radius: 120,
    color: rgb(255, 255, 0),
})
drawEllipse(options: DrawEllipseOpt)
Draw an ellipse.
drawEllipse({
    pos: vec2(100, 200),
    radiusX: 120,
    radiusY: 120,
    color: rgb(255, 255, 0),
})
drawPolygon(options: DrawPolygonOpt)
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)
Draw a rectangle with UV data.
drawFormattedText(text: FormattedText)
Draw a piece of formatted text from formatText().
since
v2000.2
// text background
const txt = formatText({
    text: "oh hi",
})

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

drawFormattedText(txt)
drawMasked(content: () => void, mask: () => void)
Whatever drawn in content will only be drawn if it's also drawn in mask (mask will not be rendered).
since
v3000.0
drawSubtracted(content: () => void, mask: () => void)
Subtract whatever drawn in content by whatever drawn in mask (mask will not be rendered).
since
v3000.0
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()
Pop the topmost transform matrix from the transform stack.
pushTranslate(x: number, y: number)
Translate all subsequent draws.
pushTranslate(100, 100)

// this will be drawn at (120, 120)
drawText({
    text: "oh hi",
    pos: vec2(20, 20),
})
pushTranslate(p: Vec2)
pushScale(x: number, y: number)
Scale all subsequent draws.
pushScale(s: number)
pushScale(s: Vec2)
pushRotate(angle: number)
Rotate all subsequent draws.
pushMatrix(mat: Mat4)
Apply a transform matrix, ignore all prior transforms.
since
v3000.0
usePostEffect(name: string, uniform?: Uniform | (() => Uniform))
Apply a post process effect from a shader name.
since
v3000.0
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
v2000.2
// 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
v3000.2
Debug
debug: Debug
// pause the whole game
debug.paused = true

// enter inspect mode
debug.inspect = true
Misc
plug(plugin: KaboomPlugin<T>) => unknown
Import a plugin.
screenshot() => string
Take a screenshot and get the dataurl of the image.
returns
The dataURL of the image.
download(filename: string, dataurl: string)
Trigger a file download from a url.
since
v3000.0
downloadText(filename: string, text: string)
Trigger a text file download.
since
v3000.0
downloadJSON(filename: string, data: any)
Trigger a json download from a .
since
v3000.0
downloadBlob(filename: string, blob: Blob)
Trigger a file download from a blob.
since
v3000.0
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
A control handle.
since
v2000.1
addKaboom(pos: Vec2, opt?: BoomOpt) => GameObj
Add an explosion
ASCII_CHARS: string
All chars in ASCII.
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
GREEN: Color
BLUE: Color
YELLOW: Color
MAGENTA: Color
CYAN: Color
WHITE: Color
BLACK: Color
canvas: HTMLCanvasElement
The canvas DOM kaboom is currently using.
quit: () => void
End everything.
type
Event
add(action: (args: ...) => void) => EventController
addOnce(action: (args: ...) => void) => EventController
next() => Promise<Args>
trigger(args: ...)
numListeners() => number
clear()
on(name: Name, action: (args: ...) => void) => EventController
onOnce(name: Name, action: (args: ...) => void) => EventController
next(name: Name) => Promise<unknown>
trigger(name: Name, args: ...)
remove(name: Name)
clear()
numListeners(name: Name) => number
paused: boolean
If the event handler is paused.
cancel: () => void
Cancel the event handler.
join(events: EventController[]) => EventController
VERSION: string
Current Kaboom library version.
since
v3000.0
type
Tag
string
type
Expand
Expand<UnionToIntersection<Defined<T>>>
Omit<MergeObj<T>, unknown>
MergeObj<ReturnType<T[number]>>
Array<T | Tag>
Array<T | KaboomPlugin<any>>
type
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"
"left" | "right" | "middle" | "back" | "forward"
"north" | "east" | "south" | "west" | "ltrigger" | "rtrigger" | "lshoulder" | "rshoulder" | "select" | "start" | "lstick" | "rstick" | "dpad-up" | "dpad-right" | "dpad-down" | "dpad-left" | "home" | "capture"
"left" | "right"
buttons: Record<string, GamepadButton>
sticks: Partial<Record<GamepadStick,
x: number
y: number
>
>
index: number
The order of the gamepad in the gamepad list.
isPressed(b: GamepadButton) => boolean
If certain button is pressed.
isDown(b: GamepadButton) => boolean
If certain button is held down.
isReleased(b: GamepadButton) => boolean
If certain button is released.
getStick(stick: GamepadStick) => Vec2
Get the value of a stick.
Record<Tag, string | null>
Kaboom 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)
font?: string
Default font (defaults to "monospace").
pixelDensity?: number
Device pixel scale (defaults to window.devicePixelRatio, high pixel density will hurt performance).
since
v3000.0
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?: number[] | 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.
texFilter?: TexFilter
Default texture filter.
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
v3000.1
hashGridSize?: number
Size of the spatial hash grid for collision detection (default 64).
since
v3000.0
touchToMouse?: boolean
If translate touch events as mouse clicks (default true).
loadingScreen?: boolean
If kaboom should render a default loading screen when assets are not fully ready (default true).
since
v3000.0
backgroundAudio?: boolean
If pause audio when tab is not active (default false).
since
v3000.0
gamepads?: Record<string, GamepadDef>
Custom gamepad definitions (see gamepad.json for reference of the format).
since
v3000.0
maxFPS?: number
Limit framerate to an amount per second.
since
v3000.0
focus?: boolean
If focus on the canvas on start (default true).
since
v3000.2
global?: boolean
If import all kaboom functions to global (default true).
plugins?: T
List of plugins to import.
burp?: boolean
Enter burp mode.
(k: KaboomCtx) => T | ((args: ...) => (k: KaboomCtx) => T)
Base interface of all game objects.
add(comps?: CompList<T> | GameObj<T>) => GameObj<T>
Add a child.
since
v3000.0
readd(obj: GameObj<T>) => GameObj<T>
Remove and re-add the game obj, without triggering add / destroy events.
remove(obj: GameObj)
Remove a child.
since
v3000.0
removeAll(tag: Tag)
Remove all children with a certain tag.
since
v3000.0
removeAll()
Remove all children.
since
v3000.0
get(tag: Tag | Tag[], opts?: GetOpt) => GameObj[]
Get a list of all game objs with certain tag.
since
v3000.0
children: GameObj[]
Get all children game objects.
since
v3000.0
update()
Update this game object and all children game objects.
since
v3000.0
draw()
Draw this game object and all children game objects.
since
v3000.0
drawInspect: () => void
Draw debug info in inspect mode
since
v3000.0
clearEvents: () => void
is(tag: Tag | Tag[]) => boolean
If there's certain tag(s) on the game obj.
use(comp: Comp | Tag)
Add a component or tag.
unuse(comp: Tag)
Remove a tag or a component with its id.
on(event: string, action: (args: ...) => void) => EventController
Register an event.
trigger(event: string, args: ...)
Trigger an event.
destroy()
Remove the game obj from scene.
c(id: Tag) => Comp | unknown
Get state for a specific comp.
inspect() => GameObjInspect
Gather debug info of all comps.
onAdd(action: () => void) => EventController
Register an event that runs when the game obj is added to the scene.
onUpdate(action: () => void) => EventController
Register an event that runs every frame as long as the game obj exists.
since
v2000.1
onDraw(action: () => void) => EventController
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
v2000.1
onDestroy(action: () => void) => EventController
Register an event that runs when the game obj is destroyed.
since
v2000.1
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
v3000.0
transform: Mat4
Calculated transform matrix of a game object.
since
v3000.0
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
v3000.2
onKeyDown(key: Key, action: (key: Key) => void) => EventController
onKeyDown(action: (key: Key) => void) => EventController
onKeyPress(key: Key, action: (key: Key) => void) => EventController
onKeyPress(action: (key: Key) => void) => EventController
onKeyPressRepeat(k: Key, action: (k: Key) => void) => EventController
onKeyPressRepeat(action: (k: Key) => void) => EventController
onKeyRelease(k: Key, action: (k: Key) => void) => EventController
onKeyRelease(action: (k: Key) => void) => EventController
onCharInput(action: (ch: string) => void) => EventController
onMouseDown(action: (m: MouseButton) => void) => EventController
onMouseDown(button: MouseButton, action: (m: MouseButton) => void) => EventController
onMousePress(action: (m: MouseButton) => void) => EventController
onMousePress(button: MouseButton, action: (m: MouseButton) => void) => EventController
onMouseRelease(action: (m: MouseButton) => void) => EventController
onMouseRelease(button: MouseButton, action: (m: MouseButton) => void) => EventController
onMouseMove(action: (pos: Vec2, delta: Vec2) => void) => EventController
onTouchStart(action: (pos: Vec2, t: Touch) => void) => EventController
onTouchMove(action: (pos: Vec2, t: Touch) => void) => EventController
onTouchEnd(action: (pos: Vec2, t: Touch) => void) => EventController
onScroll(action: (delta: Vec2) => void) => EventController
onGamepadButtonDown(btn: GamepadButton, action: (btn: GamepadButton) => void) => EventController
onGamepadButtonDown(action: (btn: GamepadButton) => GamepadButton) => EventController
onGamepadButtonPress(btn: GamepadButton, action: (btn: GamepadButton) => void) => EventController
onGamepadButtonPress(action: (btn: GamepadButton) => GamepadButton) => EventController
onGamepadButtonRelease(btn: GamepadButton, action: (btn: GamepadButton) => void) => EventController
onGamepadButtonRelease(action: (btn: GamepadButton) => void) => EventController
onGamepadStick(stick: GamepadStick, action: (value: Vec2) => void) => EventController
GameObjRaw&MergeComps<T>
string
(args: ...) => void
type
GetOpt
recursive?: boolean
Recursively get all children and their descendents.
liveUpdate?: boolean
Live update the returned list every time object is added / removed.
Screen recording control handle.
pause()
Pause the recording.
resume()
Resume the recording.
stop() => Promise<Blob>
Stop the recording and get the video data as mp4 Blob.
since
v3000.0
download(filename?: string)
Stop the recording and downloads the file as mp4. Trying to resume later will lead to error.
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.
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.
width: number
height: number
frames: string[]
anims: SpriteAnims
Record<string, SpriteAnim>
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
v3000.0
frames?: Quad[]
Individual frames.
since
v3000.0
anims?: SpriteAnims
Animation configuration.
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.
Record<string, 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.
type
Asset
loaded: boolean
loaded(data: D) => Asset<D>
data: D | null
error: Error | null
onLoad(action: (data: D) => void) => Asset<D>
onError(action: (err: Error) => void) => Asset<D>
onFinish(action: () => void) => Asset<D>
then(action: (data: D) => void) => Asset<D>
catch(action: (err: Error) => void) => Asset<D>
finally(action: () => void) => Asset<D>
string | ImageSource
frames: Array<
frame:
x: number
y: number
w: number
h: number
>
meta:
size:
w: number
h: number
frameTags: Array<
from: number
to: number
direction: "forward" | "reverse" | "pingpong"
>
tex: Texture
frames: Quad[]
anims: SpriteAnims
width: number
since
v3000.2
height: number
since
v3000.2
slice9: NineSlice | null
from(src: LoadSpriteSrc, opt?: LoadSpriteOpt) => Promise<SpriteData>
fromImage(data: ImageSource, opt?: LoadSpriteOpt) => SpriteData
fromURL(url: string, opt?: LoadSpriteOpt) => Promise<SpriteData>
buf: AudioBuffer
fromArrayBuffer(buf: ArrayBuffer) => Promise<SoundData>
fromURL(url: string) => Promise<SoundData>
string
filter?: TexFilter
outline?: number | Outline
size?: number
The size to load the font in (default 64).
since
v3000.2
chars?: string
filter?: TexFilter
outline?: number
fontface: FontFace
filter: TexFilter
outline: Outline | null
GfxFont
Shader
Audio play configurations.
paused?: boolean
If audio should start out paused.
since
v3000.0
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.
play(time?: number)
Start playing audio.
since
v3000.0
seek(time: number)
Seek time.
since
v3000.0
stop()
Stop the sound.
since
v3000.2
paused: boolean
If the sound is paused.
since
v2000.1
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.
loop: boolean
If the audio should start again when it ends.
time() => number
The current playing time (not accurate if speed is changed).
duration() => number
The total duration.
onEnd(action: () => void) => EventController
Register an event that runs when audio ends.
since
v3000.0
then(action: () => void) => EventController
type
Shader
ctx: GfxCtx
glProgram: WebGLProgram
bind() => unknown
unbind() => unknown
send(uniform: Uniform) => unknown
free() => unknown
filter?: TexFilter
wrap?: TexWrap
Exclude<TexImageSource, VideoFrame>
type
GfxCtx
any
ctx: GfxCtx
src: null | ImageSource
glTex: WebGLTexture
width: number
height: number
fromImage(ctx: GfxCtx, img: ImageSource, opt?: TextureOpt) => Texture
update(img: ImageSource, x?: number, y?: number) => unknown
bind() => unknown
unbind() => unknown
free()
Frees up texture memory. Call this once the texture is no longer being used to avoid memory leaks.
ctx: GfxCtx
tex: Texture
glFramebuffer: WebGLFramebuffer
glRenderbuffer: WebGLRenderbuffer
width: number
height: number
toImageData() => ImageData
toDataURL() => string
clear()
draw(action: () => void)
bind()
unbind()
free()
type
Canvas
width: number
height: number
toImageData() => ImageData
toDataURL() => string
draw(action: () => void)
tex: Texture
map: Record<string, Quad>
size: number
type
Vertex
pos: Vec2
uv: Vec2
color: Color
opacity: number
"nearest" | "linear"
"repeat" | "clampToEdge"
Common render properties.
pos?: Vec2
scale?: Vec2 | number
angle?: number
color?: Color
opacity?: number
fixed?: boolean
shader?: string | ShaderData | Asset<ShaderData>
uniform?: Uniform
outline?: Outline
RenderProps&
sprite: string | SpriteData | Asset<SpriteData>
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".
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".
RenderProps&
width: number
Width of the rectangle.
height: number
Height of the rectangle.
gradient?: unknown
Use gradient instead of solid color.
since
v3000.0
horizontal?: boolean
If the gradient should be horizontal.
since
v3000.0
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.
anchor?: Anchor | Vec2
The anchor point, or the pivot point. Default to "topleft".
Omit<RenderProps, "angle" | "scale">&
p1: Vec2
Starting point of the line.
p2: Vec2
Ending point of the line.
width?: number
The width, or thickness of the line,
"none" | "round" | "bevel" | "miter"
Omit<RenderProps, "angle" | "scale">&
pts: Vec2[]
The points that should be connected with a line.
width?: number
The width, or thickness of the lines,
radius?: number
The radius of each corner.
join?: LineJoin
Line join style (default "none").
RenderProps&
segments?: number
The amount of line segments to draw.
width?: number
The width of the line.
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.
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.
Omit<RenderProps, "angle">&
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?: unknown
Use gradient instead of solid color.
since
v3000.0
resolution?: number
Multiplier for circle vertices resolution (default 1)
anchor?: Anchor | Vec2
The anchor point, or the pivot point. Default to "topleft".
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?: unknown
Use gradient instead of solid color.
since
v3000.0
resolution?: number
Multiplier for circle vertices resolution (default 1)
anchor?: Anchor | Vec2
The anchor point, or the pivot point. Default to "topleft".
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
The radius of each corner.
colors?: Color[]
The color of each vertice.
since
v3000.0
width?: number
The width, or thinkness of the line.
color?: Color
The color of the line.
join?: LineJoin
Line join.
since
v3000.0
"center" | "left" | "right"
RenderProps&
text: string
The text to render.
font?: string | FontData | Asset<FontData> | BitmapFontData | Asset<BitmapFontData>
The name of font to use.
size?: number
The size of text (the height of each character).
align?: TextAlign
Text alignment (default "left")
since
v3000.0
width?: number
The maximum width. Will wrap word around if exceed.
lineSpacing?: number
The gap between each line (only available for bitmap fonts).
since
v2000.2
letterSpacing?: number
The gap between each character (only available for bitmap fonts).
since
v2000.2
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
v2000.1
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
v2000.2
width: number
height: number
chars: FormattedChar[]
opt: DrawTextOpt
One formated character.
ch: string
tex: Texture
width: number
height: number
quad: Quad
pos: Vec2
scale: Vec2
angle: number
color: Color
opacity: number
(idx: number, ch: string) => CharTransform
Describes how to transform each character.
pos?: Vec2
scale?: Vec2 | number
angle?: number
color?: Color
opacity?: number
type
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"
type
Anchor
"topleft" | "top" | "topright" | "left" | "center" | "right" | "botleft" | "bot" | "botright"
unknown | unknown | unknown | unknown | unknown
type
Vec2
x: number
y: number
LEFT: Vec2
RIGHT: Vec2
UP: Vec2
DOWN: Vec2
fromAngle(deg: number) => Vec2
clone() => Vec2
add(p: Vec2) => Vec2
Returns the addition with another vector.
add(x: number, y: number) => Vec2
sub(p: Vec2) => Vec2
Returns the subtraction with another vector.
sub(x: number, y: number) => Vec2
scale(p: Vec2) => Vec2
Scale by another vector, or a single number.
scale(s: number) => Vec2
scale(sx: number, sy: number) => Vec2
dot(p: Vec2) => number
Get the dot product with another vector.
cross(p2: Vec2) => number
Get the cross product with another vector.
since
v3000.0
dist(p: Vec2) => number
Get distance between another vector.
sdist(p: Vec2) => number
Get squared distance between another vector.
since
v3000.0
len() => number
slen() => number
Get squared length of a vector.
since
v3000.0
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
v3000.0
project(on: Vec2) => Vec2
Get the projection of a vector onto another vector.
since
v3000.0
reject(on: Vec2) => Vec2
Get the rejection of a vector onto another vector.
since
v3000.0
angle(p: Vec2) => number
Get the angle of the vector from p towards this.
angleBetween(args: ...) => number
Get the angle between this vector and another vector.
since
v3000.0
lerp(p: Vec2, t: number) => Vec2
Linear interpolate to a destination vector (for positions).
slerp(p: Vec2, t: number) => Vec2
Spherical linear interpolate to a destination vector (for rotations).
since
v3000.0
isZero() => boolean
If both x and y is 0.
since
v3000.0
toFixed(n: number) => Vec2
To n precision floating point.
transform(n: Mat4) => Vec2
Multiply by a Mat4.
since
v3000.0
bbox() => Rect
eq(p: Vec2) => boolean
type
Mat4
m: number[]
translate(p: Vec2) => Mat4
translate(p: Vec2) => Mat4
scale(s: Vec2) => Mat4
scale(s: Vec2) => Mat4
rotateX(a: number) => Mat4
rotateY(a: number) => Mat4
rotateZ(a: number) => Mat4
clone() => Mat4
mult(other: Mat4) => Mat4
multVec2(p: Vec2) => Vec2
rotate(a: number) => Mat4
getTranslation() => Vec2
getScale() => Vec2
getRotation() => number
getSkew() => Vec2
invert() => Mat4
type
Color
0-255 RGBA color.
r: number
Red (0-255).
g: number
Green (0-255).
b: number
Blue (0-255).
fromArray(arr: number[]) => Color
fromHSL(h: number, s: number, l: number) => Color
fromHex(hex: number | string) => Color
Create color from hex string or literal.
since
v3000.0
Color.fromHex(0xfcef8d)
Color.fromHex("#5ba675")
Color.fromHex("d46eb3")
RED: Color
GREEN: Color
BLUE: Color
YELLOW: Color
MAGENTA: Color
CYAN: Color
WHITE: Color
BLACK: Color
clone() => Color
lighten(n: number) => Color
Lighten the color (adds RGB by n).
darken(n: number) => Color
Darkens the color (subtracts RGB by n).
invert() => Color
mult(other: Color) => Color
lerp(dest: Color, t: number) => Color
Linear interpolate to a destination color.
since
v3000.0
eq(c: Color) => boolean
toHSL() => unknown
Convert color into HSL format.
since
v3000.2
toHex() => string
Return the hex string of color.
since
v3000.0
type
Quad
x: number
y: number
w: number
h: number
scale(q: Quad) => Quad
pos() => Vec2
clone() => Quad
eq(q: Quad) => boolean
number | Vec2 | Color
number | Vec2 | Color
Vec2 | Circle | Ellipse | Line | Rect | Polygon
fraction: number
normal: Vec2
point: Vec2
RaycastHit | null
type
Rect
pos: Vec2
width: number
height: number
fromPoints(p1: Vec2, p2: Vec2) => Rect
center() => Vec2
points() => unknown
transform(m: Mat4) => Polygon
bbox() => Rect
area() => number
clone() => Rect
distToPoint(p: Vec2) => number
sdistToPoint(p: Vec2) => number
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
type
Line
p1: Vec2
p2: Vec2
transform(m: Mat4) => Line
bbox() => Rect
area() => number
clone() => Line
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
type
Circle
center: Vec2
radius: number
transform(m: Mat4) => Ellipse
bbox() => Rect
area() => number
clone() => Circle
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
center: Vec2
radiusX: number
radiusY: number
transform(m: Mat4) => Ellipse
bbox() => Rect
area() => number
clone() => Ellipse
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
pts: Vec2[]
transform(m: Mat4) => Polygon
bbox() => Rect
area() => number
clone() => Polygon
collides(shape: ShapeType) => boolean
contains(point: Vec2) => boolean
raycast(origin: Vec2, direction: Vec2) => RaycastResult
type
Point
Vec2
type
RNG
seed: number
gen() => number
genNumber(a: number, b: number) => number
genVec2(a: Vec2, b?: Vec2) => Vec2
genColor(a: Color, b: Color) => Color
genAny(args: ...) => T
type
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.
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 | void
Debug info for inspect mode.
drawInspect?: () => void
Draw debug info in inspect mode
since
v3000.0
number
id: string
&Comp
pos: Vec2
Object's current world position.
move(xVel: number, yVel: number)
Move how many pixels per second. If object is 'solid', it won't move into other 'solid' objects.
move(vel: Vec2)
moveBy(dx: number, dy: number)
Move how many pixels, without multiplying dt, but still checking for 'solid'.
moveBy(d: Vec2)
moveTo(dest: Vec2, speed?: number)
Move to a spot with a speed (pixels per second), teleports if speed is not given.
moveTo(x: number, y: number, speed?: number)
screenPos() => Vec2
Get position on screen after camera transform.
worldPos() => Vec2
Get position on screen after camera / parent transform.
scale: Vec2
scaleTo(s: number)
scaleTo(s: Vec2)
scaleTo(sx: number, sy: number)
scaleBy(s: number)
scaleBy(s: Vec2)
scaleBy(sx: number, sy: number)
angle: number
Angle in degrees.
rotateBy(angle: number)
Rotate in degrees.
rotateTo(s: number)
Rotate to a degree (like directly assign to .angle)
since
v3000.0
color: Color
opacity: number
fadeOut(time?: number, easeFunc?: EaseFunc) => TweenController
fadeIn?: number
Fade in n seconds when object is added to scene.
since
v3000.0
anchor: Anchor | Vec2
Anchor point for render.
type
ZComp
z: number
Defines the z-index of this game obj
follow:
obj: GameObj
offset: Vec2
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
v3000.0
isOffScreen() => boolean
If object is currently out of view.
onExitScreen(action: () => void) => EventController
Register an event that runs when object goes out of view.
onEnterScreen(action: () => void) => EventController
Register an event that runs when object enters view.
Collision resolution data.
source: GameObj
The first game object in the collision.
target: GameObj
The second game object in the collision.
displacement: Vec2
The displacement source game object have to make to avoid the collision.
resolved: boolean
If the collision is resolved.
preventResolution()
Prevent collision resolution if not yet resolved.
since
v3000.0
hasOverlap()
If the 2 objects have any overlap, or they're just touching edges.
since
v3000.0
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.
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.
offset?: Vec2
Area offset.
cursor?: Cursor
Cursor on hover.
collisionIgnore?: Tag[]
If this object should ignore collisions against certain other objects.
since
v3000.0
area:
shape: Shape | null
If we use a custom shape over render shape.
scale: Vec2
Area scale.
offset: Vec2
Area offset.
cursor: Cursor | null
Cursor on hover.
Collider area info.
collisionIgnore: Tag[]
If this object should ignore collisions against certain other objects.
since
v3000.0
isClicked() => boolean
If was just clicked on last frame.
isHovering() => boolean
If is being hovered on.
checkCollision(other: GameObj<AreaComp>) => Collision | null
Check collision with another game obj.
since
v3000.0
getCollisions() => Collision[]
Get all collisions currently happening.
since
v3000.0
isColliding(o: GameObj<AreaComp>) => boolean
If is currently colliding with another game obj.
isOverlapping(o: GameObj<AreaComp>) => 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)
Register an event runs when clicked.
since
v2000.1
onHover(action: () => void) => EventController
Register an event runs once when hovered.
since
v3000.0
onHoverUpdate(action: () => void) => EventController
Register an event runs every frame when hovered.
since
v3000.0
onHoverEnd(action: () => void) => EventController
Register an event runs once when unhovered.
since
v3000.0
onCollide(tag: Tag, f: (obj: GameObj, col?: Collision) => void)
Register an event runs once when collide with another game obj with certain tag.
since
v2001.0
onCollide(f: (obj: GameObj, col?: Collision) => void)
Register an event runs once when collide with another game obj.
since
v2000.1
onCollideUpdate(tag: Tag, f: (obj: GameObj, col?: Collision) => void) => EventController
Register an event runs every frame when collide with another game obj with certain tag.
since
v3000.0
onCollideUpdate(f: (obj: GameObj, col?: Collision) => void) => EventController
Register an event runs every frame when collide with another game obj.
since
v3000.0
onCollideEnd(tag: Tag, f: (obj: GameObj) => void) => EventController
Register an event runs once when stopped colliding with another game obj with certain tag.
since
v3000.0
onCollideEnd(f: (obj: GameObj) => void)
Register an event runs once when stopped colliding with another game obj.
since
v3000.0
hasPoint(p: Vec2) => boolean
If has a certain point inside collider.
resolveCollision(obj: GameObj)
Push out from another solid game obj if currently overlapping.
localArea() => Shape
Get the geometry data for the collider in local coordinate space.
since
v3000.0
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.
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).
draw: Comp["draw"]
width: number
Width for sprite.
height: number
Height for sprite.
frame: number
Current frame.
quad: Quad
The rectangular area of the texture to render.
play(anim: string, options?: SpriteAnimPlayOpt)
Play a piece of anim.
stop()
Stop current anim.
numFrames() => number
Get total number of frames.
curAnim() => string
Get current anim name.
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) => EventController
Register an event that runs when an animation is played.
onAnimEnd(action: (anim: string) => void) => EventController
Register an event that runs when an animation is ended.
renderArea() => Rect
since
v3000.0
draw: Comp["draw"]
text: string
The text to render.
textSize: number
The text size.
font: string | BitmapFontData
The font to use.
width: number
Width of text.
height: number
Height of text.
align: TextAlign
Text alignment ("left", "center" or "right", default "left").
since
v3000.0
lineSpacing: number
The gap between each line.
since
v2000.2
letterSpacing: number
The gap between each character.
since
v2000.2
textTransform: CharTransform | CharTransformFunc
Transform the pos, scale, rotation or color for each character based on the index or char.
since
v2000.1
textStyles: Record<string, CharTransform | CharTransformFunc>
Stylesheet for styled chunks, in the syntax of "this is a [style]text[/style] word".
since
v2000.2
renderArea() => Rect
since
v3000.0
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
v3000.0
lineSpacing?: number
The gap between each line.
since
v2000.2
letterSpacing?: number
The gap between each character.
since
v2000.2
transform?: CharTransform | CharTransformFunc
Transform the pos, scale, rotation or color for each character based on the index or char.
since
v2000.1
styles?: Record<string, CharTransform | CharTransformFunc>
Stylesheet for styled chunks, in the syntax of "this is a [style]text[/style] word".
since
v2000.2
radius?: number
Radius of the rectangle corners.
fill?: boolean
If fill the rectangle (useful if you only want to render outline with outline() component).
draw: Comp["draw"]
width: number
Width of rectangle.
height: number
Height of rectangle.
radius?: number
The radius of each corner.
renderArea() => Rect
since
v3000.0
Omit<DrawPolygonOpt, "pts">
Component to draw a polygon.
since
v3000.2
draw: Comp["draw"]
pts: Vec2[]
Points in the polygon.
radius?: number
The radius of each corner.
colors?: Color[]
The color of each vertice.
renderArea() => Polygon
fill?: boolean
If fill the circle (useful if you only want to render outline with outline() component).
draw: Comp["draw"]
radius: number
Radius of circle.
renderArea() => Rect
since
v3000.0
draw: Comp["draw"]
width: number
Width of rect.
height: number
Height of height.
renderArea() => Rect
since
v3000.0
type
Shape
Rect | Line | Point | Circle | Ellipse | Polygon
outline: Outline
type
Debug
paused: boolean
Pause the whole game.
inspect: boolean
Draw bounding boxes of all objects with `area()` component, hover to inspect their states.
timeScale: number
Global time scale.
showLog: boolean
Show the debug log or not.
fps() => number
Current frames per second.
numFrames() => number
Total number of frames elapsed.
since
v3000.0
drawCalls() => number
Number of draw calls made last frame.
stepFrame()
Step to the next frame. Useful with pausing.
clearLog()
Clear the debug log.
log(msg: string |
)
Log some text to on screen debug log.
error(msg: string |
)
Log an error message to on screen debug log.
curRecording: Recording | null
The recording handle if currently in recording mode.
since
v2000.1
numObjects() => number
Get total number of objects.
since
v3000.2
number | Vec2 | Color | Mat4 | number[] | Vec2[] | Color[]
Exclude<string, "u_tex">
Record<UniformKey, UniformValue>
uniform: Uniform
shader: string
vel: Vec2
Object current velocity.
since
v3000.2
drag: number
How much velocity decays (velocity *= (1 - drag) every frame).
since
v3000.2
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().
gravityScale: number
Gravity multiplier.
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
v3000.0
stickToPlatform?: boolean
If object should move with moving platform (default true).
since
v3000.0
curPlatform() => GameObj | null
Current platform landing on.
isGrounded() => boolean
If currently landing on a platform.
since
v2000.1
isFalling() => boolean
If currently falling.
since
v2000.1
isJumping() => boolean
If currently rising.
since
v3000.0
jump(force?: number)
Upward thrust.
onPhysicsResolve(action: (col: Collision) => void) => EventController
Register an event that runs when a collision is resolved.
since
v3000.0
onBeforePhysicsResolve(action: (col: Collision) => void) => EventController
Register an event that runs before a collision would be resolved.
since
v3000.0
onGround(action: () => void) => EventController
Register an event that runs when the object is grounded.
since
v2000.1
onFall(action: () => void) => EventController
Register an event that runs when the object starts falling.
since
v2000.1
onFallOff(action: () => void) => EventController
Register an event that runs when the object falls off platform.
since
v3000.0
onHeadbutt(action: () => void) => EventController
Register an event that runs when the object bumps into something on the head.
since
v2000.1
numJumps: number
Number of jumps allowed.
doubleJump(force?: number)
Performs double jump (the initial jump only happens if player is grounded).
onDoubleJump(action: () => void) => EventController
Register an event that runs when the object performs the second jump when double jumping.
drag?: number
How much velocity decays (velocity *= (1 - drag) every frame).
since
v3000.2
jumpForce?: number
Initial speed in pixels per second for jump().
maxVelocity?: number
Maximum velocity when falling.
gravityScale?: number
Gravity multiplier.
isStatic?: boolean
If object is static, won't move, and all non static objects won't move past it.
since
v3000.0
stickToPlatform?: boolean
If object should move with moving platform (default true).
since
v3000.0
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
v3000.0
wait(time: number, action?: () => void) => TimerController
Run the callback after n seconds.
loop(time: number, action: () => void) => EventController
Run the callback every n seconds.
since
v3000.0
tween(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
v3000.0
fixed: boolean
If the obj is unaffected by camera
stay: boolean
If the obj should not be destroyed on scene switch.
scenesToStay: string[]
Array of scenes that the obj will stay on.
hurt(n?: number)
Decrease HP by n (defaults to 1).
heal(n?: number)
Increase HP by n (defaults to 1).
hp() => number
Current health points.
setHP(hp: number)
Set current health points.
maxHP() => number | null
Max amount of HP.
setMaxHP(hp: number)
Set max amount of HP.
onHurt(action: (amount?: number) => void) => EventController
Register an event that runs when hurt() is called upon the object.
since
v2000.1
onHeal(action: (amount?: number) => void) => EventController
Register an event that runs when heal() is called upon the object.
since
v2000.1
onDeath(action: () => void) => EventController
Register an event that runs when object's HP is equal or below 0.
since
v2000.1
fade?: number
Fade out duration (default 0 which is no fade out).
state: string
Current state.
enterState: (state: string, args: ...) => void
Enter a state, trigger onStateEnd for previous state and onStateEnter for the new State state.
onStateTransition(from: string, to: string, action: () => void) => EventController
Register event that runs once when a specific state transition happens. Accepts arguments passed from `enterState(name, ...args)`.
since
v2000.2
onStateEnter: (state: string, action: (args: ...) => void) => EventController
Register event that runs once when enters a specific state. Accepts arguments passed from `enterState(name, ...args)`.
onStateEnd: (state: string, action: () => void) => EventController
Register an event that runs once when leaves a specific state.
onStateUpdate: (state: string, action: () => void) => EventController
Register an event that runs every frame when in a specific state.
onStateDraw: (state: string, action: () => void) => EventController
Register an event that runs every frame when in a specific state.
type
Mask
"intersect" | "subtract"
mask: Mask
tileWidth: number
Width of each block.
tileHeight: number
Height of each block.
pos?: Vec2
Position of the first block.
tiles:
Definition of each tile.
wildcardTile?: (sym: string, pos: Vec2) => CompList<any> | null | unknown
Called when encountered a symbol not defined in "tiles".
type
Edge
"left" | "right" | "top" | "bottom"
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`.
tilePos: Vec2
The tile position inside the level.
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.
tilePosOffset: Vec2
Position offset when setting `tilePos`.
edgeMask: EdgeMask
getLevel() => GameObj<LevelComp>
moveLeft()
moveRight()
moveUp()
moveDown()
tileWidth() => number
tileHeight() => number
numRows() => number
numColumns() => number
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(obj: CompList<T>, p: Vec2) => GameObj<T>
Spawn a tile from a component list.
spawn(sym: CompList<T>, x: number, y: number) => GameObj<T>
levelWidth() => number
Total width of level in pixels.
levelHeight() => number
Total height of level in pixels.
getAt(tilePos: Vec2) => GameObj[]
Get all game objects that's currently inside a given tile.
tile2Pos(tilePos: Vec2) => Vec2
Convert tile position to pixel position.
tile2Pos(x: number, y: number) => Vec2
pos2Tile(pos: Vec2) => Vec2
Convert pixel position to tile position.
pos2Tile(x: number, y: number) => Vec2
getTilePath(from: Vec2, to: Vec2, opts?: PathFindOpt) => Vec2[] | null
Find the path to navigate from one tile to another tile.
returns
A list of traverse points in tile positions.
getPath(from: Vec2, to: Vec2, opts?: PathFindOpt) => Vec2[] | null
Find the path to navigate from one tile to another tile.
returns
A list of traverse points in pixel positions.
getSpatialMap() => GameObj[][]
onSpatialMapChanged(cb: () => void) => EventController
onNavigationMapInvalid(cb: () => void) => EventController
invalidateNavigationMap()
onNavigationMapChanged(cb: () => void) => EventController
speed?: number
allowDiagonals?: boolean
agentSpeed: number
allowDiagonals: boolean
getDistanceToTarget() => number
getNextLocation() => Vec2 | null
getPath() => Vec2[] | null
getTarget() => Vec2 | null
isNavigationFinished() => boolean
isTargetReachable() => boolean
isTargetReached() => boolean
setTarget(target: Vec2)
onNavigationStarted(cb: () => void) => EventController
onNavigationNext(cb: () => void) => EventController
onNavigationEnded(cb: () => void) => EventController
onTargetReached(cb: () => void) => EventController
speed?: number
Animation speed.
scale?: number
Scale.
comps?: CompList<any>
Additional components.
since
v3000.0
"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"
(t: number) => number
paused: boolean
If the event handler is paused.
Cancel the event handler.
onEnd(action: () => void)
Register an event when finished.
then(action: () => void) => TimerController
TimerController&
finish()
Finish the tween now and cancel.
paused: boolean
If the event handler is paused.
cancel: () => void
Cancel the event handler.
join(events: EventController[]) => EventController
type
Event
add(action: (args: ...) => void) => EventController
addOnce(action: (args: ...) => void) => EventController
next() => Promise<Args>
trigger(args: ...)
numListeners() => number
clear()
on(name: Name, action: (args: ...) => void) => EventController
onOnce(name: Name, action: (args: ...) => void) => EventController
next(name: Name) => Promise<unknown>
trigger(name: Name, args: ...)
remove(name: Name)
clear()
numListeners(name: Name) => number