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
- func Shuffle[T any](s []T) []T
- func UseAssets(f fs.FS)
- type Action
- type Color
- type Game
- func (g *Game) AgentDocs(docs string)
- func (g *Game) AgentState(fn func() any)
- func (g *Game) Autopilot(fn func(Observation) Action)
- func (g *Game) Controls(controls map[string]Key)
- func (g *Game) DisallowAgents()
- func (g *Game) Fullscreen(on bool)
- func (g *Game) Go(name string)
- func (g *Game) Headless(scene string)
- func (g *Game) Height() float64
- func (g *Game) Icon(path string)
- func (g *Game) Key(k Key) bool
- func (g *Game) Mouse() (x, y float64)
- func (g *Game) Observe() Observation
- func (g *Game) Quit()
- func (g *Game) Resizable(on bool)
- func (g *Game) Restart(name string)
- func (g *Game) Run(name string)
- func (g *Game) Scene(name string) *Scene
- func (g *Game) Sound(path string)
- func (g *Game) Step(a Action) Observation
- func (g *Game) Width() float64
- type Key
- type Object
- func (o *Object) Animation(name, path string, frames int, fps float64) *Object
- func (o *Object) At(x, y float64) *Object
- func (o *Object) AtEdge() *Object
- func (o *Object) Color(c Color) *Object
- func (o *Object) Destroy()
- func (o *Object) Font(path string) *Object
- func (o *Object) Grounded() bool
- func (o *Object) LifeTime(sec float64) *Object
- func (o *Object) Move(dx, dy float64)
- func (o *Object) MoveToward(x, y, dist float64)
- func (o *Object) OnClick(fn func())
- func (o *Object) OnCollision(fn func(other *Object))
- func (o *Object) OnCollisionWith(tag string, fn func(other *Object))
- func (o *Object) OnUpdate(fn func(dt float64))
- func (o *Object) Play(name string)
- func (o *Object) PlayOnce(name string)
- func (o *Object) SetSprite(path string)
- func (o *Object) SetText(str string)
- func (o *Object) Size(w, h float64) *Object
- func (o *Object) Solid() *Object
- func (o *Object) Tag(name string) *Object
- func (o *Object) TextColor(c Color) *Object
- func (o *Object) TextSize(px float64) *Object
- func (o *Object) VelocityToward(x, y, speed float64)
- func (o *Object) Visual() *Object
- func (o *Object) WithGravity() *Object
- type ObjectObs
- type Observation
- type Scene
- func (s *Scene) Add(o *Object) *Object
- func (s *Scene) After(sec float64, fn func())
- func (s *Scene) Count(tag string) int
- func (s *Scene) Every(sec float64, fn func())
- func (s *Scene) Gravity(g float64)
- func (s *Scene) Music(path string)
- func (s *Scene) OnClick(fn func(x, y float64))
- func (s *Scene) OnCollision(tagA, tagB string, fn func(a, b *Object))
- func (s *Scene) OnUpdate(fn func(dt float64))
Constants ¶
Variables ¶
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
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 ¶
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 (*Game) AgentDocs ¶ added in v0.3.0
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
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
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
Fullscreen switches fullscreen on or off. Callable any time, including from an input handler for an F11 toggle.
func (*Game) Go ¶
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
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) 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) Resizable ¶ added in v0.2.0
Resizable lets the player resize the window; the game keeps its logical resolution and scales.
func (*Game) Restart ¶
Restart switches to a scene after rolling it back to its initial state: setup objects restored, runtime spawns and timers dropped.
func (*Game) Run ¶
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) Sound ¶
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.
type 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
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 Sprite ¶
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 ¶
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
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) AtEdge ¶
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
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) Grounded ¶
Grounded reports whether the object is resting on a solid object. The platformer jump check.
func (*Object) LifeTime ¶
LifeTime destroys the object automatically after this many seconds. Chainable, and callable after Add too (bullets, particles).
func (*Object) Move ¶
Move shifts the object by a delta. Overlaps with solid objects are resolved at the end of the frame.
func (*Object) MoveToward ¶
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 ¶
OnCollision fires once when the object starts touching another object.
func (*Object) OnCollisionWith ¶
OnCollisionWith fires once when the object starts touching an object carrying this tag.
func (*Object) Play ¶ added in v0.2.0
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
PlayOnce switches to an animation that runs once and holds its last frame: death, explosion, one-shot attacks.
func (*Object) Solid ¶
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) TextColor ¶ added in v0.2.0
TextColor sets the text color (default white). Chainable.
func (*Object) VelocityToward ¶
VelocityToward points the object's velocity at a target with the given speed. The bullet helper.
func (*Object) Visual ¶ added in v0.2.0
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 ¶
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 ¶
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) Gravity ¶
Gravity sets downward acceleration in pixels per second squared for objects marked WithGravity.
func (*Scene) Music ¶
Music sets looping background music (wav or ogg) that plays while the scene is active.
func (*Scene) OnClick ¶
OnClick fires on every click anywhere in the scene, before any object-level click handling.
func (*Scene) OnCollision ¶
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.
Source Files
¶
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. |

