game

A LÖVE-inspired game development framework for Kit

Files

FileDescription
kit.tomlPackage manifest with metadata and dependencies
src/package.kitPackage entry point re-exporting all modules
src/game.kitGame loop, window, and timing utilities
src/graphics.kitShape drawing and text rendering
src/input.kitKeyboard, mouse, and gamepad handling
src/audio.kitSound effects and music streaming
src/assets.kitTexture, sound, music, and font loading
src/sprite.kitStatic and animated sprites with sheets
src/tilemap.kitTilemap rendering and Tiled JSON loading
src/camera.kit2D camera with smooth follow and shake
src/collision.kitAABB, circle, and line collision detection
src/quadtree.kitSpatial partitioning for collision queries
src/particles.kitParticle emitters and preset effects
src/scene.kitScene stack management and transitions
src/math.kitVectors, angles, lerp, and easing functions
src/colors.kitColor constants and RGBA utilities
src/backend/interface.kitHandle types for rendering backends
src/backend/raylib.kitRaylib backend implementation
src/backend/select.kitBackend selector (currently Raylib)
tests/game.test.kitTests for API function existence
examples/simple.kitBasic game with input and rendering
examples/minimal-test.kitMinimal game loop setup
examples/camera.kitCamera follow and zoom demonstration
examples/collision.kitCollision detection demonstration
examples/particles.kitParticle effects demonstration
examples/tilemap.kitTilemap loading and rendering
examples/hybrid-test.kitCombined feature demonstration
LICENSEMIT license file

Architecture

Game Loop

flowchart LR A[Init] --> B[Load Assets] B --> C{Game Loop} C --> D[Process Input] D --> E[Update State] E --> F[Collision Detection] F --> G[Render] G --> C C --> H[Cleanup]

Module Structure

graph TD A[package.kit] --> B[game.kit] A --> C[graphics.kit] A --> D[audio.kit] A --> E[input.kit] A --> F[assets.kit] A --> G[sprite.kit] A --> H[tilemap.kit] A --> I[camera.kit] A --> J[collision.kit] A --> K[particles.kit] A --> L[scene.kit] A --> M[math.kit] A --> N[colors.kit] J --> O[quadtree.kit] P[backend/select.kit] --> Q[backend/raylib.kit] Q --> R[raylib] B --> P C --> P D --> P E --> P F --> P

Dependencies

  • geometry
  • raylib

Installation

kit add gitlab.com/kit-lang/packages/kit-game.git

Usage

import Kit.Game as Game

# Define your game state
type State = {x: Float, y: Float, speed: Float}

# Initialize state
init = fn() => {x: 400.0, y: 300.0, speed: 200.0}

# Update state each frame (pure function)
update = fn(state, dt) =>
  dx = if Game.Input.key-down? "d" then
    state.speed * dt
  else if Game.Input.key-down? "a" then
    0.0 - state.speed * dt
  else
    0.0
  dy = if Game.Input.key-down? "s" then
    state.speed * dt
  else if Game.Input.key-down? "w" then
    0.0 - state.speed * dt
  else
    0.0
  {x: state.x + dx, y: state.y + dy, speed: state.speed}

# Draw the game
draw = fn(state) =>
  Game.Graphics.clear Game.Colors.dark-gray
  Game.Graphics.circle state.x state.y 25.0 Game.Colors.cyan
  Game.Graphics.text "WASD to move" 10.0 10.0 Game.Colors.white

# Run the game
main = fn() =>
  Game.run {
    title: "My Game", 
    width: 800, 
    height: 600, 
    fps: 60, 
    init: init, 
    update: update, 
    draw: draw
  }

main()

Game.run Configuration

FieldTypeDefaultDescription
titleString"Kit Game"Window title
widthInt800Window width
heightInt600Window height
fpsInt60Target frames per second
initfn() => StaterequiredInitialize game state
updatefn(State, Float) => StaterequiredUpdate state (receives delta time)
drawfn(State) => ()requiredRender the game
resizableBoolfalseAllow window resizing
vsyncBooltrueEnable vertical sync
fullscreenBoolfalseStart in fullscreen

Available Modules

  • Game.Graphics - Shape drawing, text rendering
  • Game.Input - Keyboard, mouse, gamepad
  • Game.Audio - Sound effects, music
  • Game.Assets - Load textures, sounds, fonts
  • Game.Sprite - Static and animated sprites
  • Game.Tilemap - Tile-based maps, Tiled JSON
  • Game.Camera - 2D camera with follow/shake
  • Game.Collision - AABB, circle, line detection
  • Game.Particles - Particle emitters and effects
  • Game.Scene - Scene stack management
  • Game.Math - Vectors, lerp, easing
  • Game.Colors - Color constants

License

MIT License - see LICENSE for details.

Exported Functions & Types

rgb

Create a color from RGB values (0-255)

Int -> Int -> Int -> Int

rgba

Create a color from RGBA values (0-255)

Int -> Int -> Int -> Int -> Int

hex

Create a color from a hex value (e.g., 0xFF0000 for red)

Int -> Int

white

Pure white (255, 255, 255)

Int

black

Pure black (0, 0, 0)

Int

blank

Fully transparent (alpha = 0)

Int

light-gray

Light gray (200, 200, 200)

Int

gray

Medium gray (130, 130, 130)

Int

dark-gray

Dark gray (80, 80, 80)

Int

red

Pure red (230, 41, 55)

Int

green

Pure green (0, 228, 48)

Int

blue

Pure blue (0, 121, 241)

Int

yellow

Bright yellow (253, 249, 0)

Int

orange

Orange (255, 161, 0)

Int

pink

Pink (255, 109, 194)

Int

purple

Purple (200, 122, 255)

Int

violet

Violet (135, 60, 190)

Int

magenta

Magenta (255, 0, 255)

Int

gold

Gold (255, 203, 0)

Int

maroon

Maroon (190, 33, 55)

Int

lime

Lime green (0, 158, 47)

Int

dark-green

Dark green (0, 117, 44)

Int

sky-blue

Sky blue (102, 191, 255)

Int

dark-blue

Dark blue (0, 82, 172)

Int

beige

Beige (211, 176, 131)

Int

brown

Brown (127, 106, 79)

Int

dark-brown

Dark brown (76, 63, 47)

Int

cyan

Cyan (0, 255, 255)

Int

teal

Teal (0, 128, 128)

Int

coral

Coral (255, 127, 80)

Int

salmon

Salmon (250, 128, 114)

Int

Navy blue (0, 0, 128)

Int

olive

Olive (128, 128, 0)

Int

indigo

Indigo (75, 0, 130)

Int

with-alpha

Make a color transparent (alpha = 0-255)

Int -> Int -> Int

fade

Fade a color (factor 0.0-1.0)

Int -> Float -> Int

create

Create a new quadtree

Config fields: bounds: {x, y, width, height} - The region to cover max-objects: Int - Objects per node before split (default: 10) max-depth: Int - Maximum tree depth (default: 5)

Record -> Record

Quadtree.create {
  bounds: {x: 0.0, y: 0.0, width: 800.0, height: 600.0},
  max-objects: 10,
  max-depth: 5
}

insert

Insert an object into the quadtree Object must have: x, y, width, height fields (or provide bounds)

Record -> Record -> Record

insert-all

Insert multiple objects

Record -> List -> Record

query

Query for all objects that could collide with a given bounds

Record -> Record -> List

query-point

Query for objects at a specific point

Record -> Float -> Float -> List

query-radius

Query for objects within a radius of a point

Record -> Float -> Float -> Float -> List

clear

Clear all objects from the tree

Record -> Record

rebuild

Rebuild the tree with new objects (useful after many removals)

Record -> List -> Record

get-all

Get all objects in the tree

Record -> List

count

Count all objects in the tree

Record -> Int

find-collision-pairs

Find all pairs of potentially colliding objects

Record -> List

get-all-bounds

Get all node bounds for debug drawing

Record -> List

stats

Get tree statistics

Record -> Record

create-emitter

Create a particle emitter

Config fields: max-particles: Int - Maximum particles (default: 100) emission-rate: Float - Particles per second (default: 10.0) lifetime: {min: Float, max: Float} - Particle lifetime range speed: {min: Float, max: Float} - Initial speed range angle: {min: Float, max: Float} - Emission angle range in degrees (0 = right) size: {start: Float, end: Float} - Size over lifetime colors: List Int - Colors to cycle through gravity: {x: Float, y: Float} - Gravity force (default: {x: 0, y: 0}) rotation-speed: {min: Float, max: Float} - Rotation speed range (optional)

Record -> Record

Particles.create-emitter {
  max-particles: 200,
  emission-rate: 50.0,
  lifetime: {min: 0.5, max: 1.5},
  speed: {min: 50.0, max: 150.0},
  angle: {min: 0.0, max: 360.0},
  size: {start: 8.0, end: 2.0},
  colors: [Colors.yellow, Colors.orange, Colors.red]
}

create-emitter-at

Create emitter at a specific position

Float -> Float -> Record -> Record

set-position

Set emitter position

Record -> Float -> Float -> Record

move

Move emitter by delta

Record -> Float -> Float -> Record

start

Start emitting

Record -> Record

stop

Stop emitting (existing particles continue)

Record -> Record

clear

Clear all particles

Record -> Record

has-particles?

Check if emitter has active particles

Record -> Bool

particle-count

Get particle count

Record -> Int

burst

Emit multiple particles at once

Record -> Int -> Record

update

Update emitter and all particles

Record -> Float -> Record

draw

Draw all particles as circles

Record -> ()

draw-rects

Draw particles as rectangles

Record -> ()

draw-faded

Draw particles with fade based on lifetime

Record -> ()

draw-textured

Draw particles with texture

Record -> Record -> ()

preset-fire

Create a fire effect emitter

Float -> Float -> Record

preset-smoke

Create a smoke effect emitter

Float -> Float -> Record

preset-sparks

Create a spark/explosion burst emitter

Float -> Float -> Record

preset-rain

Create a rain effect emitter

Int -> Record

preset-snow

Create a snow effect emitter

Int -> Record

create

Create an empty tilemap

Config fields: tile-width: Int - Width of each tile in pixels tile-height: Int - Height of each tile in pixels width: Int - Map width in tiles height: Int - Map height in tiles tileset: Texture - The tileset texture

Record -> Record

Tilemap.create {
  tile-width: 16,
  tile-height: 16,
  width: 50,
  height: 30,
  tileset: tileset-texture
}

add-layer

Add a layer to the tilemap

Record -> Record -> Record

create-layer

Create a layer with empty data

String -> Int -> Int -> Bool -> Record

create-layer-with-data

Create a layer with initial data

String -> List Int -> Bool -> Record

get-tile

Get tile index at position (in tile coordinates)

Record -> String -> Int -> Int -> Int

set-tile

Set tile at position (returns new tilemap)

Record -> String -> Int -> Int -> Int -> Record

get-tile-at

Get tile at world position (in pixels)

Record -> String -> Float -> Float -> Int

world-to-tile

Convert world position to tile position

Record -> Float -> Float -> Record

tile-to-world

Convert tile position to world position (top-left corner)

Record -> Int -> Int -> Record

get-layer

Get layer by name

Record -> String -> Option Record

set-layer-visible

Set layer visibility

Record -> String -> Bool -> Record

toggle-layer

Toggle layer visibility

Record -> String -> Record

draw

Draw all visible layers

Record -> Int -> ()

draw-layer

Draw a specific layer

Record -> Record -> Int -> ()

draw-in-bounds

Draw tilemap within camera bounds (optimized)

Record -> Float -> Float -> Float -> Float -> Int -> ()

is-solid?

Check if a tile position is solid

Record -> Int -> Int -> Bool

is-solid-at?

Check if a world position is solid

Record -> Float -> Float -> Bool

rect-collides?

Check if a rectangle collides with any solid tiles Returns true if any corner or edge touches a solid tile

Record -> Float -> Float -> Float -> Float -> Bool

get-colliding-tiles

Get all solid tiles that a rectangle overlaps with

Record -> Float -> Float -> Float -> Float -> List Record

resolve-collision

Resolve collision by pushing entity out of solid tiles Returns adjusted position {x, y}

Record -> Float -> Float -> Float -> Float -> Float -> Float -> Record

pixel-width

Get tilemap dimensions in pixels

Record -> Int

pixel-height

Record -> Int

fill-rect

Fill a rectangular region with a tile

Record -> String -> Int -> Int -> Int -> Int -> Int -> Record

clear-layer

Clear all tiles in a layer

Record -> String -> Record

TilemapError

Error type for tilemap loading

Variants

TilemapParseError {String}
TilemapMissingField {String}
TilemapInvalidFormat {String}

load

Load a tilemap from a Tiled JSON file (.tmj or .json)

Parameters:

  • path - String - Path to the JSON file
  • tileset - Texture - The tileset texture to use (loaded separately)

Returns: Result Tilemap TilemapError

String -> Record -> Result Record TilemapError

  tileset = Assets.load-texture "tiles.png"
  match Tilemap.load "level1.tmj" tileset
    | Ok map -> use map
    | Err e -> print "Failed to load: ${show e}"

Note: This loads the map structure from JSON. The tileset texture
must be loaded separately using Assets.load-texture.

from-tiled-json

Parse a Tiled JSON string into a tilemap

Parameters:

  • json-str - String - JSON content from a Tiled map file
  • tileset - Texture - The tileset texture

Returns: Result Tilemap TilemapError

String -> Record -> Result Record TilemapError

get-tileset-info

Get tileset info from Tiled JSON (helper for loading tileset)

Parameters:

  • path - String - Path to the Tiled JSON file

Returns: Result {image: String, tile-width: Int, tile-height: Int} TilemapError

String -> Result Record TilemapError

match Tilemap.get-tileset-info "level1.tmj"
  | Ok info ->
    tileset = Assets.load-texture info.image
    Tilemap.load "level1.tmj" tileset
  | Err e -> print "Error: ${show e}"

rect

A rectangle for collision detection Fields: x, y, width, height (all Float)

Create a rectangle

Float -> Float -> Float -> Float -> Record

rect-from

Create a rectangle from position and size records

Record -> Record -> Record

rect-centered

Create a rectangle centered at a point

Float -> Float -> Float -> Float -> Record

point-in-rect?

Check if a point is inside a rectangle

Float -> Float -> Record -> Bool

point-in-circle?

Check if a point is inside a circle

Float -> Float -> Float -> Float -> Float -> Bool

rects-overlap?

Check if two rectangles overlap (AABB collision)

Record -> Record -> Bool

rect-overlap

Get the overlap between two rectangles (returns None if no overlap)

Record -> Record -> Option

check-rects

Get collision info between two rectangles Returns Option with {overlap: {x, y}, normal: {x, y}, penetration: Float}

Record -> Record -> Option

rect-intersection

Get the intersection rectangle of two overlapping rectangles

Record -> Record -> Option

circles-overlap?

Check if two circles overlap

Float -> Float -> Float -> Float -> Float -> Float -> Bool

check-circles

Get collision info between two circles Returns Option with {normal: {x, y}, penetration: Float}

Float -> Float -> Float -> Float -> Float -> Float -> Option

circle-rect-overlap?

Check if a circle and rectangle overlap

Float -> Float -> Float -> Record -> Bool

check-circle-rect

Get collision info between circle and rectangle Returns Option with {closest: {x, y}, normal: {x, y}, penetration: Float}

Float -> Float -> Float -> Record -> Option

lines-intersect?

Check if two line segments intersect

Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Bool

line-intersection

Get intersection point of two line segments

Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Option

line-rect-intersect?

Check if a line segment intersects a rectangle

Float -> Float -> Float -> Float -> Record -> Bool

expand-rect

Expand a rectangle by a margin

Record -> Float -> Record

shrink-rect

Shrink a rectangle by a margin

Record -> Float -> Record

rect-center

Get the center point of a rectangle

Record -> Record

distance

Get the distance between two points

Float -> Float -> Float -> Float -> Float

distance-squared

Get the squared distance between two points (faster than distance)

Float -> Float -> Float -> Float -> Float

rect-contains-rect?

Check if a rectangle contains another rectangle

Record -> Record -> Bool

rect-contains-circle?

Check if a rectangle contains a circle

Record -> Float -> Float -> Float -> Bool

layer-default

Collision layers use bitmasks for efficient filtering Each layer is a power of 2: 1, 2, 4, 8, 16, 32, etc.

Default collision layer (1)

Int

layer-player

Player collision layer (2)

Int

layer-enemy

Enemy collision layer (4)

Int

layer-bullet

Bullet/projectile collision layer (8)

Int

layer-wall

Wall/obstacle collision layer (16)

Int

layer-pickup

Pickup/collectible collision layer (32)

Int

layer-trigger

Trigger zone collision layer (64)

Int

combine-layers

Combine multiple layers into a mask

List -> Int

layers-collide?

Check if two layer masks can collide Returns true if they share any bits

Int -> Int -> Bool

create-filter

Create a collision filter entity-layer: the layer this entity belongs to collides-with: mask of layers this entity collides with

Int -> Int -> Record

filters-collide?

Check if two filters allow collision

Record -> Record -> Bool

filter-player

Player collision filter - collides with enemies, walls, pickups, triggers

Record

filter-enemy

Enemy collision filter - collides with player, bullets, walls

Record

filter-bullet

Bullet collision filter - collides with enemies, walls

Record

filter-wall

Wall collision filter - collides with player, enemies, bullets

Record

filter-pickup

Pickup collision filter - collides with player only

Record

filter-trigger

Trigger collision filter - collides with player only

Record

separate-circles

Separate two overlapping circles Returns new positions for both circles

Float -> Float -> Float -> Float -> Float -> Float -> Record

push-out-of-rect

Push an entity out of a static rectangle Returns the adjusted position

Float -> Float -> Float -> Float -> Record -> Record

reflect-velocity

Reflect a velocity vector off a surface normal: {x, y} - the surface normal (should be normalized) vx, vy: velocity components Returns new velocity

Float -> Float -> Record -> Record

reflect-velocity-damped

Reflect with dampening (for bouncing) bounce: 0.0 = no bounce, 1.0 = perfect bounce

Float -> Float -> Record -> Float -> Record

Input

Input handling module - keyboard, mouse, gamepad

Module

Graphics

Graphics primitives module - drawing shapes, text

Module

Colors

Color constants and utilities module

Module

Audio

Audio module - sound effects and music

Module

Math

Math utilities module - vectors, angles, interpolation

Module

Sprite

Sprite and animation module

Module

Camera

2D camera module with smooth follow and effects

Module

Collision

Collision detection module - AABB, circles, lines

Module

Assets

Asset loading module - textures, sounds, fonts

Module

Scene

Scene management module

Module

Tilemap

Tilemap rendering module

Module

Particles

Particle effects module

Module

Quadtree

Spatial partitioning quadtree module

Module

run

Run the game with a configuration record

Record -> ()

delta-time

Get the current frame time (delta time)

() -> Float

fps

Get the current frames per second

() -> Int

time

Get the time since the game started

() -> Float

should-close?

Check if the window should close

() -> Bool

set-title

Set the window title

String -> ()

toggle-fullscreen

Toggle fullscreen mode

() -> ()

is-fullscreen?

Check if the window is fullscreen

() -> Bool

is-focused?

Check if the window is focused

() -> Bool

is-minimized?

Check if the window is minimized

() -> Bool

minimize

Minimize the window

() -> ()

maximize

Maximize the window

() -> ()

restore

Restore the window from minimized/maximized state

() -> ()

run

Run the game with a configuration record.

Config fields: title: String - Window title (default: "Kit Game") width: Int - Window width (default: 800) height: Int - Window height (default: 600) fps: Int - Target frames per second (default: 60) init: fn() => state - Initialize game state update: fn(state, dt) => state - Update game state draw: fn(state) => () - Draw the game

Optional fields: resizable: Bool - Allow window resizing (default: false) vsync: Bool - Enable vertical sync (default: true) fullscreen: Bool - Start in fullscreen (default: false) msaa: Bool - Enable anti-aliasing (default: false) debug: Bool - Enable debug mode (default: false)

Record -> ()

  Game.run {
    title: "My Game",
    width: 800,
    height: 600,
    init: fn => {x: 0.0, y: 0.0},
    update: fn(state, dt) => {...state, x: state.x + dt},
    draw: fn(state) => Graphics.circle state.x state.y 20.0 Colors.red
  }
Run a game with a configuration record.

The update function receives (state, dt) and must return new state.
The draw function receives state and draws to the screen.

delta-time

Get the current frame time (delta time)

() -> Float

fps

Get the current FPS

() -> Int

time

Get the time since the game started

() -> Float

should-close?

Check if the window should close (user pressed close button or escape)

() -> Bool

set-title

Set the window title

String -> ()

toggle-fullscreen

Toggle fullscreen mode

() -> ()

is-fullscreen?

Check if the window is fullscreen

() -> Bool

is-focused?

Check if the window is focused

() -> Bool

is-minimized?

Check if the window is minimized

() -> Bool

minimize

Minimize the window

() -> ()

maximize

Maximize the window

() -> ()

restore

Restore the window from minimized/maximized state

() -> ()

clear

Clear the screen with a color

Int -> ()

width

Get the screen width

() -> Int

height

Get the screen height

() -> Int

circle

Draw a filled circle

Float -> Float -> Float -> Int -> ()

circle-outline

Draw a circle outline

Float -> Float -> Float -> Int -> ()

rect

Draw a filled rectangle

Float -> Float -> Float -> Float -> Int -> ()

rect-outline

Draw a rectangle outline

Float -> Float -> Float -> Float -> Int -> ()

rect-rounded

Draw a rounded rectangle

Float -> Float -> Float -> Float -> Float -> Int -> ()

line

Draw a line

Float -> Float -> Float -> Float -> Int -> ()

line-thick

Draw a line with thickness

Float -> Float -> Float -> Float -> Float -> Int -> ()

point

Draw a point (1x1 pixel)

Float -> Float -> Int -> ()

triangle

Draw a triangle

Float -> Float -> Float -> Float -> Float -> Float -> Int -> ()

polygon

Draw a polygon

Float -> Float -> Int -> Float -> Float -> Int -> ()

ellipse

Draw an ellipse

Float -> Float -> Float -> Float -> Int -> ()

ellipse-outline

Draw an ellipse outline

Float -> Float -> Float -> Float -> Int -> ()

text

Draw text at a position

String -> Float -> Float -> Int -> ()

text-size

Draw text with a specific font size

String -> Float -> Float -> Int -> Int -> ()

measure-text

Measure text width for default font

String -> Int -> Int

rect-rotated

Draw a rectangle with rotation and origin

Float -> Float -> Float -> Float -> Float -> Float -> Float -> Int -> ()

ring

Draw a ring (donut shape)

Float -> Float -> Float -> Float -> Float -> Float -> Int -> ()

sector

Draw a pie/sector of a circle

Float -> Float -> Float -> Float -> Float -> Int -> ()

pi

Pi (3.14159...)

Float

tau

Tau (2 * Pi, full circle in radians)

Float

clamp

Clamp a value between min and max

Float -> Float -> Float -> Float

lerp

Linear interpolation between two values

Float -> Float -> Float -> Float

inverse-lerp

Inverse lerp: get t from a value between a and b

Float -> Float -> Float -> Float

remap

Remap a value from one range to another

Float -> Float -> Float -> Float -> Float -> Float

sign

Get the sign of a number (-1, 0, or 1)

Float -> Float

move-toward

Move a value toward a target by a maximum delta

Float -> Float -> Float -> Float

deg-to-rad

Convert degrees to radians

Float -> Float

rad-to-deg

Convert radians to degrees

Float -> Float

vec2

Create a 2D vector

Float -> Float -> Record

vec2-zero

Zero vector (0, 0)

Record

vec2-up

Unit vector pointing up (0, -1)

Record

vec2-down

Unit vector pointing down (0, 1)

Record

vec2-left

Unit vector pointing left (-1, 0)

Record

vec2-right

Unit vector pointing right (1, 0)

Record

vec2-add

Add two vectors

Record -> Record -> Record

vec2-sub

Subtract two vectors

Record -> Record -> Record

vec2-scale

Multiply a vector by a scalar

Record -> Float -> Record

vec2-div

Divide a vector by a scalar

Record -> Float -> Record

vec2-negate

Negate a vector

Record -> Record

vec2-length

Get the length of a vector

Record -> Float

vec2-length-squared

Get the squared length of a vector (faster than length)

Record -> Float

vec2-normalize

Normalize a vector to unit length

Record -> Record

vec2-dot

Dot product of two vectors

Record -> Record -> Float

vec2-cross

Cross product (returns scalar z-component)

Record -> Record -> Float

vec2-distance

Distance between two points

Record -> Record -> Float

vec2-distance-squared

Squared distance between two points

Record -> Record -> Float

vec2-lerp

Linear interpolation between two vectors

Record -> Record -> Float -> Record

vec2-rotate

Rotate a vector by an angle (in radians)

Record -> Float -> Record

vec2-angle

Get the angle of a vector (from positive x-axis)

Record -> Float

vec2-perpendicular

Get a perpendicular vector (90 degrees counter-clockwise)

Record -> Record

vec2-reflect

Reflect a vector off a surface with the given normal

Record -> Record -> Record

vec2-clamp-length

Clamp a vector to a maximum length

Record -> Float -> Record

vec2-from-angle

Create a unit vector from an angle (in radians)

Float -> Record

ease-linear

Linear easing (no easing)

Float -> Float

ease-in-quad

Quadratic ease in

Float -> Float

ease-out-quad

Quadratic ease out

Float -> Float

ease-in-cubic

Cubic ease in

Float -> Float

ease-out-cubic

Cubic ease out

Float -> Float

create

Create a static sprite from a texture

Record -> Record

create-centered

Create a static sprite with centered origin

Record -> Record

draw

Draw a static sprite

Record -> Float -> Float -> ()

draw-tinted

Draw a static sprite with tint

Record -> Float -> Float -> Int -> ()

draw-ex

Draw a static sprite with rotation and scale

Record -> Float -> Float -> Float -> Float -> Int -> ()

draw-pro

Draw a static sprite with full control

Record -> Float -> Float -> Float -> Float -> Float -> Int -> ()

animated

Create an animated sprite from a sprite sheet

Config fields: texture: Texture - The sprite sheet texture frame-width: Int - Width of each frame in pixels frame-height: Int - Height of each frame in pixels animations: Record - Map of animation name to {frames: [Int], fps: Float} default-animation: String - Name of the animation to start with (optional)

Record -> Record

Sprite.animated {
  texture: sheet,
  frame-width: 32,
  frame-height: 32,
  animations: {
    idle: {frames: [0, 1], fps: 2.0},
    walk: {frames: [2, 3, 4, 5], fps: 8.0},
    jump: {frames: [6, 7], fps: 4.0}
  }
}

animated-centered

Create an animated sprite with centered origin

Record -> Record

set-animation

Set the current animation (resets frame to 0 if different)

Record -> String -> Record

update

Update an animated sprite (call each frame)

Record -> Float -> Record

update-with

Update with explicit animation data

Record -> Float -> List -> Float -> Record

play

Play the animation

Record -> Record

pause

Pause the animation

Record -> Record

reset

Reset the animation to frame 0

Record -> Record

set-flip-x

Set horizontal flip

Record -> Bool -> Record

set-flip-y

Set vertical flip

Record -> Bool -> Record

draw-animated

Draw an animated sprite at position

Record -> Float -> Float -> Int -> Int -> ()

draw-current

Draw an animated sprite using its current frame

Record -> Float -> Float -> Int -> ()

draw-animated-ex

Draw an animated sprite with rotation and scale

Record -> Float -> Float -> Int -> Float -> Float -> Int -> ()

frame-count

Get frame count in a sprite sheet

Record -> Int -> Int -> Int

frame-position

Get frame position (x, y in pixels) for a frame index

Record -> Int -> Int -> Int -> Record

row-frames

Create a list of frame indices for a row

Record -> Int -> Int -> Int -> List

col-frames

Create a list of frame indices for a column

Record -> Int -> Int -> Int -> Int -> List

set-origin

Set the origin point (pivot) of a sprite

Record -> Float -> Float -> Record

center-origin

Set origin to center of sprite

Record -> Record

bottom-center-origin

Set origin to bottom-center (useful for characters)

Record -> Record

init

Initialize the audio device (called automatically by Game.run)

() -> ()

close

Close the audio device

() -> ()

ready?

Check if the audio device is ready

() -> Bool

set-master-volume

Set the master volume (0.0 to 1.0)

Float -> ()

get-master-volume

Get the master volume

() -> Float

load-sound

Load a sound from a file

String -> Ptr

unload-sound

Unload a sound from memory

Ptr -> ()

play

Play a sound

Ptr -> ()

stop-sound

Stop a sound

Ptr -> ()

pause-sound

Pause a sound

Ptr -> ()

resume-sound

Resume a paused sound

Ptr -> ()

sound-playing?

Check if a sound is playing

Ptr -> Bool

set-sound-volume

Set the volume for a sound (0.0 to 1.0)

Ptr -> Float -> ()

set-sound-pitch

Set the pitch for a sound (1.0 is normal)

Ptr -> Float -> ()

set-sound-pan

Set the pan for a sound (0.0 left, 0.5 center, 1.0 right)

Ptr -> Float -> ()

play-at-volume

Play a sound at a specific volume

Ptr -> Float -> ()

load-music

Load music from a file (streaming)

String -> Ptr

unload-music

Unload music from memory

Ptr -> ()

play-music

Play music (must call update-music each frame)

Ptr -> ()

stop-music

Stop music

Ptr -> ()

pause-music

Pause music

Ptr -> ()

resume-music

Resume paused music

Ptr -> ()

update-music

Update music stream buffer (call each frame)

Ptr -> ()

music-playing?

Check if music is playing

Ptr -> Bool

set-music-volume

Set music volume (0.0 to 1.0)

Ptr -> Float -> ()

set-music-pitch

Set music pitch (1.0 is normal)

Ptr -> Float -> ()

set-music-pan

Set music pan (0.0 left, 0.5 center, 1.0 right)

Ptr -> Float -> ()

music-length

Get the total length of music in seconds

Ptr -> Float

music-position

Get the current playback position in seconds

Ptr -> Float

seek-music

Seek to a specific position in music (in seconds)

Ptr -> Float -> ()

set-music-looping

Set whether music should loop

Ptr -> Bool -> ()

key-down?

Check if a key is currently held down

String -> Bool

key-pressed?

Check if a key was just pressed this frame

String -> Bool

key-released?

Check if a key was just released this frame

String -> Bool

key-up?

Check if a key is not being pressed

String -> Bool

get-key-pressed

Get the last key pressed (returns key code)

() -> Int

get-char-pressed

Get the last char pressed (for text input)

() -> Int

mouse-position

Get the current mouse position as a record {x, y}

() -> Record

mouse-x

Get the mouse X position

() -> Int

mouse-y

Get the mouse Y position

() -> Int

mouse-down?

Check if a mouse button is held down

String -> Bool

mouse-pressed?

Check if a mouse button was just pressed

String -> Bool

mouse-released?

Check if a mouse button was just released

String -> Bool

mouse-wheel

Get the mouse wheel movement (positive = up)

() -> Float

mouse-delta

Get mouse delta (movement since last frame)

() -> Record

hide-cursor

Hide the mouse cursor

() -> ()

show-cursor

Show the mouse cursor

() -> ()

cursor-hidden?

Check if the cursor is hidden

() -> Bool

gamepad-connected?

Check if a gamepad is connected

Int -> Bool

gamepad-name

Get the name of a gamepad

Int -> String

gamepad-button-down?

Check if a gamepad button is held down

Int -> String -> Bool

gamepad-button-pressed?

Check if a gamepad button was just pressed

Int -> String -> Bool

gamepad-button-released?

Check if a gamepad button was just released

Int -> String -> Bool

gamepad-axis

Get a gamepad axis value (-1.0 to 1.0)

Int -> String -> Float

gamepad-left-stick

Get the left stick as a record {x, y}

Int -> Record

gamepad-right-stick

Get the right stick as a record {x, y}

Int -> Record

load-texture

Load a texture from a file

Returns:

String -> Record

unload-texture

Unload a texture from memory

Record -> ()

is-texture-valid?

Check if texture is valid (loaded successfully)

Record -> Bool

load-sound

Load a sound from a file

Supported formats: WAV, OGG, MP3

String -> Ptr

unload-sound

Unload a sound from memory

Ptr -> ()

load-music

Load streaming music from a file

Supported formats: OGG, MP3, WAV, FLAC

String -> Ptr

unload-music

Unload music from memory

Ptr -> ()

load-font

Load a font from a file

Supported formats: TTF, OTF, FNT

String -> Ptr

load-font-size

Load a font with specific size

String -> Int -> Ptr

unload-font

Unload a font from memory

Ptr -> ()

default-font

Get the default font

() -> Ptr

load-image

Load an image from a file (CPU memory)

Use this when you need to process an image before creating a texture

String -> Ptr

unload-image

Unload an image from CPU memory

Ptr -> ()

texture-from-image

Create a texture from an image

Ptr -> Record

join-path

Join path components

String -> String -> String

=> "assets/sprites/player.png"

join-paths

Join multiple path components

List -> String

try-load-texture

Load texture with result handling

String -> Result

try-load-sound

Load sound with result handling

String -> Result

try-load-music

Load music with result handling

String -> Result

load-textures

Load multiple textures from a list of paths Returns a list of textures in the same order

List -> List

unload-textures

Unload multiple textures

List -> ()

load-sounds

Load multiple sounds from a list of paths

List -> List

unload-sounds

Unload multiple sounds

List -> ()

create

Create a new scene manager with an initial scene

Record -> Record

empty

Create an empty scene manager

() -> Record

active

Get the active (top) scene

Record -> Option

active-state

Get the active scene's state

Record -> Option

push

Push a new scene onto the stack (pauses current scene)

Record -> Record -> Record

pop

Pop the current scene from the stack (returns to previous)

Record -> Record

replace

Replace the current scene with a new one

Record -> Record -> Record

switch-to

Switch to a completely new scene (clears stack)

Record -> Record -> Record

update

Update the scene manager (updates active scene)

Record -> Float -> Record

update-with-transition

Update with transition handling

Record -> Float -> Record

draw

Draw the active scene

Record -> ()

draw-all

Draw all scenes in stack (for overlay effects)

Record -> ()

transition-to

Transition types fade-in: Fade from black fade-out: Fade to black fade: Fade out then fade in none: Instant switch

Start a fade transition to a new scene

Record -> Record -> Float -> Record

transition-push

Start a push transition

Record -> Record -> Float -> Record

transition-progress

Get the current transition progress (0.0 to 1.0)

Record -> Float

is-transitioning?

Check if currently transitioning

Record -> Bool

update-transition

Update transition state

Record -> Float -> Record

fade-alpha

Get fade alpha for current transition (0.0-1.0, where 1.0 is fully opaque)

Record -> Float

update-state

Update the state of the active scene directly

Record -> (a -> a) -> Record

scene-count

Get scene count in stack

Record -> Int

has-scene?

Check if a scene with given name is in the stack

Record -> String -> Bool

create

Create a 2D camera

Config fields: target: {x: Float, y: Float} - Point the camera is looking at zoom: Float - Camera zoom (1.0 = normal, default) rotation: Float - Camera rotation in degrees (default: 0.0)

Record -> Record

Camera.create {target: {x: 400.0, y: 300.0}, zoom: 1.0}

create-centered

Create a camera centered on the screen

Int -> Int -> Float -> Float -> Record

create-for-screen

Create a camera with screen dimensions (auto-centered)

Int -> Int -> Record

begin

Begin drawing with this camera

Record -> ()

end

End camera drawing mode

() -> ()

set-target

Set the camera target directly

Record -> Float -> Float -> Record

move

Move the camera target by a delta

Record -> Float -> Float -> Record

follow

Smoothly follow a target position

smoothness: 0.0 = instant, 1.0 = no movement (typically use 0.05-0.2)

Record -> Float -> Float -> Float -> Record

follow-with-deadzone

Follow with deadzone (camera doesn't move if target is within deadzone)

Record -> Float -> Float -> Float -> Float -> Float -> Record

clamp-to-bounds

Constrain camera within bounds

Record -> Float -> Float -> Float -> Float -> Record

set-zoom

Set the camera zoom level

Record -> Float -> Record

zoom-by

Adjust zoom by a factor

Record -> Float -> Record

zoom-to

Smoothly zoom to a target level

Record -> Float -> Float -> Record

clamp-zoom

Clamp zoom to min/max range

Record -> Float -> Float -> Record

set-rotation

Set the camera rotation (in degrees)

Record -> Float -> Record

rotate-by

Rotate the camera by an angle

Record -> Float -> Record

rotate-to

Smoothly rotate to a target angle

Record -> Float -> Float -> Record

shake

Start camera shake effect

intensity: Maximum shake offset in pixels duration: How long the shake lasts in seconds

Record -> Float -> Float -> Record

update-shake

Update camera shake (call each frame)

Record -> Float -> Record

is-shaking?

Check if camera is currently shaking

Record -> Bool

screen-to-world

Convert screen coordinates to world coordinates

Record -> Float -> Float -> Record

world-to-screen

Convert world coordinates to screen coordinates

Record -> Float -> Float -> Record

update

Update camera (handles shake, call each frame)

Record -> Float -> Record