collider

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: MIT Imports: 23 Imported by: 0

README

# Collider

The fastest way to a playable 2D game in Go. Every game you build can be played by humans and by AI agents, out of the box.

Collider is a code-first 2D game engine built around one idea: games are made of objects that collide, and things that happen when they do. You import the library, describe your objects, attach events, and you have a game. No editor, no project files, no boilerplate game loop.

player.OnCollisionWith("enemy", func(e *engine.Object) {
    g.Sound("hit.wav")
    g.Go("gameover")
})

That covers the humans. For the agents, the very same binary you ship to players is also a deterministic headless environment for bots and CI, and an MCP server that any AI agent can connect to and play, with zero extra code in your game:

claude mcp add mygame -e COLLIDER_AGENT=mcp -- C:\path\to\mygame.exe

Zombie Night, one of the example games

What's in the box:

  • Collision-first core: enter-only collision events, tag rules, solid resolution, gravity, spatial hash broad phase
  • AI agents can play every game made with Collider, out of the box: headless and deterministic for bots and CI, over MCP for any AI agent (Claude, Cursor, or a plain script), or on-screen via autopilot; one example game is played by its own agent and even records its demo GIF itself
  • Scenes, timers, sprite-sheet animations, text with custom TTF fonts, sound and music (wav/ogg)
  • Fourteen example games across genres, from pong to a dungeon crawler, each one a template you can start from
  • Shipping built in: embed assets into a single .exe or build for the browser; one example is live on itch.io
  • A GIF recorder for demos, and generated placeholder assets so nothing here needs hand-drawn art to run

Design principles

  1. Fewest lines possible. A complete game with menus, music, sprites and logic should fit in one small file. Every line of required boilerplate is a bug.
  2. Collisions are the core. Clicks are point-vs-object collisions. Triggers, solid walls, bullets hitting enemies: one unified system with events.
  3. Sensible defaults. Sprites collide with their image bounds. Sounds just play. Scenes just switch. Configuration is always optional.
  4. Scenes are everything. A menu, a level and a game-over screen are all the same concept. Learn one thing, build every screen of your game with it.
  5. No magic. Plain Go, plain callbacks, go get and read the code.

Built on top of Ebitengine for windowing, rendering, input and audio. Collider is the game-object, collision and event layer that every Ebitengine project currently rebuilds by hand.


Install

go get github.com/LucasAntunesdeAlmeida/collider
import engine "github.com/LucasAntunesdeAlmeida/collider"

Hello, collision

The smallest complete program: two objects, one event.

go run ./examples/hello
package main

import (
	"fmt"

	engine "github.com/LucasAntunesdeAlmeida/collider"
)

func main() {
	g := engine.New("Hello, collision", 800, 600)
	play := g.Scene("play")

	box := play.Add(engine.Rect(64, 64, engine.Red).At(400, 300))
	player := play.Add(engine.Rect(48, 48, engine.Blue).At(100, 300))

	player.OnUpdate(func(dt float64) {
		if g.Key(engine.Right) {
			player.Move(200*dt, 0)
		}
		if g.Key(engine.Left) {
			player.Move(-200*dt, 0)
		}
	})

	player.OnCollision(func(other *engine.Object) {
		fmt.Println("hit!")
	})

	box.OnClick(func() {
		box.Destroy()
	})

	g.Run("play")
}

Example games

Fourteen complete games, each exercising a different part of the engine and each a starting point for your own. Run any of them from its own folder so the asset paths resolve:

cd examples/pong
go run .
Game Genre What it proves
Hello Smallest program Objects, movement, collision and click events
Pong Arcade / versus Built-in velocity, solid bounce, score text
Jumper Platformer Gravity, solid ground, Grounded(), pickups
Zombie Night Top-down shooter Runtime spawning, tags, scene collision rules, timers
Breakout Brick breaker Grid spawning, win conditions, mouse control, menus
Memory Point-and-click puzzle A game with zero movement, pure click events
Arena Survival Extending the engine: your own types embedding Object with custom methods
Caves Exploration Procedural generation: cellular automata map, BFS-guaranteed winnable
Runner Endless runner Sprite sheet animations (run/jump/death), moving-world auto-scroll
Dialog Visual novel Custom TTF fonts, text size and color, typewriter effect
Dungeon Dungeon crawler Multiple screens: ASCII room layouts, edge transitions, key and lock
Catcher Arcade Save system with plain encoding/json, no engine API needed
Ship Arcade Publishing: embedded assets, fullscreen/resizable/icon, exe and browser builds
Gem Rush Arcade Agents only: no human input; played by its own pilot, headless bots, or MCP agents

Each example folder has the game's code, an explanation and a demo GIF. The placeholder assets are generated by go run ./tools/genassets; replace them with real art and the games look like games.

AI agents can play your game

Any game you build with Collider is agent-playable out of the box, with zero overhead until used. An agent sees the game as structured data, one observation per step: the scene, and every object with its tag, position, motion, size and text (so HUDs and scores are readable):

{"scene": "play", "objects": [
  {"tag": "player", "x": 400, "y": 520, "w": 48, "h": 48},
  {"tag": "comet", "x": 312, "y": 180, "vy": 260, "w": 24, "h": 24},
  {"text": "SCORE 12", "x": 64, "y": 24, "w": 96, "h": 16}
], "state": {"lives": 2, "wave": 3}}

Three optional calls make any game, however complex, fully agent-playable and self-describing:

  • g.Controls(map[string]engine.Key{"jump": engine.Space, ...}) names your inputs; the MCP act tool accepts these names and lists them in its own description, so agents discover how to play on connect.
  • g.AgentState(func() any {...}) attaches game state (score, health, phase) to every observation as the state field above.
  • g.AgentDocs("...") serves your game's rules to agents when they connect (the MCP initialize instructions).

Four ways in:

  • Headless (bots, CI): g.Headless("play") then a loop of g.Step(engine.Action{Keys: ...}), each step returning the next observation. Deterministic: same actions, same results. Playtest your game with a bot on every commit.
  • MCP (AI agents): run any Collider game with COLLIDER_AGENT=mcp and it serves MCP on stdio (observe, act, reset tools). Any MCP client can connect and play your game; act accepts any keyboard key by name, or the names you declared with Controls.
  • Windowed MCP (fight the AI): COLLIDER_AGENT=mcp-window opens the normal window running in real time while serving the same MCP tools. Agent input merges with the keyboard, so a person and an agent can play the same game together, and COLLIDER_RECORD captures the match.
  • Autopilot (watch it): g.Autopilot(fn) runs the game windowed while your agent function supplies the input each frame. Combine with the GIF recorder and an agent records your demo for you.

Connect any MCP client in one command

The game itself is the MCP server (stdio): there is nothing to install. With Claude:

claude mcp add mygame -e COLLIDER_AGENT=mcp -- C:\path\to\mygame.exe

Cursor, Windsurf, VS Code and every other MCP client take the same shape, a command plus one env var:

{"mcpServers": {"mygame": {
  "command": "C:/path/to/mygame.exe",
  "env": {"COLLIDER_AGENT": "mcp"}
}}}

The protocol is plain newline-delimited JSON-RPC, so even a Python script can drive a game through a subprocess.

Tag your player "player" so agents can find themselves. A game can opt out entirely with g.DisallowAgents(). The Gem Rush example is a game with no human input at all: its own pilot plays it, and its demo GIF is agent-recorded.

Publish your game

Collider games ship as a single self-contained .exe (assets embedded via engine.UseAssets and go:embed) or run in the browser via WebAssembly, ready for itch.io. PUBLISHING.md is the complete guide; the ship example has it all wired up, and it is actually published: play Ship in your browser on itch.io.

Record a GIF of your game

Every Collider game can record itself, no tooling needed. Set the COLLIDER_RECORD environment variable to a file path, play, close the window, and the session is saved as an animated GIF (the demos above were made exactly this way):

$env:COLLIDER_RECORD="demo.gif"; go run .

API cheat sheet

The complete public surface implied by the example games. If it is not here, it does not exist. That is the point.

Game

Call Meaning
engine.New(title, w, h) *Game Create the game/window
g.Scene(name) *Scene Create (or fetch) a scene
g.Go(name) Switch scenes (state preserved)
g.Restart(name) Switch scenes, resetting it to its initial state
g.Run(name) Start the loop on a scene (blocks)
g.Key(k) bool Is this key held?
g.Mouse() (x, y) Cursor position (a finger on a touch screen counts)
g.Sound(path) Fire-and-forget sound effect
g.Quit() Exit
g.Fullscreen(on) / g.Resizable(on) / g.Icon(path) Window polish
g.Headless(scene) / g.Step(action) / g.Observe() Agent play, headless and deterministic
g.Controls(map[string]Key) Name your inputs so agents can discover them
g.AgentState(fn) Attach game state to every observation
g.AgentDocs(text) Game rules served to agents on MCP connect
g.DisallowAgents() Opt out of agent play (on by default)

Scene

Call Meaning
s.Add(obj) *Object Put an object in the scene (any time, even mid-game)
s.Music(path) Looping background music while the scene is active
s.Gravity(px_per_s2) Gravity for WithGravity() objects
s.Every(sec, fn) Repeating timer
s.After(sec, fn) One-shot timer
s.OnClick(fn(x, y)) Click anywhere in the scene
s.OnUpdate(fn(dt)) Runs every frame while the scene is active
s.OnCollision(tagA, tagB, fn(a, b)) Rule for every current and future pair
s.Count(tag) int How many objects with this tag are alive

Object: constructors and configuration (chainable)

Call Meaning
engine.Sprite(path) Object from an image (collider = image bounds)
engine.Rect(w, h, color) Colored rectangle object
engine.Text(str) Text object (clickable, but never collides)
engine.UseAssets(fs) Load all assets from an embedded filesystem (go:embed)
.At(x, y) Position (center); .AtEdge() picks a random screen edge
.Tag(name) Label for tag-based collision rules
.Solid() Engine resolves overlaps (walls, floors, paddles)
.WithGravity() Affected by the scene's gravity
.Size(w, h) Override collider size
.Animation(name, strip, frames, fps) Define a sprite-sheet animation
.Font(path) / .TextSize(px) / .TextColor(c) Text styling (custom TTF, size, color)

Object: runtime

Call Meaning
o.X, o.Y, o.Vx, o.Vy Position and velocity; velocity applies every frame
o.Data Free any field for your game state
o.Move(dx, dy) Move (respects solid collisions)
o.MoveToward(x, y, dist) / o.VelocityToward(x, y, speed) Homing helpers
o.Grounded() bool Resting on a solid (platformers)
o.SetText(s) / o.SetSprite(path) Change content at runtime
o.Play(name) / o.PlayOnce(name) Switch animations (loop / hold last frame)
o.LifeTime(sec) Auto-destroy after n seconds
o.Destroy() Remove from scene (safe inside callbacks; applied at end of frame)
o.OnUpdate(fn(dt)) Per-frame logic
o.OnClick(fn) Clicked (point-vs-bounds collision)
o.OnCollision(fn(other)) Touching anything
o.OnCollisionWith(tag, fn(other)) Touching anything with this tag

Behavior you can rely on

  1. Destroy() is always safe, including inside any callback: the object is removed at the end of the frame, never mid-iteration.
  2. Collision events fire on enter. OnCollision fires once when contact begins, not on every frame of overlap. Continuous contact (standing on the floor) is one event.
  3. Solid vs trigger is the whole physics story. Solid() objects push others out; everything else just reports contact. No forces, no torque, no restitution. If your game needs Angry Birds physics, this is not its engine.
  4. Text never collides. A score label overlapping the ball will not bounce it. Text objects render and take clicks, nothing else.
  5. Restart rolls a scene back to its setup. Objects added before the scene first runs are restored (even if destroyed); objects and timers spawned during play are dropped. Variables captured in your closures are yours to reset.
  6. A tap is a click. g.Mouse() and every OnClick read touch as well as the mouse, so a game built for a mouse works on a phone without a second input path. A lifted finger leaves the cursor where it was, so anything following the cursor stays put until the next touch.

Documentation

Overview

Package collider is a code-first 2D game engine focused on collisions and events.

You import the library, describe your objects, attach events, and you have a game: no editor, no project files, no boilerplate game loop.

g := collider.New("My Game", 800, 600)
play := g.Scene("play")

player := play.Add(collider.Rect(48, 48, collider.Blue).At(100, 300))
player.OnCollisionWith("enemy", func(e *collider.Object) {
	g.Go("gameover")
})

g.Run("play")

See README.md for the full spec and five complete example games.

Index

Constants

Variables

View Source
var (
	White  = color.RGBA{R: 0xF2, G: 0xF2, B: 0xF2, A: 0xFF}
	Black  = color.RGBA{R: 0x10, G: 0x10, B: 0x10, A: 0xFF}
	Red    = color.RGBA{R: 0xE5, G: 0x3E, B: 0x3E, A: 0xFF}
	Green  = color.RGBA{R: 0x3E, G: 0xB6, B: 0x58, A: 0xFF}
	Blue   = color.RGBA{R: 0x3E, G: 0x6F, B: 0xE5, A: 0xFF}
	Yellow = color.RGBA{R: 0xF2, G: 0xC9, B: 0x38, A: 0xFF}
	Orange = color.RGBA{R: 0xF2, G: 0x8C, B: 0x38, A: 0xFF}
)

Functions

func Shuffle

func Shuffle[T any](s []T) []T

Shuffle returns a shuffled copy of a slice. Handy for card decks and spawn tables.

func UseAssets added in v0.2.0

func UseAssets(f fs.FS)

UseAssets routes all asset loading (sprites, sounds, music, fonts) through a filesystem instead of the disk: pass an embed.FS and the game ships as a single self-contained binary.

//go:embed sprites audios
var content embed.FS

func main() {
	collider.UseAssets(content)
	...
}

Call it before creating objects. Without it, paths load from disk, which is what you want during development.

Types

type Action added in v0.2.0

type Action struct {
	Keys   []Key   `json:"-"` // keys held during the frame
	MouseX float64 `json:"mouseX"`
	MouseY float64 `json:"mouseY"`
	Click  bool    `json:"click"` // press the left button this frame
}

Action is one frame of injected input.

type Color

type Color = color.Color

Color is any standard library color. The palette below covers the common cases so examples never need to import image/color.

type Game

type Game struct {
	// contains filtered or unexported fields
}

Game owns the window, the scenes, the asset cache and the main loop.

func New

func New(title string, width, height int) *Game

New creates a game with a window title and size in pixels.

func (*Game) AgentDocs added in v0.3.0

func (g *Game) AgentDocs(docs string)

AgentDocs sets the game's agent-facing documentation: rules, goals, coordinate conventions, anything an agent should know before playing. It is returned as the MCP server's instructions on initialize. Optional.

func (*Game) AgentState added in v0.3.0

func (g *Game) AgentState(fn func() any)

AgentState attaches game-defined state to every observation: fn runs once per observation and its result appears as the "state" field. Use it for what object positions cannot express: score, health, phase, whose turn it is. Optional.

func (*Game) Autopilot added in v0.2.0

func (g *Game) Autopilot(fn func(Observation) Action)

Autopilot runs the game windowed while an agent function supplies the input: fn receives each frame's observation and returns the action to hold. Watch a bot play, or combine with COLLIDER_RECORD and let the agent record its own demo GIF. Call before Run.

func (*Game) Controls added in v0.3.0

func (g *Game) Controls(controls map[string]Key)

Controls names this game's inputs for agents: action name to key, like {"jump": engine.Space, "p2-attack": ebiten.KeyNumpad1}. The MCP act tool then accepts these names and lists them in its description, so any agent discovers how to play without reading the game's source. Optional; raw key names always work.

func (*Game) DisallowAgents added in v0.2.0

func (g *Game) DisallowAgents()

DisallowAgents turns agent play off for this game: Headless, Step and the MCP server refuse to run, and COLLIDER_AGENT is ignored. Agent play is allowed by default.

func (*Game) Fullscreen added in v0.2.0

func (g *Game) Fullscreen(on bool)

Fullscreen switches fullscreen on or off. Callable any time, including from an input handler for an F11 toggle.

func (*Game) Go

func (g *Game) Go(name string)

Go switches to another scene at the end of the current frame. The scene keeps its state; use Restart to reset it.

func (*Game) Headless added in v0.2.0

func (g *Game) Headless(scene string)

Headless prepares the game to be driven by Step instead of Run: no window, no audio, injected input, fixed 60 steps per second.

func (*Game) Height

func (g *Game) Height() float64

Height returns the window height in pixels.

func (*Game) Icon added in v0.2.0

func (g *Game) Icon(path string)

Icon sets the window icon from an image asset.

func (*Game) Key

func (g *Game) Key(k Key) bool

Key reports whether a key is currently held down.

func (*Game) Mouse

func (g *Game) Mouse() (x, y float64)

Mouse returns the cursor position in game coordinates.

func (*Game) Observe added in v0.2.0

func (g *Game) Observe() Observation

Observe returns the structured state of the current frame without advancing it.

func (*Game) Quit

func (g *Game) Quit()

Quit closes the window and returns from Run.

func (*Game) Resizable added in v0.2.0

func (g *Game) Resizable(on bool)

Resizable lets the player resize the window; the game keeps its logical resolution and scales.

func (*Game) Restart

func (g *Game) Restart(name string)

Restart switches to a scene after rolling it back to its initial state: setup objects restored, runtime spawns and timers dropped.

func (*Game) Run

func (g *Game) Run(name string)

Run starts the game on the given scene and blocks until the window closes or Quit is called. If the COLLIDER_RECORD environment variable is set to a file path, the session is saved there as an animated GIF.

Agent play (unless the game called DisallowAgents):

  • COLLIDER_AGENT=mcp runs headless as an MCP server on stdio; act steps the simulation deterministically.
  • COLLIDER_AGENT=mcp-window opens the window and runs in real time while serving the same MCP tools: agents and the person at the keyboard play together, and the session is watchable (and recordable with COLLIDER_RECORD).

func (*Game) Scene

func (g *Game) Scene(name string) *Scene

Scene returns the scene with this name, creating it on first use.

func (*Game) Sound

func (g *Game) Sound(path string)

Sound plays a short effect, fire and forget. Silent in headless (agent) runs so bots and CI never touch the audio device.

func (*Game) Step added in v0.2.0

func (g *Game) Step(a Action) Observation

Step advances exactly one frame with the given input and returns the resulting observation. Deterministic: same actions, same results.

func (*Game) Width

func (g *Game) Width() float64

Width returns the window width in pixels.

type Key

type Key = ebiten.Key

Key identifies a keyboard key. The constants below cover common game controls; any ebiten.Key value also works.

type Object

type Object struct {
	X, Y   float64
	Vx, Vy float64

	// Data is a free field for game state (a card face, hit points, anything).
	Data any
	// contains filtered or unexported fields
}

Object is anything that lives in a scene: the player, a wall, a bullet, a button. Position is the object's center. Velocity applies every frame.

func Button added in v0.2.0

func Button(label string) *Object

Button creates a clickable plate with a centered label: menus, retry screens, anything a player presses. Like text, buttons never collide.

play := menu.Add(collider.Button("PLAY").At(400, 350))
play.OnClick(func() { g.Go("play") })

Size follows the label unless Size is called; Color sets the plate color (the light and dark edges are derived from it) and TextColor the label.

func Rect

func Rect(w, h float64, c Color) *Object

Rect creates a colored rectangle object.

func Sprite

func Sprite(path string) *Object

Sprite creates an object from an image file. The collider defaults to the image bounds; override with Size. The image itself is loaded from the game's asset cache when the object is added to a scene.

func Text

func Text(str string) *Object

Text creates a text object. Text objects render on screen and can be clicked, but never take part in collisions: a score label overlapping the ball must not bounce it.

func (*Object) Animation added in v0.2.0

func (o *Object) Animation(name, path string, frames int, fps float64) *Object

Animation defines a named animation from a horizontal sprite strip: the image is cut into `frames` equal slices played at `fps`. Chainable. Define several (run, jump, death...) and switch with Play.

func (*Object) At

func (o *Object) At(x, y float64) *Object

At places the object's center. Chainable.

func (*Object) AtEdge

func (o *Object) AtEdge() *Object

AtEdge places the object at a random point on a random screen edge when it is added to a scene. Chainable.

func (*Object) Color added in v0.2.0

func (o *Object) Color(c Color) *Object

Color sets the object's color: the fill of a Rect, the plate of a Button. Chainable.

func (*Object) Destroy

func (o *Object) Destroy()

Destroy removes the object at the end of the frame. Always safe to call from inside callbacks.

func (*Object) Font added in v0.2.0

func (o *Object) Font(path string) *Object

Font sets a custom font from a TTF/OTF file path. Chainable.

func (*Object) Grounded

func (o *Object) Grounded() bool

Grounded reports whether the object is resting on a solid object. The platformer jump check.

func (*Object) LifeTime

func (o *Object) LifeTime(sec float64) *Object

LifeTime destroys the object automatically after this many seconds. Chainable, and callable after Add too (bullets, particles).

func (*Object) Move

func (o *Object) Move(dx, dy float64)

Move shifts the object by a delta. Overlaps with solid objects are resolved at the end of the frame.

func (*Object) MoveToward

func (o *Object) MoveToward(x, y, dist float64)

MoveToward moves the object dist pixels toward a point, stopping exactly on it instead of overshooting.

func (*Object) OnClick

func (o *Object) OnClick(fn func())

OnClick fires when the object is clicked (a point-vs-bounds collision).

func (*Object) OnCollision

func (o *Object) OnCollision(fn func(other *Object))

OnCollision fires once when the object starts touching another object.

func (*Object) OnCollisionWith

func (o *Object) OnCollisionWith(tag string, fn func(other *Object))

OnCollisionWith fires once when the object starts touching an object carrying this tag.

func (*Object) OnUpdate

func (o *Object) OnUpdate(fn func(dt float64))

OnUpdate runs every frame with the elapsed time in seconds.

func (*Object) Play added in v0.2.0

func (o *Object) Play(name string)

Play switches to a looping animation. Playing the animation that is already active does nothing, so calling it every frame is fine.

func (*Object) PlayOnce added in v0.2.0

func (o *Object) PlayOnce(name string)

PlayOnce switches to an animation that runs once and holds its last frame: death, explosion, one-shot attacks.

func (*Object) SetSprite

func (o *Object) SetSprite(path string)

SetSprite swaps the object's image at runtime.

func (*Object) SetText

func (o *Object) SetText(str string)

SetText changes the text at runtime and re-measures the bounds.

func (*Object) Size

func (o *Object) Size(w, h float64) *Object

Size overrides the collider (and draw) size. Chainable.

func (*Object) Solid

func (o *Object) Solid() *Object

Solid marks the object as solid geometry: the engine pushes non-solid objects out of it instead of letting them pass through. Chainable.

func (*Object) Tag

func (o *Object) Tag(name string) *Object

Tag labels the object for tag-based collision rules. Chainable.

func (*Object) TextColor added in v0.2.0

func (o *Object) TextColor(c Color) *Object

TextColor sets the text color (default white). Chainable.

func (*Object) TextSize added in v0.2.0

func (o *Object) TextSize(px float64) *Object

TextSize sets the font size in pixels. Chainable.

func (*Object) VelocityToward

func (o *Object) VelocityToward(x, y, speed float64)

VelocityToward points the object's velocity at a target with the given speed. The bullet helper.

func (*Object) Visual added in v0.2.0

func (o *Object) Visual() *Object

Visual marks an object as decoration: it is drawn but never takes part in collisions. Use it for backgrounds and scenery so they do not clutter the collision world. Chainable.

func (*Object) WithGravity

func (o *Object) WithGravity() *Object

WithGravity makes the object fall with the scene's gravity. Chainable.

type ObjectObs added in v0.2.0

type ObjectObs struct {
	Tag   string  `json:"tag,omitempty"`
	X     float64 `json:"x"`
	Y     float64 `json:"y"`
	Vx    float64 `json:"vx,omitempty"`
	Vy    float64 `json:"vy,omitempty"`
	W     float64 `json:"w"`
	H     float64 `json:"h"`
	Solid bool    `json:"solid,omitempty"`
	Text  string  `json:"text,omitempty"`
}

ObjectObs describes one live object. Tag is the game's own label (tag your player "player" so agents can find themselves); Text is set for text objects, so HUDs and scores are readable.

type Observation added in v0.2.0

type Observation struct {
	Scene   string      `json:"scene"`
	Objects []ObjectObs `json:"objects"`
	State   any         `json:"state,omitempty"`
}

Observation is the structured view of the current frame: the scene name, every object with its position, motion and label, and whatever extra state the game attached with AgentState.

type Scene

type Scene struct {
	// contains filtered or unexported fields
}

Scene is a screen of the game: a level, a menu, a game-over screen. It holds objects and runs their events every frame.

func (*Scene) Add

func (s *Scene) Add(o *Object) *Object

Add puts an object into the scene. It is safe to call at any time, including from inside callbacks; the object joins this frame.

func (*Scene) After

func (s *Scene) After(sec float64, fn func())

After runs fn once, sec seconds from now, while the scene is active.

func (*Scene) Count

func (s *Scene) Count(tag string) int

Count reports how many objects with this tag are alive.

func (*Scene) Every

func (s *Scene) Every(sec float64, fn func())

Every runs fn repeatedly, every sec seconds, while the scene is active.

func (*Scene) Gravity

func (s *Scene) Gravity(g float64)

Gravity sets downward acceleration in pixels per second squared for objects marked WithGravity.

func (*Scene) Music

func (s *Scene) Music(path string)

Music sets looping background music (wav or ogg) that plays while the scene is active.

func (*Scene) OnClick

func (s *Scene) OnClick(fn func(x, y float64))

OnClick fires on every click anywhere in the scene, before any object-level click handling.

func (*Scene) OnCollision

func (s *Scene) OnCollision(tagA, tagB string, fn func(a, b *Object))

OnCollision declares a rule for every current and future pair of objects with these tags. The callback receives the objects in tag order: the tagA object first.

func (*Scene) OnUpdate added in v0.2.0

func (s *Scene) OnUpdate(fn func(dt float64))

OnUpdate runs every frame while the scene is active, before object updates. The place for scene-wide input like a fullscreen toggle.

Directories

Path Synopsis
examples
agent command
Gem Rush: a game with NO human input.
Gem Rush: a game with NO human input.
agent/bot command
The headless run: the same Decide pilot plays Gem Rush with no window at all, via Headless and Step.
The headless run: the same Decide pilot plays Gem Rush with no window at all, via Headless and Step.
agent/game
Package game is Gem Rush: collect all gems before the timer runs out.
Package game is Gem Rush: collect all gems before the timer runs out.
arena command
Arena: survive the chasers.
Arena: survive the chasers.
arena/scripts
Package scripts holds this game's custom types.
Package scripts holds this game's custom types.
breakout command
Breakout: clear fifty bricks with three lives.
Breakout: clear fifty bricks with three lives.
catcher command
Catcher: catch falling gems with the basket for 30 seconds.
Catcher: catch falling gems with the basket for 30 seconds.
caves command
Caves: explore a procedurally generated cave and collect every gem.
Caves: explore a procedurally generated cave and collect every gem.
caves/scripts
Package scripts holds the map generation for Caves: pure algorithms, no engine types.
Package scripts holds the map generation for Caves: pure algorithms, no engine types.
dialog command
Dialog: a visual-novel style conversation with drawn portraits, a framed dialog box, a typewriter effect with letter blips, and a menu.
Dialog: a visual-novel style conversation with drawn portraits, a framed dialog box, a typewriter effect with letter blips, and a menu.
dungeon command
Dungeon: four connected rooms, a key, a locked door, a treasure chest.
Dungeon: four connected rooms, a key, a locked door, a treasure chest.
dungeon/scripts
Package scripts holds the dungeon's world: a grid of rooms drawn as ASCII layouts.
Package scripts holds the dungeon's world: a grid of rooms drawn as ASCII layouts.
hello command
Hello, collision: the smallest complete Collider program.
Hello, collision: the smallest complete Collider program.
jumper command
Jumper: climb the platforms, grab every coin, avoid the spikes.
Jumper: climb the platforms, grab every coin, avoid the spikes.
memory command
Memory: flip cards two at a time and find the eight pairs of pixel icons.
Memory: flip cards two at a time and find the eight pairs of pixel icons.
pong command
Pong: first to five points.
Pong: first to five points.
runner command
Runner: an endless runner with a drawn sprinter.
Runner: an endless runner with a drawn sprinter.
ship command
Ship: a small dodge game built to be PUBLISHED.
Ship: a small dodge game built to be PUBLISHED.
zombie-night command
Zombie Night: survive the horde.
Zombie Night: survive the horde.
internal
assets
Package assets loads and caches game content: images, sound effects and music.
Package assets loads and caches game content: images, sound effects and music.
mcps
Package mcps is a minimal MCP (Model Context Protocol) server over stdio: newline-delimited JSON-RPC 2.0 with the initialize, tools/list and tools/call methods.
Package mcps is a minimal MCP (Model Context Protocol) server over stdio: newline-delimited JSON-RPC 2.0 with the initialize, tools/list and tools/call methods.
physics
Package physics holds collision primitives: AABB tests now, the spatial hash broad phase in M4.
Package physics holds collision primitives: AABB tests now, the spatial hash broad phase in M4.
record
Package record captures gameplay frames and writes an animated GIF.
Package record captures gameplay frames and writes an animated GIF.
tools
cover command
Command cover generates the repository's social preview image (.github/social-preview.png, 1280x640) from real project assets: the pixel font, the engine palette and gameplay frames pulled straight from the example demo GIFs.
Command cover generates the repository's social preview image (.github/social-preview.png, 1280x640) from real project assets: the pixel font, the engine palette and gameplay frames pulled straight from the example demo GIFs.
genassets command
Command genassets draws every example game's art and sound from code: pixel art as ASCII grids (sprites.go), backgrounds and tiles as small generators (art.go), sounds as synthesized waveforms, plus a copy of the Press Start 2P font (with its OFL license) into each game that uses text.
Command genassets draws every example game's art and sound from code: pixel art as ASCII grids (sprites.go), backgrounds and tiles as small generators (art.go), sounds as synthesized waveforms, plus a copy of the Press Start 2P font (with its OFL license) into each game that uses text.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL