game
| Kind | kit |
|---|---|
| Capabilities | ffi |
| Categories | graphics gamedev |
| Keywords | game gamedev graphics 2d raylib |
A LÖVE-inspired game development framework for Kit
Files
| File | Description |
|---|---|
.editorconfig | Editor formatting configuration |
.gitignore | Git ignore rules for build artifacts and dependencies |
.tool-versions | asdf tool versions (Zig, Kit) |
LICENSE | MIT license file |
README.md | This file |
examples/breakout.kit | Example: breakout with ball physics, bricks, scoring |
examples/camera.kit | Example: camera |
examples/collision.kit | Example: collision |
examples/hybrid-test.kit | Example: hybrid test |
examples/minimal-test.kit | Example: minimal test |
examples/particles.kit | Example: particles |
examples/platformer.kit | Example: platformer with tilemap, physics, camera, debug overlay |
examples/pong.kit | Example: pong |
examples/simple.kit | Example: simple |
examples/tilemap.kit | Example: tilemap |
examples/topdown.kit | Example: top-down coin collector with tilemap, camera, save/load |
kit.toml | Package manifest with metadata and dependencies |
src/assets.kit | Module for assets |
src/audio.kit | Module for audio |
src/backend/interface.kit | Opaque texture handle with dimensions |
src/backend/raylib.kit | Module for raylib |
src/backend/select.kit | Module for select |
src/cache.kit | Asset cache for textures, sounds, fonts |
src/camera.kit | Module for camera |
src/collision.kit | A rectangle for collision detection |
src/colors.kit | Module for colors |
src/debug.kit | Debug overlay and development tools |
src/ecs.kit | Entity Component System |
src/game.kit | Main module |
src/graphics.kit | Module for graphics |
src/input.kit | Module for input |
src/math.kit | Pi (3.14159...) |
src/package.kit | Kit Game - A LOVE-inspired game development framework |
src/particles.kit | Module for particles |
src/quadtree.kit | A quadtree node containing: |
src/save.kit | JSON-based save/load game state |
src/scene.kit | A scene manager holds the current scene stack and transition state |
src/sprite.kit | Module for sprite |
src/template.kit | Project template generator |
src/tilemap.kit | Module for tilemap |
tests/cache.test.kit | Tests for cache module |
tests/collision.test.kit | Tests for collision module |
tests/debug.test.kit | Tests for debug module |
tests/ecs.test.kit | Tests for ECS module |
tests/game.test.kit | Tests for game |
tests/minimal-import.test.kit | Tests for minimal import |
tests/module-structure.test.kit | Tests for module-structure |
tests/save.test.kit | Tests for save module |
tests/template.test.kit | Tests for template module |
Architecture
Game Loop
Module Structure
Dependencies
geometryraylib
Installation
kit add gitlab.com/kit-lang/packages/kit-game.gitUsage
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
| Field | Type | Default | Description |
|---|---|---|---|
title | String | "Kit Game" | Window title |
width | Int | 800 | Window width |
height | Int | 600 | Window height |
fps | Int | 60 | Target frames per second |
init | fn() => State | required | Initialize game state |
update | fn(State, Float) => State | required | Update state (receives delta time) |
draw | fn(State) => () | required | Render the game |
resizable | Bool | false | Allow window resizing |
vsync | Bool | true | Enable vertical sync |
fullscreen | Bool | false | Start in fullscreen |
Available Modules
Game.Graphics- Shape drawing, text renderingGame.Input- Keyboard, mouse, gamepadGame.Audio- Sound effects, musicGame.Assets- Load textures, sounds, fontsGame.Sprite- Static and animated spritesGame.Tilemap- Tile-based maps, Tiled JSON and TMX XMLGame.Camera- 2D camera with follow/shakeGame.Collision- AABB, circle, line detection, swept AABB (prevents tunneling)Game.Particles- Particle emitters and effectsGame.ECS- Lightweight Entity Component SystemGame.Scene- Scene stack managementGame.Save- JSON-based save/load game stateGame.Debug- Debug overlay, FPS counter, watch variables, pause/step, profilingGame.Math- Vectors, lerp, easingGame.Colors- Color constantsGame.Cache- Asset cache, preload and reuse textures/soundsGame.Template- Project template generator
Debug Tools
The Game.Debug module provides development aids:
# In your init:
init = fn => {
player: {x: 100.0, y: 100.0},
debug: Game.Debug.create {enabled: false}
}
# In your update:
update = fn(state, dt) =>
# Toggle pause with P key
debug = if Game.Input.key-pressed? "p" then
Game.Debug.toggle-pause state.debug
else
state.debug
# Step one frame with N while paused
debug2 = if Game.Input.key-pressed? "n" and Game.Debug.is-paused? debug then
Game.Debug.step debug
else
debug
# Only run game logic when not paused (or stepping)
new-player = if Game.Debug.should-advance? debug2 then
update-player state.player dt
else
state.player
# Consume the step request after advancing
debug3 = Game.Debug.consume-step debug2
# Track frame time and clear watches
debug4 = Game.Debug.update debug3 dt
{...state, player: new-player, debug: debug4}
# In your draw:
draw = fn(state) =>
# ... draw game ...
# Profile a section
debug = Game.Debug.profile-start state.debug "draw-world"
# ... heavy drawing ...
debug2 = Game.Debug.profile-end debug "draw-world"
# Show watches on overlay
debug3 = Game.Debug.watch debug2 "Player X" (Float.to-string state.player.x)
# Draw overlay (shows FPS, frame time, pause status, profiles)
Game.Debug.draw debug3Asset Cache
The Game.Cache module prevents repeated disk loads:
init = fn => {
cache: Game.Cache.create,
player: {x: 100.0, y: 100.0}
}
# Load once, reuse everywhere
result = Game.Cache.get-texture state.cache "sprites/player.png"
texture = result.asset
cache2 = result.cache
# Preload a batch at level start
cache3 = Game.Cache.preload-textures cache2 ["bg.png", "enemy.png"]Project Templates
Generate starter project files with Game.Template:
# Print starter main.kit content
print (Game.Template.main-file "My Game")
# Print kit.toml content
print (Game.Template.kit-toml "my-game" "0.1.0")
# Get all files at once
scaffold = Game.Template.scaffold "my-game" "My Game"
# scaffold.main, scaffold.kit-toml, scaffold.readme, scaffold.gitignoreTilemap Loading
The Game.Tilemap module supports both Tiled JSON (.tmj) and Tiled TMX XML (.tmx) formats.
See Game.Tilemap docs.
Tiled JSON (.tmj / .json)
# Load a tileset texture separately
tileset = Game.Assets.load-texture "tiles.png"
# Load the map from JSON
match Game.Tilemap.load "level1.tmj" tileset
| Ok map ->
# Use map.tile-width, map.tile-height, map.layers, etc.
no-op
| Err e -> print "Failed: ${show e}"Tiled TMX XML (.tmx)
Requires the kit-xml package (added automatically as a dependency).
See kit-xml docs.
# Load a tileset texture separately
tileset = Game.Assets.load-texture "tiles.png"
# Load the map from TMX XML
match Game.Tilemap.load-tmx "level1.tmx" tileset
| Ok map ->
# Same map structure as JSON loading
no-op
| Err e -> print "Failed: ${show e}"TMX notes:
- CSV, uncompressed Base64, zlib-compressed Base64, and gzip-compressed Base64 tile data are all supported.
- External tilesets (
.tsxfiles referenced viasource="tileset.tsx") are loaded automatically. - Layer
visibleandsolidcustom properties are supported. - Object layers are parsed via
Game.Tilemap.parse-tmx-objectgroups xml-str. - TMX parsing uses libxml2 FFI and only works in compiled builds. The
kitinterpreter has a runtime conflict between the Raylib and libxml2 FFI modules, soload-tmx/from-tmx-xmlwill panic in interpreted tests. Usekit checkand compiled examples to verify TMX functionality. - In Tiled, go to
File → Export As... → Tiled Map Files (*.tmx)to save as TMX.
Release Builds
Build a native binary for distribution:
# Development build (fast, larger binary)
kit build main.kit -o my-game
# Release build (slower compile, optimized binary)
kit build main.kit -o my-game --releaseLicense
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
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 -> PositiveFloat -> List
clear
Clear all objects from the tree
Record -> Record
rebuild
Rebuild the tree with new objects (useful after many removals)
Quadtree -> List -> Quadtree
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
NonEmptyString -> Int -> Int -> Bool -> Record
create-layer-with-data
Create a layer with initial data
NonEmptyString -> List Int -> Bool -> Record
get-tile
Get tile index at position (in tile coordinates)
Record -> NonEmptyString -> Int -> Int -> Int
set-tile
Set tile at position (returns new tilemap)
Record -> NonEmptyString -> Int -> Int -> Int -> Record
get-tile-at
Get tile at world position (in pixels)
Record -> NonEmptyString -> 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 -> NonEmptyString -> Option Record
set-layer-visible
Set layer visibility
Record -> NonEmptyString -> Bool -> Record
toggle-layer
Toggle layer visibility
Record -> NonEmptyString -> 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 -> NonEmptyString -> 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 filetileset- Texture - The tileset texture to use (loaded separately)
Returns: Result Tilemap TilemapError
NonEmptyString -> 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 filetileset- 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
NonEmptyString -> 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}"load-tmx
Load a tilemap from a Tiled TMX XML file (.tmx)
Parameters:
path- String - Path to the TMX filetileset- Texture - The tileset texture to use (loaded separately)
Returns: Result Tilemap TilemapError
Note: Only CSV-encoded tile data is currently supported. Base64, zlib, gzip, and other encodings are not yet supported.
NonEmptyString -> Record -> Result Record TilemapError
tileset = Assets.load-texture "tiles.png"
match Tilemap.load-tmx "level1.tmx" tileset
| Ok map -> use map
| Err e -> print "Failed to load: ${show e}"from-tmx-xml
Parse a Tiled TMX XML string into a tilemap
Parameters:
xml-str- String - XML content from a Tiled TMX filetileset- Texture - The tileset texture
Returns: Result Tilemap TilemapError
Note: Only CSV-encoded tile data is currently supported.
String -> Record -> Result Record TilemapError
parse-tmx-objectgroups
Parse object group layers from a TMX XML document string.
Returns a list of {name: String, visible: Bool, objects: List} records. Each object has: id, x, y, width, height, kind, name.
Note: This is a separate utility function. Object groups are not yet integrated into the main tilemap structure.
String -> List Record
get-tileset-info-tmx
Get tileset info from a Tiled TMX file.
Parameters:
path- String - Path to the TMX file
Returns: Result {image: String, tile-width: Int, tile-height: Int, tile-count: Int} TilemapError
Note: For external tilesets, the .tsx file is loaded and parsed automatically.
NonEmptyString -> Result Record TilemapError
match Tilemap.get-tileset-info-tmx "level1.tmx"
| Ok info ->
tileset = Assets.load-texture info.image
Tilemap.load-tmx "level1.tmx" 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 -> PositiveFloat -> 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 -> PositiveFloat -> 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 -> PositiveFloat -> 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 -> PositiveFloat -> 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
sweep-rect
Swept AABB collision - find when a moving rectangle hits a static rectangle. Prevents tunneling where fast objects pass through thin walls between frames.
moving: {x, y, width, height} - rectangle at current position static-rect: {x, y, width, height} - static rectangle vx, vy: Float - velocity of moving rectangle for this frame
Returns Option with {time: Float (0-1), normal: {x, y}, contact: {x, y}}
Record -> Record -> Float -> Float -> Option
sweep-move
Move a rectangle with swept collision against a static rectangle. Returns the new position, collision time, hit flag, and normal.
Record -> Record -> Float -> Float -> Record
sweep-move-many
Move a rectangle with swept collision against multiple static rectangles. Tests all obstacles and returns the result of the nearest collision.
moving: {x, y, width, height} - rectangle at current position obstacles: List of {x, y, width, height} - static rectangles vx, vy: Float - velocity of moving rectangle for this frame
Returns {x, y, time, hit, normal}
Record -> List -> Float -> 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
Cache
Asset cache module - preload and reuse textures, sounds, fonts
Module
ECS
Entity Component System module
Module
Save
Save/load game state module
Module
Debug
Debug overlay and development tools module
Module
Template
Project template generator module
Module
Pool
Object pool module for recycling short-lived entities
Module
Physics
Basic rigid body physics module with gravity, forces, and collision resolution
Module
AutoSave
Auto-save timer module for periodic game state saves
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
() -> ()
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
NonEmptyString -> ()
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 -> PositiveFloat -> Int -> ()
circle-outline
Draw a circle outline
Float -> Float -> PositiveFloat -> 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 -> PositiveFloat -> 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 -> PositiveFloat -> Float -> Float -> Int -> ()
create
Create a new empty ECS world
() -> Record
create-with-capacity
Create a world with initial capacity hint (for documentation only, functional lists don't pre-allocate)
Int -> Record
add
Add an entity to the world. The entity should not have an id field; one will be assigned automatically. Returns {world: Record, id: Int}
Record -> Record -> Record
add-simple
Add an entity to the world (convenience, returns just world)
Record -> Record -> Record
add-many
Add multiple entities to the world Returns the new world and a list of assigned IDs
Record -> List -> Record
remove
Remove an entity by ID
Record -> Int -> Record
remove-where
Remove all entities matching a predicate
Record -> (Record -> Bool) -> Record
get
Get an entity by ID (returns Option)
Record -> Int -> Option
has?
Check if an entity with the given ID exists
Record -> Int -> Bool
query
Find all entities matching a predicate
Record -> (Record -> Bool) -> List
query-first
Find first entity matching a predicate (returns Option)
Record -> (Record -> Bool) -> Option
update
Update a single entity by ID Returns unchanged world if entity not found
Record -> Int -> (Record -> Record) -> Record
update-where
Update all entities matching a predicate
Record -> (Record -> Bool) -> (Record -> Record) -> Record
map-entities
Map a function over all entities
Record -> (Record -> Record) -> Record
count
Count all entities
Record -> Int
count-where
Count entities matching a predicate
Record -> (Record -> Bool) -> Int
sort-by
Sort entities by a key function (lowest first)
Record -> (Record -> Float) -> Record
create
Create an empty asset cache.
() -> Record
get-texture
Get a texture from the cache, loading it if not present. Returns {asset: Texture, cache: Record}
Record -> String -> Record
preload-textures
Preload multiple textures into the cache.
Record -> List -> Record
has-texture?
Check if a texture is already cached.
Record -> String -> Bool
unload-texture
Remove a texture from the cache and unload it.
Record -> String -> Record
get-sound
Get a sound from the cache, loading it if not present. Returns {asset: Ptr, cache: Record}
Record -> String -> Record
preload-sounds
Preload multiple sounds into the cache.
Record -> List -> Record
has-sound?
Check if a sound is already cached.
Record -> String -> Bool
unload-sound
Remove a sound from the cache and unload it.
Record -> String -> Record
get-font
Get a font from the cache, loading it if not present. Returns {asset: Ptr, cache: Record}
Record -> String -> Record
has-font?
Check if a font is already cached.
Record -> String -> Bool
get-music
Get music from the cache, loading it if not present. Returns {asset: Ptr, cache: Record}
Record -> String -> Record
has-music?
Check if music is already cached.
Record -> String -> Bool
preload-all
Preload textures, sounds, fonts, and music from asset lists.
Record -> Record -> Record
unload-all
Unload all cached assets and return an empty cache.
Record -> Record
size
Get the total number of cached assets.
Record -> Int
create
Create debug state with optional configuration. Config fields (all optional - provide only the ones you want to override): enabled: Bool (default: false) show-fps: Bool (default: true) show-frame-time: Bool (default: true) max-frame-history: Int (default: 60)
Record -> Record
empty
Default debug state. Use as Game.Debug.empty.
Record
toggle
Toggle overlay visibility
Record -> Record
enable
Enable the overlay
Record -> Record
disable
Disable the overlay
Record -> Record
watch
Add a watch variable to display on the overlay. The value should be a string; use interpolation for non-string values.
Record -> String -> String -> Record
update
Update debug state each frame. Records frame time and clears watches for the next frame. Call this in your update function.
Record -> Float -> Record
set-entity-count
Set entity count to display on overlay (0 to hide)
Record -> Int -> Record
set-scene-name
Set current scene name to display on overlay ("" to hide)
Record -> String -> Record
pause
Pause the game. When paused, is-paused? returns true and should-advance? returns false until step or unpause is called.
Record -> Record
unpause
Unpause the game.
Record -> Record
toggle-pause
Toggle pause state.
Record -> Record
step
Request a single frame advance while paused. Call this when the step key is pressed.
Record -> Record
is-paused?
Check if the game is currently paused.
Record -> Bool
should-advance?
Check if the game should advance this frame. Returns true if not paused, or if a step was requested. Call this in your update function to decide whether to process game logic.
Record -> Bool
consume-step
Consume a step request. Call after advancing one paused frame.
Record -> Record
profile-start
Start timing a named profile marker.
Record -> String -> Record
profile-end
End timing a named profile marker. Finds the most recent un-ended marker with this name and records elapsed time.
Record -> String -> Record
profile-get
Get the elapsed time of the most recent completed profile marker. Returns 0.0 if no matching completed marker exists.
Record -> String -> Float
clear-profiles
Clear all profile markers.
Record -> Record
toggle-console
Toggle the debug console open/closed.
Record -> Record
console-open?
Check if the debug console is open.
Record -> Bool
register-command
Register a console command. name: command name (first word typed) handler: fn(String) -> String - receives args string, returns output
Record -> String -> (String -> String) -> Record
console-input-char
Append a character to the console input. Only works when console is open.
Record -> String -> Record
console-backspace
Remove the last character from console input. Only works when console is open.
Record -> () -> Record
console-submit
Submit the current console input, execute the command, and add to history. Returns updated state with cleared input.
Record -> Record
console-clear
Clear the console input and history.
Record -> Record
get-history
Get the console history as a list of {input, output} records.
Record -> List
get-console-input
Get the current console input string.
Record -> String
draw-console
Draw the debug console if open. Call this in your draw function after drawing the game.
Record -> ()
draw
Draw the debug overlay if enabled. Call this at the end of your draw function.
Record -> ()
draw-bounds
Draw a rectangle outline for visual debugging (e.g. collision bounds). Only draws if debug state is enabled.
Record -> Float -> Float -> Float -> Float -> Int -> ()
draw-vector
Draw a line representing a vector from a point. Only draws if debug state is enabled.
Record -> Float -> Float -> Float -> Float -> Int -> ()
draw-circle
Draw a circle for visual debugging. Only draws if debug state is enabled.
Record -> Float -> Float -> PositiveFloat -> Int -> ()
draw-point
Draw a point/crosshair for visual debugging.
Record -> Float -> Float -> Int -> ()
default-body
Default dynamic body. Override fields with record spread.
Record
default-world
Default physics world with gravity (0, 300).
Record
static-body
Create a static body (obstacle/wall).
Float -> Float -> Float -> Float -> Record
create-world
Create a world with custom gravity.
Float -> Float -> Record
add-body
Add a body to the world. Returns the updated world and the assigned id.
Record -> Record -> Record
get-body
Get a body by id (returns Option).
Record -> Int -> Option
set-body
Update a body by id.
Record -> Int -> Record -> Record
remove-body
Remove a body by id.
Record -> Int -> Record
body-count
Count bodies in the world.
Record -> Int
step
Step the physics simulation forward by dt seconds. Applies gravity, integrates velocity, applies friction. Only dynamic bodies are updated.
Record -> Float -> Record
step-with-collisions
Step with collision resolution between all bodies. Resolves overlaps and applies bounce (restitution).
Record -> Float -> Record
apply-force
Apply a force to a body (affects acceleration). Force is cleared after each step.
Record -> Float -> Float -> Record
apply-impulse
Apply an instantaneous impulse to a body (affects velocity directly).
Record -> Float -> Float -> Record
set-velocity
Set the body's velocity directly.
Record -> Float -> Float -> Record
set-position
Set the body's position directly.
Record -> Float -> Float -> Record
set-size
Set the body's size.
Record -> Float -> Float -> Record
stop
Zero out the velocity.
Record -> Record
scale-velocity
Scale the velocity (for time dilation / slow motion).
Record -> Float -> Record
get-position
Get the position as a {x, y} record.
Record -> Record
get-velocity
Get the velocity as a {x, y} record.
Record -> Record
get-bounds
Get the body's AABB bounds.
Record -> Record
point-in-body?
Check if a point is inside a body's bounds.
Float -> Float -> Record -> Bool
on-ground?
Check if a body is on the ground (has downward collision). Tests a small ray below the body against static bodies.
Record -> Record -> Bool
move-and-slide
Move a body and resolve collisions with static bodies in the world. Returns the updated world with the moved body.
Record -> Int -> Float -> Float -> Record
resolve-all-collisions
Resolve all body-vs-body collisions in the world. Static-static pairs are skipped. Dynamic-dynamic pairs get mutual separation.
Record -> Record
create
Create a pool from a list of pre-allocated objects. Each object is wrapped with an id and active flag.
List -> Record
create-with-factory
Create a pool with a factory function called N times.
Int -> (() -> Record) -> Record
acquire
Acquire an available object from the pool. Returns {pool: Record, data: Option, id: Int}. id is -1 if no object is available.
Record -> Record
release
Release an object back to the pool by id.
Record -> Int -> Record
release-all
Release all active objects back to the pool.
Record -> Record
is-active?
Check if an entry is active.
Record -> Int -> Bool
get
Get an active entry's data by id (returns None if inactive or missing).
Record -> Int -> Option
active-list
Get all active entries as a list of {id, data} records.
Record -> List
active-data
Get only the data of all active objects.
Record -> List
active-count
Count active objects.
Record -> Int
available-count
Count available (inactive) objects.
Record -> Int
capacity
Total pool capacity.
Record -> Int
has-available?
Check if pool has any available objects.
Record -> Bool
is-empty?
Check if pool is completely inactive.
Record -> Bool
update
Update an active object's data by id. Only updates if the entry is active.
Record -> Int -> (Record -> Record) -> Record
map-active
Map a function over all active objects' data. Inactive objects are left unchanged.
Record -> (Record -> Record) -> Record
filter-active
Filter active objects by predicate, releasing those that don't match.
Record -> (Record -> Bool) -> Record
grow
Resize the pool by adding new inactive objects. Preserves existing active entries.
Record -> List -> Record
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
Texture -> Sprite
create-centered
Create a static sprite with centered origin
Texture -> Sprite
draw
Draw a static sprite
Sprite -> Float -> Float -> ()
draw-tinted
Draw a static sprite with tint
Sprite -> Float -> Float -> Int -> ()
draw-ex
Draw a static sprite with rotation and scale
Sprite -> Float -> Float -> Float -> Float -> Int -> ()
draw-pro
Draw a static sprite with full control
Sprite -> Float -> Float -> Float -> Float -> Float -> Int -> ()
animated
Create an animated sprite from a sprite sheet
Config fields: texture: Ptr - The sprite sheet texture frame-width: Int - Width of each frame in pixels frame-height: Int - Height of each frame in pixels animations: Map - Map of animation name to {frames: [Int], fps: Float} default-animation: String - Name of the animation to start with (optional)
{texture: Texture, frame-width: Int, frame-height: Int, animations: Map, default-animation: String} -> AnimatedSprite
animated-centered
Create an animated sprite with centered origin
{texture: Texture, frame-width: Int, frame-height: Int, animations: Map, default-animation: String} -> AnimatedSprite
set-animation
Set the current animation
AnimatedSprite -> NonEmptyString -> AnimatedSprite
update
Update an animated sprite Advances the current animation based on its fps and frames list.
AnimatedSprite -> Float -> AnimatedSprite
update-with
Update with explicit animation data
AnimatedSprite -> Float -> List -> Float -> AnimatedSprite
play
Play the animation
AnimatedSprite -> AnimatedSprite
pause
Pause the animation
AnimatedSprite -> AnimatedSprite
reset
Reset the animation
AnimatedSprite -> AnimatedSprite
set-flip-x
Set horizontal flip
AnimatedSprite -> Bool -> AnimatedSprite
set-flip-y
Set vertical flip
AnimatedSprite -> Bool -> AnimatedSprite
draw-animated
Draw an animated sprite
AnimatedSprite -> Float -> Float -> Int -> Int -> ()
draw-current
Draw current frame Looks up the current animation's frame list to resolve the sprite sheet index.
AnimatedSprite -> Float -> Float -> Int -> ()
draw-animated-ex
Draw with rotation and scale
AnimatedSprite -> Float -> Float -> Int -> Float -> Float -> Int -> ()
frame-count
Calculate the total number of frames in a sprite sheet
Texture -> Int -> Int -> Int
frame-position
Calculate the position of a frame in a sprite sheet
Texture -> Int -> Int -> Int -> {x: Int, y: Int}
row-frames
Get frame indices for a row
Texture -> Int -> Int -> Int -> List
col-frames
Get frame indices for a column
Texture -> Int -> Int -> Int -> Int -> List
set-origin
Set the origin of a sprite
Sprite -> Float -> Float -> Sprite
center-origin
Center the origin of a sprite
Sprite -> Sprite
bottom-center-origin
Set the origin to bottom-center
Sprite -> Sprite
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
NonEmptyString -> 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)
NonEmptyString -> 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 -> ()
main-file
Generate a starter main.kit file content. title: the game window title
String -> String
kit-toml
Generate a starter kit.toml file content. name: package name version: e.g. "0.1.0"
String -> String -> String
readme
Generate a starter README.md file content. title: project title
String -> String
gitignore
Generate a starter .gitignore file content.
() -> String
scaffold
Generate all starter file contents as a record. Fields: main, kit-toml, readme, gitignore
String -> String -> Record
key-down?
Check if a key is currently held down
NonEmptyString -> Bool
key-pressed?
Check if a key was just pressed this frame
NonEmptyString -> Bool
key-released?
Check if a key was just released this frame
NonEmptyString -> Bool
key-up?
Check if a key is not being pressed
NonEmptyString -> 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
NonEmptyString -> Bool
mouse-pressed?
Check if a mouse button was just pressed
NonEmptyString -> Bool
mouse-released?
Check if a mouse button was just released
NonEmptyString -> Bool
mouse-wheel
Get the mouse wheel movement (positive = up)
() -> Float
mouse-wheel-move
Backwards-compatible alias for mouse wheel movement
() -> 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 -> NonEmptyString -> Bool
gamepad-button-pressed?
Check if a gamepad button was just pressed
Int -> NonEmptyString -> Bool
gamepad-button-released?
Check if a gamepad button was just released
Int -> NonEmptyString -> Bool
gamepad-axis
Get a gamepad axis value (-1.0 to 1.0)
Int -> NonEmptyString -> 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:
NonEmptyString -> 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
NonEmptyString -> Ptr
unload-sound
Unload a sound from memory
Ptr -> ()
load-music
Load streaming music from a file
Supported formats: OGG, MP3, WAV, FLAC
NonEmptyString -> Ptr
unload-music
Unload music from memory
Ptr -> ()
load-font
Load a font from a file
Supported formats: TTF, OTF, FNT
NonEmptyString -> Ptr
load-font-size
Load a font with specific size
NonEmptyString -> PositiveInt -> 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
NonEmptyString -> 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
NonEmptyString -> Result
try-load-sound
Load sound with result handling
NonEmptyString -> Result
try-load-music
Load music with result handling
NonEmptyString -> 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 -> ()
default
Default auto-save state (60 second interval, enabled). Override fields with record spread: auto = {...Game.AutoSave.default, interval: 30.0, slot: "quicksave"}
Record
update
Update the auto-save timer. Call each frame with dt. Returns state with due flag set to true when timer reaches zero.
Record -> Float -> Record
is-due?
Check if auto-save is due this frame.
Record -> Bool
is-enabled?
Check if auto-save is enabled.
Record -> Bool
time-remaining
Get seconds remaining until next save.
Record -> Float
get-slot
Get the save slot name.
Record -> String
set-enabled
Enable or disable auto-save.
Record -> Bool -> Record
set-interval
Set the interval and reset the timer.
Record -> Float -> Record
set-slot
Set the save slot name.
Record -> String -> Record
reset
Reset the timer to the full interval. Call after performing a save.
Record -> Record
trigger-now
Trigger an immediate save on the next frame. Sets timer to zero.
Record -> Record
save
Save game state to a slot The state is serialized to JSON and written to save-{slot}.json
String -> Record -> Result () String
load
Load game state from a slot Returns the parsed JSON value. The caller must convert it to their state type.
String -> Result Record String
exists?
Check if a save slot exists
String -> Bool
delete
Delete a save slot
String -> Result () String
slot-path
Get the file path for a save slot
String -> String
slot-path-in
Get the file path for a save slot in a directory
String -> String -> String
save-versioned
Save game state with a version number. The state is wrapped in an envelope with version metadata.
String -> Int -> Record -> Result () String
load-versioned
Load a versioned save, running migrations if needed. migrations: List of (Record -> Record) functions, where index i migrates from version i to i+1 Returns Ok state if successful, or Err if file missing, parse failed, or migration missing.
String -> Int -> List -> Result Record String
create-migrations
Create an empty migrations list.
() -> List
register-migration
Register a migration function (transforms Record from version N to N+1). migrations is a list where index 0 migrates from v0->v1, index 1 from v1->v2, etc.
List -> (Record -> Record) -> List
get-version
Get the version from a raw loaded save (returns 0 for legacy saves).
Record -> Int
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 -> NonEmptyString -> 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