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 Align
- 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) CanQuit() bool
- func (g *Game) CloseOverlay()
- func (g *Game) Controls(controls map[string]Key)
- func (g *Game) DisallowAgents()
- func (g *Game) Focused() bool
- 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) Language() string
- func (g *Game) Load(key string, v any) bool
- func (g *Game) Mouse() (x, y float64)
- func (g *Game) MouseDown() bool
- func (g *Game) MusicVolume(v float64)
- func (g *Game) Observe() Observation
- func (g *Game) OnClose(fn func())
- func (g *Game) Overlay(name string)
- func (g *Game) PadAxis(a PadAxis) float64
- func (g *Game) PadConnected() bool
- func (g *Game) PadDown(b PadButton) bool
- 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) Save(key string, v any) error
- func (g *Game) Scene(name string) *Scene
- func (g *Game) Sound(path string)
- func (g *Game) SoundVolume(v float64)
- func (g *Game) Step(a Action) Observation
- func (g *Game) Volume(v float64)
- func (g *Game) Width() float64
- type Key
- type Object
- func (o *Object) Alpha(a float64) *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) Fixed() *Object
- func (o *Object) Flash(c Color, sec float64)
- func (o *Object) FlipX(on bool) *Object
- func (o *Object) Font(paths ...string) *Object
- func (o *Object) Grounded() bool
- func (o *Object) Height() float64
- func (o *Object) Hitbox(w, h float64) *Object
- func (o *Object) Layer(n int) *Object
- func (o *Object) LifeTime(sec float64) *Object
- func (o *Object) LineHeight(px 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) Rotate(rad float64) *Object
- 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) TextAlign(a Align) *Object
- func (o *Object) TextColor(c Color) *Object
- func (o *Object) TextSize(px float64) *Object
- func (o *Object) Tint(c Color) *Object
- func (o *Object) Touching(tag string) []*Object
- func (o *Object) VelocityToward(x, y, speed float64)
- func (o *Object) Visual() *Object
- func (o *Object) Width() float64
- func (o *Object) WithGravity() *Object
- func (o *Object) Wrap(width float64) *Object
- type ObjectObs
- type Observation
- type PadAxis
- type PadButton
- type Scene
- func (s *Scene) Add(o *Object) *Object
- func (s *Scene) After(sec float64, fn func())
- func (s *Scene) Camera(x, y float64)
- 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) Near(tag string, x, y, r float64) []*Object
- 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 ¶
const ( Left = ebiten.KeyArrowLeft Right = ebiten.KeyArrowRight Up = ebiten.KeyArrowUp Down = ebiten.KeyArrowDown Space = ebiten.KeySpace Enter = ebiten.KeyEnter Esc = ebiten.KeyEscape W = ebiten.KeyW A = ebiten.KeyA S = ebiten.KeyS D = ebiten.KeyD F = ebiten.KeyF R = ebiten.KeyR P = ebiten.KeyP M = ebiten.KeyM )
const ( PadA = ebiten.StandardGamepadButtonRightBottom // bottom face button PadB = ebiten.StandardGamepadButtonRightRight // right face button PadX = ebiten.StandardGamepadButtonRightLeft // left face button PadY = ebiten.StandardGamepadButtonRightTop // top face button PadLB = ebiten.StandardGamepadButtonFrontTopLeft PadRB = ebiten.StandardGamepadButtonFrontTopRight PadLT = ebiten.StandardGamepadButtonFrontBottomLeft // left trigger, pulled PadRT = ebiten.StandardGamepadButtonFrontBottomRight // right trigger, pulled PadBack = ebiten.StandardGamepadButtonCenterLeft // View / Select / Share PadStart = ebiten.StandardGamepadButtonCenterRight // Menu / Start / Options PadLStick = ebiten.StandardGamepadButtonLeftStick // left stick, pressed in PadRStick = ebiten.StandardGamepadButtonRightStick // right stick, pressed in PadUp = ebiten.StandardGamepadButtonLeftTop // d-pad PadDown = ebiten.StandardGamepadButtonLeftBottom PadLeft = ebiten.StandardGamepadButtonLeftLeft PadRight = ebiten.StandardGamepadButtonLeftRight )
const ( PadLeftX = ebiten.StandardGamepadAxisLeftStickHorizontal // -1 left .. 1 right PadLeftY = ebiten.StandardGamepadAxisLeftStickVertical // -1 up .. 1 down PadRightX = ebiten.StandardGamepadAxisRightStickHorizontal // -1 left .. 1 right PadRightY = ebiten.StandardGamepadAxisRightStickVertical // -1 up .. 1 down )
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
// MouseDown holds the pointer at MouseX, MouseY this frame (drags,
// virtual joysticks); Click implies it on its frame.
MouseDown bool `json:"mouseDown"`
// Pad holds gamepad buttons this frame, and StickX, StickY push
// the left stick (-1..1, clamped; Y grows downward). The first
// action that uses the pad connects it (PadConnected) for the rest
// of the run.
Pad []PadButton `json:"-"`
StickX float64 `json:"stickX"`
StickY float64 `json:"stickY"`
}
Action is one frame of injected input.
type Align ¶ added in v0.6.3
type Align int
Align is how the lines of a text line up in its box (TextAlign).
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. Like every agent run it plays no audio. Call before Run.
func (*Game) CanQuit ¶ added in v0.6.0
CanQuit reports whether Quit can end the game here: true on desktop and in headless play, false in a browser. Show a QUIT menu entry only when it is true.
func (*Game) CloseOverlay ¶ added in v0.4.0
func (g *Game) CloseOverlay()
CloseOverlay removes the overlay at the start of the next frame and the scene under it resumes where it froze. Safe to call with no overlay open. Go and Restart close the overlay too.
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": engine.KeyNamed("Numpad1")}. 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 locks a shipped game against outside control: Headless, Step, Autopilot and the MCP server refuse to run, and the COLLIDER_AGENT and COLLIDER_RECORD environment variables are ignored, so nothing can drive the game or make it write a GIF to a path of its choosing. Agent play (and recording) is allowed by default; call it only in release builds if you still want to record demos.
func (*Game) Focused ¶ added in v0.4.0
Focused reports whether the game window has the keyboard focus, so a game can pause itself when the player switches away. Always true in headless and agent play (Step, MCP, Autopilot), where there is no player to switch away.
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. Any open overlay closes.
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) Language ¶ added in v0.6.3
Language reports the player's language as a BCP 47 tag, such as "pt-BR", "zh-CN", "en-US" or "de", or "" when it is unknown: the moment to pick the game's translation, before or while building scenes (it needs only New). Match leniently: the primary subtag ("pt", "zh") picks the translation, the region or script only where it matters (zh-CN and zh-Hans are Simplified Chinese, zh-TW and zh-Hant Traditional), and anything unknown or "" falls back to the game's default.
Where it comes from: on Windows, the user's display language; on macOS, the first preferred language (System Settings), then the environment; on Linux and other Unix systems, LC_ALL, LC_MESSAGES or LANG ("pt_BR.UTF-8" becomes "pt-BR"; "C" and "POSIX" mean unknown), with GNU's LANGUAGE list taking precedence as it does for gettext; in a browser, navigator.language.
Agent and test runs (Headless, Autopilot, COLLIDER_AGENT=mcp, go test: the runs that are silent and keep saves in memory) get "", so the game plays in its default language and agents see the same text on every machine. Headless and Autopilot count from the moment they are called; a bot that builds the game first and then calls Headless should set COLLIDER_LANG.
The COLLIDER_LANG environment variable overrides all of this, agent runs included, to try a translation without changing the system ("COLLIDER_LANG=zh-CN go run ."); COLLIDER_LANG=C forces "". Like LANG, it only picks among the game's own strings, so it is honored even after DisallowAgents.
func (*Game) Load ¶ added in v0.4.0
Load reads the value saved under key into v, which must be a pointer, and reports whether it did. A missing key (the first run) or data that does not decode into v returns false and leaves v untouched, so defaults set before Load survive. Fields missing from an older save keep the values v already had.
func (*Game) MouseDown ¶ added in v0.4.0
MouseDown reports whether the pointer is held: the left mouse button, or any finger on a touch screen. Drag, aim, charge, a virtual joystick: read it with Mouse every frame. Clicks (a press) still arrive through OnClick.
func (*Game) MusicVolume ¶ added in v0.6.0
MusicVolume sets the music's own volume, 0 to 1 (the default), clamped like Volume. The music plays at this times the master Volume, starting with the track playing now. For a settings menu's music slider.
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) OnClose ¶ added in v0.6.2
func (g *Game) OnClose(fn func())
OnClose runs fn once when the player closes the window (the X button, Alt+F4, the taskbar, a launcher's exit), before the game ends: the moment to save progress or bank a run in progress. fn runs on the game loop, between two frames, like any other callback; then the game quits the way Quit does (the window closes and Run returns, saving the COLLIDER_RECORD GIF on the way). There is no veto: a close request always ends the game, since launchers and the OS expect it to.
Only a close request runs fn: Quit is the game's own decision and does not. Headless runs (Step, COLLIDER_AGENT=mcp) have no window, so fn never runs there. In a browser a page is closed by its tab, not by the game: fn never runs either (save as you go; saves there are written at once). OnClose(nil) restores the default: the window closes at once. Callable any time, before or after Run.
func (*Game) Overlay ¶ added in v0.4.0
Overlay shows a scene on top of the current one: a pause menu, an inventory, a level-up choice. The overlay runs (its timers, updates, clicks and collisions) and draws above, while the scene under it still draws but is frozen: no updates, no timers, no input. Like Go, it takes effect at the start of the next frame, so the key or click that opened it never reaches the overlay on the same frame. Opening one while another is open replaces it. The overlay keeps its state between openings (Restart it by hand if it should start fresh) and never changes the music.
func (*Game) PadAxis ¶ added in v0.6.0
PadAxis returns a stick axis from -1 to 1, raw: no dead zone, so apply your own (a resting stick rarely reads exactly 0; ignoring lengths under 0.2 is typical). Y grows downward like the screen. With several pads, the one pushed furthest on this axis answers. Agents set the left stick through Action.StickX and StickY.
func (*Game) PadConnected ¶ added in v0.6.0
PadConnected reports whether a gamepad with a standard layout is connected, so a game can show pad prompts ("A" instead of "ENTER"). In headless and agent play it is false until an action first uses the pad, then true for the rest of the run.
func (*Game) PadDown ¶ added in v0.6.0
PadDown reports whether a gamepad button is held on any connected controller with a standard layout (Xbox, PlayStation, Switch Pro, Steam Deck and most others). Agents hold pad buttons through Action.Pad.
func (*Game) Quit ¶
func (g *Game) Quit()
Quit ends the game after the current frame: the frame finishes (its updates, deferred destroys and draw), then the window closes and Run returns, saving the COLLIDER_RECORD GIF on the way. Callable any time, from any callback, as often as you like.
In a browser Quit does nothing, since a page cannot close its tab; CanQuit reports it, so a game can hide its QUIT entry there. Headless, the run ends instead: every later Step advances nothing and returns the final observation, marked Quit; Headless starts a new run.
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. Any open overlay closes.
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 (unless the game called DisallowAgents).
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) Save ¶ added in v0.4.0
Save stores v as JSON under key, for the next run of the game: best scores, unlocks, settings. On desktop each key is a file in the user's config directory (under a folder named after the game title); in the browser it is an entry in localStorage. Games run by agents or tests (Headless, Autopilot, COLLIDER_AGENT=mcp, go test) keep saves in memory instead, so bots and CI never touch the player's data.
Keys are simple names like "best" or "settings"; characters other than letters, digits, '-', '_' and '.' are replaced.
func (*Game) Sound ¶
Sound plays a short effect, fire and forget. Agent and test runs (Headless, Autopilot, COLLIDER_AGENT=mcp, go test) are silent: no audio work at all, the device is never opened. On a machine with no working audio device the game plays silently too, after one log line.
func (*Game) SoundVolume ¶ added in v0.6.0
SoundVolume sets the sound effects' own volume, 0 to 1 (the default), clamped like Volume. Every Sound started afterwards plays at this times the master Volume; at 0, Sound does no work at all.
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. Once the game has called Quit, Step advances nothing and returns the final observation, with Quit set.
func (*Game) Volume ¶ added in v0.4.0
Volume sets the master volume from 0 (muted) to 1 (full, the default); values outside are clamped, NaN counts as 0. It scales both channels, MusicVolume and SoundVolume: it applies to the music that is playing right away, and to every sound effect and music started afterwards. Callable any time, including from an input handler for a mute key.
type Key ¶
Key identifies a keyboard key. The constants below cover common game controls; KeyNamed reaches every other key by name.
func KeyNamed ¶ added in v0.5.0
KeyNamed returns the key with this name, for keys beyond the constants: KeyNamed("1") for a card pick, KeyNamed("Tab"), KeyNamed("F1"). It accepts the same names agents send over MCP, case sensitive: letters "A" to "Z"; the number row as "0" to "9" or "Digit0" to "Digit9" (the keypad is "Numpad0" to "Numpad9"); "F1" to "F24"; the ebiten names of the rest ("ArrowLeft", "ShiftLeft", "Escape", "Backspace", "Tab", "Comma", "Minus", ...); and the aliases Left, Right, Up, Down, Space, Enter, Esc. An unknown name panics: a typo is a bug, so look keys up once, at setup.
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 (drawing too) or Hitbox (collisions only). 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) Alpha ¶ added in v0.4.0
Alpha sets the object's opacity, from 0 (invisible) to 1 (opaque, the default): fades, ghosts, translucent auras. Chainable, and callable any time.
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) Fixed ¶ added in v0.4.0
Fixed pins the object to the screen: its position is in screen pixels, it ignores the scene camera, and clicks hit it where it is drawn. The HUD, a pause button, a virtual joystick. Like Visual objects, fixed ones never collide: they do not live in the world. Chainable.
func (*Object) Flash ¶ added in v0.4.0
Flash draws the object as a solid silhouette of color c for sec seconds, then back to normal: the classic hit flash is o.Flash(engine.White, 0.1). Opacity still applies; a new flash replaces a running one.
func (*Object) FlipX ¶ added in v0.4.0
FlipX mirrors the object horizontally when on: a character facing the way it walks. Drawing only; applies to sprites, rectangles and text. Chainable, and callable any time.
func (*Object) Font ¶ added in v0.2.0
Font sets the text's font from TTF/OTF file paths, each read once and cached. With several, the first draws every glyph it has and the others, in order, fill in the rest: a pixel font for Latin and Cyrillic, then a CJK font for Chinese:
engine.Text(s).Font("fonts/pixel.ttf", "fonts/cjk.ttf")
Every font draws at the same TextSize, and every glyph of a line sits on one baseline. A line is as tall as the largest ascent plus the largest descent among the fonts the text actually uses, so text the first font draws entirely measures and draws exactly as with that font alone: adding a fallback never moves it. A fallback font is only read and parsed the first time a text needs one of its glyphs. Pixel fonts stay sharp at whole multiples of their design size; an 8px Latin font and a 12px CJK font are both sharp at 24 and 48.
The empty path is the built-in Go font, the default; Font() with no paths restores it. A path that does not exist panics here. Chainable.
func (*Object) Grounded ¶
Grounded reports whether the object is resting on a solid object. The platformer jump check.
func (*Object) Height ¶ added in v0.6.4
Height is the object's drawn height in pixels, measured like Width. A text is as tall as its lines: from the first line's top to the last line's bottom, LineHeight apart.
func (*Object) Hitbox ¶ added in v0.5.0
Hitbox sets the collision box apart from the drawn size: a w x h box centered on the object's position, used by collisions, solids, Touching and Near, and reported to agents as the object's w and h. Drawing, culling and clicks keep the sprite (or Size) bounds, since players click what they see. The fair-contact fix: a 42px hero with a 26px hitbox is only hurt when a chaser really reaches it. Without Hitbox the collider is the drawn size, as before. Chainable, and callable any time.
func (*Object) Layer ¶ added in v0.4.0
Layer sets the draw order: lower layers draw first, higher ones on top, and objects on the same layer keep the order they were added in. Clicks go to the topmost object. The default layer is 0; any int works, negative included. Chainable, and callable any time.
func (*Object) LifeTime ¶
LifeTime destroys the object automatically after this many seconds. Chainable, and callable after Add too (bullets, particles).
func (*Object) LineHeight ¶ added in v0.6.3
LineHeight sets the distance in pixels from one line's baseline to the next, for text with several lines. The default (0) is the fonts' own line height: the largest ascent plus the largest descent (plus any line gap) of the fonts in use, so lines of a pixel font touch; 1.5 times the text size is a comfortable paragraph. The box runs from the first line's top to the last line's bottom. Chainable, and callable any time.
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) Rotate ¶ added in v0.4.0
Rotate turns the object to an absolute angle in radians, clockwise on screen, around its center: an arrow pointing where it flies. Drawing only: the collider stays the upright box. Applies to sprites, rectangles and text. Chainable, and callable any time.
func (*Object) Size ¶
Size overrides the drawn size, which is also the collider unless Hitbox sets one apart. Chainable.
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) TextAlign ¶ added in v0.6.3
TextAlign sets how the lines of a text line up in its box: centered (the default), left or right. The box is the widest line, the Wrap column or the Size, and stays centered on the text's position; a single line without Wrap fills its box, so it only matters for text with several lines, or with Wrap. Chainable, and callable any time.
func (*Object) TextColor ¶ added in v0.2.0
TextColor sets the text color (default white). Chainable.
func (*Object) Tint ¶ added in v0.4.0
Tint multiplies the object's colors by c: one white sprite becomes a red, blue or pale variant, a scene goes cold under a blue tint. nil clears it. Chainable, and callable any time.
func (*Object) Touching ¶ added in v0.4.0
Touching returns the objects with this tag whose box (the Hitbox, when set) overlaps this one's right now, in scene order: continuous contact, for damage over time or standing in a zone, next to the enter-only OnCollision events. Like collisions, it ignores visual, text and Fixed objects (and returns nothing when called on one), dead objects, and the object itself. The slice is the caller's to keep.
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) Width ¶ added in v0.6.4
Width is the object's drawn width in pixels, the box it is drawn in and clicked by: its Size when set, else a Rect's width, a sprite's image width (known once the object is in a scene), or a text's measured width, with its fonts (fallbacks included), TextSize and Wrap (a wrapped text is its column wide), plus the plate margins of a button. A Hitbox never changes it. Text is measured the moment it changes, so Width is current right after SetText, Font, TextSize, Wrap or LineHeight, in the same frame, with no window and nothing drawn yet: lay out a label by its edge, or test in go test that every translation fits its box.
func (*Object) WithGravity ¶
WithGravity makes the object fall with the scene's gravity. Chainable.
func (*Object) Wrap ¶ added in v0.6.3
Wrap breaks the text into lines no wider than width pixels, at spaces in Latin and Cyrillic text and between any two CJK characters, never before closing punctuation (,。!?」 , . ! ?) or after opening punctuation (「( ( ), and never inside a word unless the word alone is wider than the line (then between its letters). A "\n" always starts a new line; spaces at the end of a wrapped line are dropped.
The text's box becomes a column exactly width wide (for clicks, and agents' w) and as tall as its lines, centered on the text's position like every object: with TextAlign(AlignLeft) the lines start at X - width/2 whatever they say. The object's text (and what agents read) stays the unwrapped string. For a fixed text area (a dialog box) whose first line stays put however many lines follow, give the text a Size too: its lines then start at the top of that box. 0 turns wrapping off. Applies to buttons' labels too. Chainable, and callable any time.
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"`
// Fixed objects (the HUD) report screen coordinates; everything
// else is in world coordinates, which differ once the scene moves
// its camera.
Fixed bool `json:"fixed,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. W and H are the collision box: the object's Hitbox when it has one, else its drawn size.
type Observation ¶ added in v0.2.0
type Observation struct {
Scene string `json:"scene"`
Overlay string `json:"overlay,omitempty"`
Objects []ObjectObs `json:"objects"`
State any `json:"state,omitempty"`
// Quit is set once the game has called Quit (a QUIT menu entry):
// the run is over, and further steps advance nothing.
Quit bool `json:"quit,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. While an overlay is open (a pause menu), Overlay names it and Objects lists the frozen scene's objects first, then the overlay's.
type PadAxis ¶ added in v0.6.0
type PadAxis = ebiten.StandardGamepadAxis
PadAxis identifies a stick axis in the standard layout.
type PadButton ¶ added in v0.6.0
type PadButton = ebiten.StandardGamepadButton
PadButton identifies a gamepad button in the standard layout (an Xbox style controller: A at the bottom of the face buttons). Nintendo and PlayStation pads map by position, so PadA is Cross on a PlayStation pad and B on a Nintendo one.
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) Camera ¶ added in v0.4.0
Camera centers the view on a world point: every object draws shifted so that (x, y) lands in the middle of the screen, and clicks land in the world where they appear to. Call it every frame to follow the player. Objects marked Fixed ignore the camera. The default camera looks at the screen center, where world and screen coordinates are the same.
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. Like Sound, it stays silent in agent and test runs and on a machine with no working audio device.
func (*Scene) Near ¶ added in v0.4.0
Near returns the live objects with this tag whose box (the Hitbox, when set) overlaps the circle of radius r around (x, y), closest center first (ties keep scene order). Visual objects count, Fixed ones (screen space) never do. The auto-aim and pickup-magnet query: s.Near("enemy", p.X, p.Y, 300). The slice is the caller's to keep.
func (*Scene) OnClick ¶
OnClick fires on every click anywhere in the scene, before any object-level click handling. The position is in world coordinates, so under a moving camera it is where the click lands in the world.
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. |
|
horde
command
Horde: survive the night on a field far bigger than the window.
|
Horde: survive the night on a field far bigger than the window. |
|
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. |

