Help us shape the future of Go! Take the 2026 Go Developer Survey

gram

package module
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 2 Imported by: 0

README

gram

gram logo
Go Version GoDoc License Codecov Coverage Go Quality Check

gram is a modular game engine for Go. A game is a set of named Stages, each with its own entity-component world and its own Scenes; an engine drives the active Stage on the goke ECS, a tick and a picture a frame, and draws it on the GPU through WebGPU (gogpu, pure Go). Everything beyond the tick loop is a plugin: the built-in ones give a Stage a world of moving boxes, collisions, sight, a board with terrain, pathfinding and mouse selection, and a game adds its own the same way.

Features  •  Installation  •  Example  •  Demos  •  Model  •  Architecture  •  Benchmarks  •  Documentation

Design Goals

  • One extension point. Everything beyond the tick loop is a plugin.Plugin, built-in or yours. There is no registry and no lookup by name: a plugin that needs another takes it as a constructor argument.
  • A Stage owns its ECS. Each Stage gets a fresh world the moment it is entered, so a menu Stage sits idle with no gameplay entities until the player starts.
  • Behaviour is rules. What a game does about what a plugin finds is a rule, a sentence of who, when and what, run inside that plugin's own pass — written in ceremony, the library gram builds on. A rule is a role's, a role is played, and the engine hands it to the plugin catching its moment; one no plugin catches is an error.
  • Kinds say what an entity is. A kind is the list of components its entities carry, each constant or read from the entity's own row; it also tells save files what to expect.
  • Saves survive change. Persisted resources are matched by name, never by position.
  • Contract in the open, orchestration inside. What a game implements (game, plugin, render) is public and documented; only the engine that drives it is internal.

📦 Installation

go get github.com/kjkrol/gram

Prerequisites: Go 1.27+ and a GPU with a Vulkan, Metal or DirectX 12 driver; gogpu needs no cgo. Without a GPU the tests that draw skip themselves.

✨ Key Features

Capability Package What you get
Stages and Scenes game, game/stage Named Stages with their own ECS, defined a section at a time; Scenes as ui screens showing the world through cameras; a live Composition of what is shown and which Scene takes input
Plugins plugin The one extension contract; Installer.Hosts, where a plugin hands the engine the hosts that run the rules of its moments inside its own pass
Behaviour ceremony The library gram builds on, through its binding over goke (ceremony/goke): act.Branch[P]{Name, When, Then} a rule of a moment, plan.Loop[P]{Name, When, Then, Until, Timeout, Cooldown} a loop of a plan, every clause of either saying whom it is about (cond.Self.If(x), act.Other.Do(cmd)); roles a kind, a cell or a plugin plays; effects that hold for a while and turn the plugins' knobs; messages between plans; commands written as sentences, for entities found by name or group
World plugins/world Every entity's Base; the spatial index under stop, wrap or open edges; kinds and spawning before the game and during it; heights or planes
Motion plugins/motion, plugins/motion/steering Every entity moved each step, Moving and Leaving for rules; a Steering profile turned into heading and speed; Driven for a unit steered by hand
Collisions plugins/collision Collider to take part, Physics to bounce and be pushed apart, the solid ground of a board, Meeting and Struck for rules
Gravity plugins/gravity Bodies falling, standing on what bears them and leaping, along Z or across the plane, as the pull goes; Leap, Away and Landing for rules
Shooting plugins/bullet Shots as entities fired from a unit's muzzle or thrown in an arc, swept by collision; Landing, Resting and Blast for rules
Sight plugins/vision A Sight cone scanned into Sighted, cut by walls and dimmed by forests, over them by height; Sighting rules per observer
Conversations plugins/dialog Nodes of lines and answers from YAML, every unit with lines of its own; what an answer changes is the game's own
Board and navigation plugins/board, plugins/navigation Square or hex grid with terrain, ways and what stands on it, in a world with heights; a map laid out of a file; MoveOrder paths that re-route, onto a bridge's deck or under it
Bridges plugins/bridges Bridges built by one set of rules whoever builds them: a level's file, the map maker, a player with a bridge in hand
Light plugins/light The sun and the lamps as sources on entities, what each thing casts and takes; the shadows of the relief and of what stands still baked into the ground as the sun moves, the live ones laid over whatever ground is drawn
Topography plugins/topography A map in relief on the GPU: heights shaped, lit and shaded, every step's slope for the board's mobility, water glinting and running; the cameras' cage
Atmosphere plugins/atmosphere The calendar, the sky of the hour (the Earth's with the real stars, or a game's own of four parts), the climate and the weather, what falls and what it does to the board
Selection, players, cameras plugins/selection, plugins/players, plugins/cameras Click and marquee into Selected; players over the command handlers, their bindings and a list of keys (K); cameras made where a scene shows them, on a stick turned and leaned from straight down to isometric and flatter, orthographic or in perspective, kept out of what a map makes solid, fastened over a unit, behind it or inside it
Minimap plugins/minimap A small picture round a player's camera, turning with it or north up: the ground in miniature, a dot for each kind its figure marks, the camera's view outlined; a click on it takes the camera there
Telemetry plugins/telemetry The panel in the corner saying how the game runs — the frame rate, the ticks, where a frame's time goes, the entities, the game time, the plugins' and the game's own lines — in every Stage with a world, shown and hidden with ~
Persistence game.Persistence Save, load and list the active Stage's ECS and every tracked value by name
Rendering render, camera Everything drawn on the GPU (WebGPU, WGSL): sources drawn over one another by height in a shared depth buffer, the ground first and the marks last, Direct sources with shaders of their own, an atlas baked at Close

Example

The smallest game that does something: one Stage with a torus of bouncing boxes, a collision plugin counting their contacts, and one Scene showing them through a camera from above, the telemetry panel over it (~ shows everything, then hides it). This is examples/start/minimal; run it with make demo-start-minimal.

package main

import (
	"image/color"
	"math/rand/v2"
	"time"

	"github.com/kjkrol/aabbworld"
	"github.com/kjkrol/aabbworld/geom"
	"github.com/kjkrol/ceremony/comp"
	"github.com/kjkrol/goke/v3"
	"github.com/kjkrol/gram"
	"github.com/kjkrol/gram/camera"
	"github.com/kjkrol/gram/entity/kind"
	"github.com/kjkrol/gram/game"
	"github.com/kjkrol/gram/game/stage"
	"github.com/kjkrol/gram/plugins/cameras"
	"github.com/kjkrol/gram/plugins/collision"
	"github.com/kjkrol/gram/plugins/motion"
	"github.com/kjkrol/gram/plugins/players"
	"github.com/kjkrol/gram/plugins/telemetry"
	"github.com/kjkrol/gram/plugins/world"
	"github.com/kjkrol/gram/render"
	"github.com/kjkrol/gram/ui"
)

const (
	screenWidth, screenHeight = 640, 480
	boxSize                   = 12
	boxCount                  = 300
)

type boxRow struct {
	pos world.Position
	vel world.Velocity
}

// box is the one kind: a bouncing square
type box struct{}

var _ world.Figure = box{}

func (box) Define(w *world.Plugin) {
	kind.Define[boxRow](w.Kinds(), BoxKind, kind.Spec{
		comp.Load(func(b boxRow) world.Position { return b.pos }),
		comp.Load(func(b boxRow) world.Velocity { return b.vel }),
		comp.Const(collision.Collider{}),
		comp.Const(collision.Physics{Restitution: 1}),
	})
}

func (box) Look(a *world.Atlas, w *world.Plugin) {
	a.Add(kind.Named[boxRow](w.Kinds(), BoxKind), boxSize, render.Solid(boxColor))
}

const (
	BoxKind    = "box"
	ArenaStage = "arena"
	ViewScene  = "view"
)

type arena struct {
	world     *world.Plugin
	motion    *motion.Plugin
	collision *collision.Plugin
	cameras   *cameras.Plugin
	players   *players.Plugin
	telemetry *telemetry.Plugin
	player    *players.Player
	stats     collision.ContactStats
}

func main() {
	props := game.Props{
		Title:        "gram minimal",
		ScreenWidth:  screenWidth,
		ScreenHeight: screenHeight,
		TargetTPS:    60,
	}
	a := &arena{}
	mainStage := stage.New(ArenaStage).
		World(world.Config{
			Space: world.SpaceCfg{
				Width:  screenWidth,
				Height: screenHeight,
				Edges:  aabbworld.Torus,
			},
			Entities: world.EntitiesCfg{MaxCount: boxCount, MinSize: boxSize, MaxSize: boxSize},
		}).
		Plugins(a.makePlugins).
		Figures(a.defineFigures).
		Players(a.definePlayer).
		Spawn(a.spawnUnits).
		Scenes(a.defineScenes).
		Shows(ViewScene, telemetry.SceneName).
		Update(a.update)
	gram.Run(game.New(props, mainStage))
}

func (a *arena) makePlugins(w *world.Plugin) {
	a.world = w
	a.motion = motion.NewPlugin(a.world)
	a.collision = collision.NewPlugin(a.world, a.motion).WithStats(&a.stats)
	a.cameras = cameras.NewPlugin(a.world, cameras.Config{})
	a.telemetry = telemetry.NewPlugin(a.world)
	a.players = players.NewPlugin(a.world, a.collision, a.cameras)
}

func (a *arena) definePlayer() error {
	a.player = a.players.Local("player")
	return a.player.Bind(a.players.Defaults()...)
}

func (a *arena) defineFigures() { a.world.Figures(box{}) }

func (a *arena) spawnUnits() {
	boxKind := kind.Named[boxRow](a.world.Kinds(), BoxKind)
	rng := rand.New(rand.NewPCG(1, 2))
	placement := world.NewGridPlacement(screenWidth, screenHeight, boxSize)
	entries := make([]kind.Entry, boxCount)
	for i := range entries {
		var vel world.Velocity
		vel.SetDelta(geom.NewVec(rng.Float32()*200-100, rng.Float32()*200-100))
		entries[i] = boxKind.Entry(boxRow{pos: placement.Place(i, boxCount), vel: vel})
	}
	a.world.Write().Seed(entries...)
}

func (a *arena) defineScenes(ctx game.Initializer) []game.Scene {
	m := &mainScene{arena: a}
	a.telemetry.With(a.stats.Reporter(&ctx.TPS().Ticks))
	return []game.Scene{ui.NewScene(ViewScene, m.screen()).Input(a.players.Handle)}
}

func (a *arena) update(ctx goke.RunCtx, d time.Duration) {
	a.world.RunPlan(ctx, d)
	a.motion.RunPlan(ctx, d)
	a.collision.RunPlan(ctx, d)
	a.cameras.RunPlan(ctx, d)
	a.players.RunPlan(ctx, d)
	ctx.Sync()
}

type mainScene struct {
	arena *arena
}

var (
	boxColor        = color.RGBA{R: 90, G: 200, B: 110, A: 255}
	backgroundColor = color.RGBA{R: 30, G: 30, B: 30, A: 255}
)

func (m *mainScene) screen() *ui.Element {
	a := m.arena
	view := render.NewFeed(a.cameras.New(cameras.FromAbove, camera.Config{}), a.world.Picture())
	return ui.Layers(
		ui.Blank().Fill(backgroundColor),
		ui.Image(view).Input(a.players.Through(a.player)),
	)
}

Demos

examples/motion/collision is the same idea at scale: thousands of colliding boxes at a fixed 120 TPS, saved on F5 and loaded on F9.


Stats: 2306 colliding AABBs | 120 TPS | 50 collisions/tick

Stats: 524 colliding AABBs | 120 TPS | 15 collisions/tick

The demos are grouped by what they show, each group from the simplest to the richest. Every demo opens a window; what it shows is tested in the library's package that does it.

Start: the frame of a game
Demo Shows Run
start/minimal One Stage, one Scene, a world with collisions: the README example make demo-start-minimal
start/scenes A menu Stage switching into a gameplay Stage; a modal panel over the ticking world, open or closed as the game was saved make demo-start-scenes
start/split-screen Two players at one keyboard, each driving its own block through a camera of its own in its half of the screen; a minimap over them make demo-start-split-screen
Look: how entities and the sky are drawn
Demo Shows Run
look/animation A gallery of animations drawn frame after frame from sheets in game time (Shift+P freezes them), each figure labelled: a walker on a patrol stepping the way it goes in eight directions and braking, an idler bored by stages (blinking, stamping, looking about), a puller's hands on a lever, a lever swinging down and up make demo-look-animation
look/material Materials of the game's own WGSL in place of sprites: a ward pulsing on the clock and four embers circling it, drawn out of their own state, breathing standing and streaming a tail driven (WSAD); G calms the ward and F douses the embers into plain sprites for a while make demo-look-material
look/sky A sky of the game's own over a valley in relief, a day in a minute and a half: its own WGSL vault, turquoise by day and violet at night with a band shimmering along the stars' equator, the Earth's moon three times as big and orange, showing by day too, made-up stars; Tab turns to the perspective, Q and E turn it, F lays the stick down to the sky make demo-look-sky
look/light A flat board under a sun of the game's own, circling in a day and a half a minute: a tower's shadow baked into the ground and swinging with the sun, walkers casting soft patches, a hero (WSAD) casting the silhouette of its sprite, a lantern lighting the night and casting their shadows by it (switched on the settings screen, F10), lava that takes no shade make demo-look-light
Rules: states, rules and commands
Demo Shows Run
rules/effect An ice witch turns the ground round her into snow and the lake into ice; it thaws behind her, a walker slips on it, a boat is frozen in, each kind in its own frozen look; F freezes whoever the cursor points at, J hastens the selected for two seconds make demo-rules-effect
rules/mechanisms Three commands, each a sentence saying what it does, whom it is for and who sets it off: a hero walked on WSAD; a lever he walks up to, pulled and pushed back at hand (Space), its colour its position; a plate stood on, a gate flipped (G); zoom by the wheel, = and - make demo-rules-mechanisms
rules/dialog Conversations read from YAML: the traveller greeted by the miller and the smith in a window, the answers changing the host's Regard, shown under it as Friend, Neutral or Enemy make demo-rules-dialog
rules/vision Entities keeping out of each other's way by sight, and a hunter living off the ones that fail make demo-rules-vision
rules/guard Guards on a plan (plan.New): patrol the yard, step aside for whoever blocks them long enough, rest where they arrive, run to the gate while the alarm (A) is on make demo-rules-guard
Board: boards and maps
Demo Shows Run
board/atlas A small flat board drawn from the game's own atlas, the water a material shimmering per pixel, a road laid as a way make demo-board-atlas
board/custom-map A board drawn by a map of the game's own (board.Plugin.WithMap) and walked by a mobility of its own (cell.Mobility): hills rising out of the grass, shaded by how high they lie; the walkers go round the steep and slow down climbing make demo-board-custom-map
board/flat Madeira on the simple map out of cmd/gramap: the island in its colours, rivers and roads as bands, bridges and fords standing on it, a day and the weather going by, a minimap north up make demo-board-flat
board/topography Madeira in relief, its true heights, a cell 333 m: lit by the sun, water running, roads laid as Transport Tycoon lays them, bridges on piers (Shift+B builds one), the ground shaped under the cursor; the camera on a stick turned (Q, E) and leaned (R, F) from straight down to isometric and flatter, orthographic or in perspective (Tab); a minimap turning with it, a click on it taking the camera there; the ground textured from photographs (make demo-board-topography) or painted, the light in bands (make demo-board-topography-ghibli); the hour, the date and the weather in a bar or apart by the corners (make demo-board-topography-widgets) make demo-board-topography
Navigation: units sent across a board
Demo Shows Run
navigation/square Units sent by a right click round a wall and over a river by a bridge, a wagon too wide for it going round by the ford; sight cones that stop at walls and fade in forests, and a hawk that flies over both make demo-navigation-square
navigation/hex The same on a hex board make demo-navigation-hex
navigation/spawn Walkers spawned under the cursor (N) hold their cells at once, the cells held outlined make demo-navigation-spawn
Motion: collisions, shots and gravity
Demo Shows Run
motion/collision Thousands of bouncing boxes of many kinds, hit overlays, telemetry, save and load make demo-motion-collision
motion/expanse A hundred thousand boxes on a torus of about 98 km: the world lives in bands round the camera, the settings screen (F10) shows the sectors by their bands or by what the camera sees and switches the bands off to weigh what they spare; a minimap of the boxes round the camera make demo-motion-expanse
motion/bullet A soldier on WSAD, the camera following him: Space fires a round the way he faces, Shift held and let go throws a grenade the further the longer held, in an arc that lies with a spark and bursts; the shots are the plugin's, the wounds and the fuse rules, effects and a plan make demo-motion-bullet
motion/platformer A hero in a side view under gravity: A and D walk, W jumps, G turns gravity over, a hard landing dazes make demo-motion-platformer

Model

Stage and Scene

A game.Game supplies Props (window, tick rate) and its Stages by name; game.New(props, stages...) is one. A Stage is one self-contained context, a menu or the gameplay, with its own goke ECS built fresh the moment Runtime.SwitchStage enters it: Init installs its plugins, Spawn seeds a fresh game, Loaded stands in for Spawn when the Stage is entered from a save, Update is one tick. A game defines a Stage a section at a time with game/stage, always in the same order; a chain out of order does not compile, a section the game has no use for is left out, and what is defined in the wrong section is refused:

stage.New(MeadowStage).
	World(worldCfg).                                   // the world…
	Plugins(s.makePlugins).                            // …and the plugins the arena makes over it
	Players(s.definePlayer).                           // the players, the plugins' default keys
	Effects(s.defineEffects).                          // the states
	Rules(s.defineRules).                              // the roles and their rules
	Commands(s.defineCommands).                        // what can be asked for
	With(dialog.Conversations(s.defineConversations)). // a plugin's own section, in its place
	Kinds(s.defineCells, s.defineKinds).               // the kinds of cells and of units
	Controls(s.bindKeys).                              // the game's own keys, each a command
	Spawn(s.spawn).                                    // a fresh game, out of its map
	Scenes(s.defineScenes).                            // the scenes and their cameras
	Update(s.update)                                   // the tick; hands back the game.Stage

Saving and loading are the engine's: commands like any other (game.Save, game.Load, game.Enter, game.Quit) bound to keys (F5, F9, Shift+Esc in every game, as the controls screen (K) lists them and F10 opens the settings) or to ui buttons, a Stage entered from its save from any other, a menu's Continue.

A Scene is one thing a Stage can show. Its screen is a ui tree: the world's picture, all its plugins draw, through a camera made beside it, render.NewFeed(s.cameras.New(cameras.FromAbove, camera.Config{}), s.world.Picture()), wired to the player who acts through it, ui.Image(feed).Input(s.players.Through(player)). The Stage's Scenes registry is static; the Composition over it is live: which Scenes are visible, in what order, and which is active, the topmost focusable one and the only one whose HandleEvents runs. Runtime (pause, quit, switch Stage, persistence, full screen) reaches a Stage and every Scene alike.

Plugins, rules and plans

A plugin's Install only queues ECS wiring, flushed in one ecs.Setup after the Stage's Init. What a game does about what a plugin finds is a rule of ceremony, the library of behaviour gram builds on, run in the pass of the plugin that catches its moment:

roles := s.world.Roles()
roles.Define(PreyRole)
roles.Define(PredatorRole, act.Branch[collision.Meeting]{
	Name: "caught",
	When: cond.Other.If(roles.Named(PreyRole)),
	Then: act.Other.Do(world.Despawn{}),
})
kind.Define[body](kinds, HunterKind, kind.Spec{…, ceremony.Plays(roles.Named(PredatorRole))})

reads as a sentence, who, when, what: a predator, meeting one playing prey, has it give itself a Despawn. Every clause says whom it is about: cond.Self the entity, cond.Other the other of the pair or the moment's subject, cond.At(board.Around(n)) the places round, cond.On(s.world) the world's own entity; and in what state, .If(x): under an effect, playing a role, as a word of the moment says (unit.Fallen(), vision.SeesNobody()), cond.Chance(p), cond.Always, or cond.Not of one; clauses join with And and Or. The steps say the same, act.Self.Put(e), act.Other.Do(cmd), act.At(board.Around(1)).Put(e), in order (act.Steps) or the first that does (act.OneOf). Nobody hands the rule to collision: once Init returns, the engine gives the rules of every role somebody plays to the plugin that catches their moment, and a rule none catches is an error. What an entity does over time is a plan of loops, plan.New(name, root), carried by its kind: a plan.Loop is a branch with an end — Until the fact a plugin tells it (cond.Self.If(navigation.Arrived{})), Timeout, Cooldown — choosing what to do (plan.OneOf) or doing one thing after another (plan.Steps). Rules and plans cast effects that hold for a while and give commands for their entity (plan.Self.Do(navigation.MoveTo{…})), the same a player gives. An effect turns the knobs a plugin gives, components it only reads, like steering.Steering or a cell's cell.Ground. A rule holds no Go code but its words; how entities are drawn is the one place rules are Go (world.Rule), declared on the world's atlas in a scene, where a kind's look under an effect is declared too (Slot.Under(effect, look)). A plugin ships no ready-made reactions: it gives moments and their words, and the game says what follows. The language is ceremony's doc/ceremony.md; how a game uses it over gram's plugins is doc/behaviour.md.

What a player wants is a command too, a command.Command (ceremony's): the plugin that defines its type (navigation.MoveTo, selection.Select) is a plugin.CommandHandler that drains its queue in its own pass; the players plugin carries what a player's bindings, an AI or a network issue, the world what the entities give themselves.

Roles and commands

A role is a behaviour an entity plays, mortal, hasty, a plate, not a group: s.world.Roles().Define(name, rules...) fires the rules for those playing it alone. Defining registers and hands nothing back: effects, roles, commands and kinds are defined under a name in the Stage's world and taken back with Named(name) wherever they are built on; a game keeps its names as constants, each with a suffix saying what it names (Ef, Cmd, Role, Plan, Kind, Cell). A kind plays roles through ceremony.Plays(roles...), a cell through its kind or alone, a plugin through its own Plays: a plugin is an entity of the world too (world.Self), so a state of the sky is an effect on the atmosphere, ceremony.Put(bloodMoon).On(s.atmosphere), read back by cond.On(s.atmosphere).If(bloodMoon). A command about an effect is a sentence: put it on (ceremony.Put), take it off (Take) or switch it (Toggle), for the entities bearing a name, those in a group, the world itself, the player's selected units or the one pointed at (On), set off by the entity named (By):

const (
	OpenEf       = "open"
	HasteEf      = "haste"
	MortalRole   = "mortal"
	HastyRole    = "hasty"
	PlateRole    = "plate"
	OpenWestCmd  = "open west"
	OpenEastCmd  = "open east"
	HastenCmd    = "hasten"
	ScoutKind    = "scout"
	TrapdoorKind = "trapdoor"
	PlateKind    = "plate"
)

fx, roles, cmds := s.world.Effects(), s.world.Roles(), s.world.Commands()

// Effects
fx.Define(OpenEf, effect.Spec{effect.Lasts(2 * time.Second),
	effect.Alter(func(f *cell.Floor) { f.Allows = 0 })})
fx.Define(HasteEf, effect.Spec{effect.Lasts(3 * time.Second),
	effect.Alter(func(st *steering.Steering) { st.MaxSpeed *= 2 })})

// Rules
roles.Define(MortalRole, act.Branch[unit.Standing]{
	Name: "fall in",
	When: cond.Self.If(unit.Fallen()),
	Then: act.Self.Do(world.Despawn{}),
})
roles.Define(HastyRole)
roles.Define(PlateRole, act.Branch[collision.Meeting]{
	Name: "press",
	When: cond.Self.If(cond.Always),
	Then: act.Self.Do(ceremony.Trigger{}),
})

// Commands
cmds.Define(OpenWestCmd, ceremony.Put(fx.Named(OpenEf)).On(ceremony.Group("west trapdoors")))
cmds.Define(OpenEastCmd, ceremony.Put(fx.Named(OpenEf)).On(ceremony.Group("east trapdoors")).
	By(ceremony.Named("plate")))
cmds.Define(HastenCmd, ceremony.Put(fx.Named(HasteEf)).
	On(s.selection.Selected(roles.Named(HastyRole))))

// Kinds
units.Define(ScoutKind, land, profile,
	ceremony.Plays(roles.Named(MortalRole), roles.Named(HastyRole)))
standing.Define(TrapdoorKind, comp.Const(cell.Floor{Allows: cell.Land}))
standing.Define(PlateKind, comp.Const(collision.Collider{}),
	ceremony.Plays(roles.Named(PlateRole)))

// Controls
s.player.Bind(
	control.Give(control.KeyPress{Key: control.Key1}, "Pull the west lever",
		cmds.Named(OpenWestCmd)),
	control.Give(control.KeyPress{Key: control.KeyJ}, "Hasten the selected scouts",
		cmds.Named(HastenCmd)))

// Spawn: the map; a row's yaml tags are the file's keys
type unitRow struct {
	Start cell.ID `yaml:"start"`
}
level, _ := s.board.Lay(mapFile, "map.yaml")
board.Spawn[standingRow](level, nil)
board.Spawn[unitRow](level, board.Sides{
	PlayerSide: {players.Give{To: s.player.ID}, selection.Allow{}}})
board:
  entities:
    - {kind: trapdoor, group: west trapdoors, at: [7, 2]}
    - {kind: plate, name: plate, at: [20, 14]}
units:
  - {kind: scout, side: player, start: [3, 14]}

1 opens every trapdoor in the group "west trapdoors" for two seconds under whoever stands there; the plate, met, sets off the command that names it; J hastens the selected scouts. An AI gives them as a key does (players.Issue). examples/rules/mechanisms is the whole program.

Kinds, spawning and saves

kind.Define[Row](world.Kinds(), "name", kind.Spec{...}) says what an entity is: each component comp.Const(v) (the same for all) or comp.Load(func(row Row) T) (read from that entity's row). A unit over a board is defined through board.NewUnits[Row](brd, shape, at), which derives its position and cell from the one point at reads off a row and runs the world's roster, what the plugins in the game bring by default and what they require. What stands still on the board, a lever, a trapdoor, a gate, is a kind of board.NewEntities. Spawn puts entries on the world's roster, or lays the game's map out of a file (board.Plugin.Lay: the board a character a cell, the relief in metres, roads and rivers along paths, the entities and the units, each a kind and the fields of its row tagged yaml); a fresh Stage spawns them, a loaded one does not. Mid-game the command world.Spawn{Entry} adds an entity the same way. Kinds tell save files every component type their entities carry, so a game's own state survives a save without being registered anywhere else.

Maps of the Earth

cmd/gramap makes such a map of any stretch of the Earth at any scale out of a recipe (cmd/gramap/madeira.yaml is Madeira's):

go run ./cmd/gramap -recipe cmd/gramap/madeira.yaml -out examples/board/topography/map.yaml
go run ./cmd/gramap -recipe cmd/gramap/madeira.yaml -out examples/board/flat/map.yaml -flat

The recipe says where, how many cells and how many metres a cell spans, what the ground is by its slope and height, how much drained land makes a brook, a stream and a river, and the roads as chains of named places. The heights come from the Terrain Tiles on AWS, fetched once into the user's cache. The rivers are carved into the ground, the roads routed and graded as Transport Tycoon lays them, with bridges over water and down valleys and fords where a river is shallow; with -flat the map has no heights.

Architecture

The packages form a strict acyclic graph; each imports only the layers below it. Every package has a doc.go describing what it brings. What is left to do is in doc/roadmap.md.

Package Responsibility
camera The contract of a view onto a world: screen conversion, culling, move and zoom, projections, fastening over an entity
control The input vocabulary: Binding, the triggers, Context, Keys, a player's Tool; the commands a binding builds are ceremony/command's
render Drawing: Renderer, the Composer over Sources and its Frame, Direct sources, Feed, Atlas, Font, the drawing rules a renderer runs every frame
plugin The extension contract: Plugin, Installer (with Hosts, the hosts of a plugin's moments), CommandHandler, Serializable, PostLoader, Populator, Made; plugin/section the parts of a Stage
entity What every entity carries: Base, Position, Velocity, Z, Layers, Eye, Lie; entity/kind what an entity is (Spec, Define, Of, the roster)
clock The tactical clock: game time as the sum of the simulation's steps, the pause (Shift+P), the tempo (] and [), the Moment of a step with At and Every
ceremony The library gram builds on, outside the module: how entities behave — cond the conditions, act the steps and the branch of a rule, plan the loops of a plan, effect the states and knobs, fact the facts and messages, roles, commands about effects and labels in its root, host the hosts a plugin runs rules with, command the queues and the carrier, tag and comp; the language in its doc/ceremony.md, how a game uses it over gram's plugins in doc/behaviour.md
plugins/world The foundation: the space under the edge rules, kinds and tags, Seed/Populate, Spawn, Despawn, the commands about effects, the carrier of commands, the entities' looks on the atlas; it runs the core's systems; view beside it
plugins/motion The entities moved: Moving with Still and Braking, Leaving and Outside past an open edge, Drift, UnitTemplate; steering the heading and speed reached gradually
game What a game implements and receives: Game, Stage, Scene, Scenes, Composition, Initializer, Runtime, Persistence; game/stage a Stage defined a section at a time
ui A scene's screen as a tree of elements: Layers, Columns/Rows, anchors, Panel, Label, Image of a feed, Window, Button giving commands, elements pinned to entities Under an effect or On a name, a Theme
plugins/collision Collision over the world's space: Collider, Physics, Sweep, the solid ground of a Field, Meeting and Struck
plugins/vision Sight cones into Sighted, Sighting rules, the views drawn
plugins/board A square or hex grid with terrain over the world: the Board, Layout and Map, NewUnits, NewEntities, a level out of a file (Lay); cell the vocabulary of a cell, unit of a unit on it, grid the topology, look how it is drawn, ground what its ground is to the others, water and network rivers and roads
plugins/atmosphere The sky over a world on the world's clock: calendar, sky, celestial, climate and its weather, air, precipitation, weathering, backdrop
plugins/topography A map in relief drawn on the GPU: the heights, the light and the shadows, the water, the commands shaping the ground, the cameras' cage; relief and painter its vocabulary
plugins/navigation MoveOrder paths across a board, re-routing as terrain changes, on a bridge's deck or under it; MoveTo a cell or an entity by name; a patrol as a plan over the unit's Round (Onward); the crowd as rules over Touch; routes drawn
plugins/driving Units driven by hand: Ahead, Back, Turn, Toward, Jump, Tank and Compass keys
plugins/gravity Bodies falling, standing and leaping: Pull, Body, Leap, Away, Landing
plugins/bridges Bridges: Types of them, a level's, a player's with a Tool in hand; where one may stand in bridges/site
plugins/bullet Shots fired and flown: Shoot, Shots, Flight, Landing, Resting, Burst into Blasts
plugins/selection Select into Selected, Hovered, Selected(roles...) and Pointed() as the targets of commands
plugins/dialog Conversations as data: Nodes from YAML, a unit's Script, the game's Changes and Conditions, Window
plugins/cameras The cameras a game looks through: Config, New, the Cage, Pan, Zoom, Follow, CenterOn, the views' View, Turn, Tilt, Ride, Keys
plugins/players Players over the command handlers: bindings into commands, Through and IssueAs for a ui scene, the list of keys; players/owner whose a unit is
plugins/telemetry The telemetry panel: standard lines, the plugins' reporters and the game's own lines, a scene of its own in every Stage with a world, ~
internal/engine The Engine: the window's loop, one active Stage, saves and loads
gram Run; the package you import. The root doc.go carries the concepts and the full package graph
camera ───► render ──► plugin ──► plugins/world ──► game ──► internal/engine ──► gram
control ────┘  ▲                  │  ▲
ceremony ──────┘                  ▼  │
      plugins/{cameras, collision, selection, vision} ──► plugins/board ──► plugins/driving ──► plugins/navigation
                                                            └──► plugins/{bullet, gravity, bridges, topography, atmosphere} ──► plugins/players

Outside the module: ceremony is the behaviour — rules, plans, effects, roles, commands, facts — which gram's plugins perceive for and carry out, with goke as its store; goke is the ECS every Stage runs on, aabbworld the space, collisions and line of sight under the world, gogpu the window, the loop and the GPU (WebGPU), hpastar the pathfinding.

⏱️ Performance

One tick of the built-in plugins on an Intel i5-8265U (see BENCHMARKS.md), 0 allocs/op throughout once warm, the median of 5 runs at v0.6.0:

Tick Scene Cost
World: move every entity, the space reading them in place 5,000 boxes, 20×20 each, on a 4000×4000 torus 36 µs
World + collisions 524 boxes, 20×20 each, covering 20% of a 1024×1024 torus 124 µs
World + collisions 8,388 boxes, 5×5 each, covering 20% of the same torus 2.7 ms
Vision: every observer scans its cone 500 observers, 60° cones of radius 200 232 µs
Navigation: walkers under orders, in the open / through one gap 1,000 walkers on a 64×64 board 3.0 / 10.5 ms

Deep dive: every scene, what each benchmark measures, and how to reproduce, in BENCHMARKS.md.

make bench

Relationship to goke and aabbworld

gram began as goke's Ebitengine example and was extracted so the ECS stays free of GUI dependencies; it has since left Ebitengine for WebGPU. The world, collisions and line of sight are aabbworld's; gram is where they meet an ECS and a screen.

📖 Documentation

Credits

  • The night sky's stars: the Yale Bright Star Catalogue, 5th revised edition (Hoffleit & Warren 1991), from the CDS, catalogue V/50 (plugins/atmosphere/celestial/stars_gen.go).
  • The moon's face: NASA's Scientific Visualization Studio, CGI Moon Kit (Lunar Reconnaissance Orbiter LROC data) (plugins/atmosphere/celestial/moon.png).
  • The animation demo's lever: "Lever and Button" on OpenGameArt (CC0), its two positions, with two frames between drawn after them (examples/look/animation/lever.png). Its figure (hero.png) is drawn in-house.
  • The heights of Madeira's maps and of every map cmd/gramap makes: the Terrain Tiles on AWS, Mapzen's Tilezen terrarium — SRTM, EU-DEM (Copernicus), GMTED2010, ETOPO1 and others; see their attribution.

License

MIT

Documentation

Overview

Package gram is a modular game engine for Go: a game.Game — named game.Stage values, each with its own entity-component world and its own [game.Scene]s — driven by an engine that runs the goke ECS in a window's loop, a tick and a picture a frame, the picture drawn on the GPU through WebGPU (gogpu). Everything beyond the tick loop is a plugin.Plugin: the built-in ones give a Stage a world of moving boxes, collisions, sight, a board with terrain, pathfinding and mouse selection; a game adds its own the same way. Run is the whole public surface of this package.

Game, Stage and Scene

A Game supplies game.Props (window, tick rate) and its Stages by name. A Stage is one context the game can be in — a menu, the gameplay — with its own ECS, built fresh as game.Runtime.SwitchStage enters it: Init installs its plugins through a game.Initializer, Spawn seeds a fresh game, Loaded stands in for Spawn when the Stage is entered from a save, Update is one tick. A game defines a Stage a section at a time with package game/stage — World, Plugins, Players, Effects, Rules, Commands, Kinds, Controls, Spawn, Scenes, Update — in that order, which the compiler keeps. Saving and loading are commands like any other (game.Save, game.Load, game.Enter, game.Quit), bound to keys or ui buttons.

A Scene is one thing a Stage can show: its renderers and its input handling. The Stage's game.Scenes is the registry of them; the live game.Composition over it says which are visible, in what order, and which is active, the only one whose HandleEvents runs. game.Runtime — pause, quit, switch Stage, persistence, full screen — reaches a Stage and every Scene alike. A scene's screen is a tree of elements of package ui, the world among them as its picture, everything the Stage's plugins draw (world.Read.Picture), through a camera ([ui.Image] of a render.Feed); the cameras are the cameras plugin's, made beside the feed that shows them. A player owns no camera: it acts through the picture a scene wires it to.

Plugins and rules

A plugin.Plugin is used from a Stage's Plugins section. Its Install only queues ECS wiring, flushed in one ecs.Setup after Init returns, and says what the plugin draws (plugin.Installer.Draws, the Stage's one picture of it all ordered by height) and how its kinds look (plugin.Installer.Looks, declared once Init returns, before the scenes are made). A plugin needing another takes it as a constructor argument: there is no registry and no lookup by name.

What a game does about what a plugin finds is a rule of the library ceremony (github.com/kjkrol/ceremony), which gram builds on with goke as the store: act.Branch[P]{Name, When, Then}, run inside the pass of the plugin that catches its moment P — a collision.Meeting for a pair of entities, a unit.Standing for an entity on the board — when its When holds, clauses of ceremony/cond each saying whom they are about (cond.Self.If, cond.Other.If, cond.At(board.Around(n)).If, cond.On(plugin).If), its Then doing steps said of somebody the same way (act.Self.Do, act.Other.Put, act.At(board.Around(n)).Put): putting on and taking off effects, giving commands. A rule is a role's (world.Roles), a role is played by a kind, a cell or a plugin, and once Init returns the engine hands the rules of every role played to the plugin that catches their moment (ceremony.Deliver, to the hosts of plugin.Installer.Hosts); one none catches is an error. What an entity does over time is a plan, plan.New, of loops of the same words, plan.Loop[P]{Name, When, Then, Until, Timeout, Cooldown}, carried by its kind. What somebody asks for is a command (ceremony/command): a player's key, a rule's act.Self.Do, and about an effect a sentence — ceremony.Put(open).On(ceremony.Group("trapdoors")).By(ceremony.Named("lever")). The language is ceremony's own documentation; gram's plugins give the moments, facts, words and knobs it is written over, each marked beside its type, and the world keeps a Stage's registers of effects, roles and commands by name (doc/behaviour.md).

Kinds and spawning

What an entity is comes from a kind (package entity/kind): a Spec of the components every entity of the kind carries, the same for all (Const) or read from that entity's own row (Load). A kind's Entry puts one entity on the world's roster, spawned for a Stage entered afresh; a map file (board.Plugin.Lay) does the same for a board. Kinds also tell the saves which component types to expect.

Tick

Props.TargetTPS is the engine's one fixed step. The window's loop runs one Update per frame, stepping as many times as the time gone says, at most five, so a slow frame slows the game instead of spiralling. Each step calls the active Scene's HandleEvents, then Stage.Update, where the game runs its plugins' RunPlan in the order it needs: the world, then motion, before whatever reads its space. What is drawn goes by the clock's Shown time, which runs on between the steps.

Persistence

game.Persistence saves and loads the active Stage's ECS with every tracked value's state: a plugin's Serializable, or anything a Stage handed to ctx.Track. Resources are matched by name, never by position, so a save survives plugins being added, removed or reordered.

Numbers

Every number of the world's geometry and of the screen is a float32, as aabbworld's boxes and the GPU have them: positions, sizes, speeds, heights, angles, pixels. Whole units are exact up to 2^24, and at 16,384 units off the origin a coordinate steps about a thousandth of a unit.

Package dependencies

The packages form a strict acyclic graph; each imports only layers below it:

0  camera               a camera over a world: conversion, culling, move, zoom
   ceremony             how entities behave (github.com/kjkrol/ceremony): tag, comp,
                        effect, fact, cond, act, plan, host, command, store, its root
                        and goke, its binding over the ECS
1  render               drawing: Composer, Frame, Atlas, Feed     → camera, ceremony/effect
   control              input events and bindings                 → camera, ceremony/command
2  entity/kind          what an entity is: Spec, Define, Of       → render, ceremony/comp
   clock                the tactical clock: time, pause, tempo    → control, render, ceremony
3  entity               what every entity carries: Base, Z        → kind
   plugin               the extension contract                    → control, render, ceremony
   plugins/players/owner whose a unit is; a leaf                  → ceremony/command, tag
4  plugins/world        the foundation: space, entities, kinds    → plugin, clock, ceremony
5  game                 Game, Stage, Scene, Composition, Runtime  → plugin, world, ceremony
   ui                   a scene's screen of elements              → game, render, control
   plugins/motion       entities steered and moved, the leavers   → world
   plugins/vision       what the units see                        → world, …
6  plugins/cameras, collision                                     → world, motion, …
7  plugins/selection    the units a player picks                  → cameras, motion, …
   plugins/board        a grid with terrain over the world        → motion, collision, …
   plugins/dialog       conversations as data                     → world, ui, …
8  plugins/driving      units driven by hand                      → motion, selection, board
9  plugins/navigation   MoveOrder paths across a board            → board, selection, driving
   plugins/bullet       shots fired, flown, landing and bursting  → motion, collision, board
   plugins/gravity      bodies falling, standing and leaping      → motion, board, collision
   plugins/bridges      bridges built by one set of rules         → world, board, …
   plugins/topography   a map in relief drawn on the GPU          → motion, board, atmosphere
   plugins/atmosphere   calendar, climate, weather, sky           → world, board, …
   plugins/players      players over the command handlers         → motion, cameras, ui, …
10 internal/engine      the Engine: the loop, one Stage, saves    → game, world, ceremony
11 gram                 Run; the package you import               → game, internal/engine

Outside the module: ceremony is the behaviour — rules, plans, effects, roles, commands, facts — the layer under plugin and control, its store goke/v3 through its binding ceremony/goke (the only package of it importing goke, imported in gram as cgoke); goke/v3 is the ECS every Stage runs on, aabbworld the space, collisions and line of sight under the world, gogpu the window, the loop and the GPU, hpastar the pathfinding, and uid the entity identifiers.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Run

func Run(g game.Game)

Run launches a Game

Types

This section is empty.

Directories

Path Synopsis
Package camera is the view onto a world: screen conversion, culling, the visible window and its control.
Package camera is the view onto a world: screen conversion, culling, the visible window and its control.
Package clock is the tactical clock of a world: the one game time everything that simulates goes by, kept by the world and saved with the game.
Package clock is the tactical clock of a world: the one game time everything that simulates goes by, kept by the world and saved with the game.
cmd
gramap command
Command gramap makes a gram map, a level file a board lays, of any stretch of the Earth at any scale, from a recipe:
Command gramap makes a gram map, a level file a board lays, of any stretch of the Earth at any scale, from a recipe:
Package control is the input vocabulary: what the engine captures each frame, and the commands and bindings a game is driven by.
Package control is the input vocabulary: what the engine captures each frame, and the commands and bindings a game is driven by.
Package entity is what every entity of a world carries: its Base (where it is, Position; how it moves, Velocity; its kind and what the space may do with it), its planes (Layers), in a world with heights its place in height (Z), where it looks from (Eye), the Drift it is carried at under gravity, how it lies flat (Lie) and how it casts its shadow ([Shadow]).
Package entity is what every entity of a world carries: its Base (where it is, Position; how it moves, Velocity; its kind and what the space may do with it), its planes (Layers), in a world with heights its place in height (Z), where it looks from (Eye), the Drift it is carried at under gravity, how it lies flat (Lie) and how it casts its shadow ([Shadow]).
kind
Package kind is how a game says what its entities are.
Package kind is how a game says what its entities are.
examples
board/atlas command
board/flat command
board/topography/hud
Package hud lays out the demo's screen.
Package hud lays out the demo's screen.
look/animation command
look/light command
look/material command
look/sky command
motion/bullet command
motion/expanse command
navigation/hex command
rules/dialog command
rules/effect command
rules/guard command
rules/vision command
start/minimal command
start/scenes command
Package game is what a game implements and what it is handed back: the Game the engine drives, its [Stage]s and their [Scene]s, and the Initializer, Runtime and Persistence a Stage or Scene works through.
Package game is what a game implements and what it is handed back: the Game the engine drives, its [Stage]s and their [Scene]s, and the Initializer, Runtime and Persistence a Stage or Scene works through.
stage
Package stage defines a game.Stage a section at a time, always in the same order: a chain begun with New and ended with Update, each link one part of the game and nothing else.
Package stage defines a game.Stage a section at a time, always in the same order: a chain begun with New and ended with Update, each link one part of the game and nothing else.
internal
engine
Package engine is the driver behind gram.Run: the window's loop (gogpu), one active Stage and its ECS at a time, and the unexported implementations of the contracts package game declares.
Package engine is the driver behind gram.Run: the window's loop (gogpu), one active Stage and its ECS at a time, and the unexported implementations of the contracts package game declares.
f32
Package f32 is package math for the float32 geometry gram keeps: each function is math's of the same name, worked out in float64 and rounded once.
Package f32 is package math for the float32 geometry gram keeps: each function is math's of the same name, worked out in float64 and rounded once.
parallel
Package parallel shares a job of many tasks among the goroutines of a pool kept for the whole game: the caller's own and the pool's, each known by its number.
Package parallel shares a job of many tasks among the goroutines of a pool kept for the whole game: the caller's own and the pool's, each known by its number.
vec
Package vec is the three-float vectors the cameras and the billboards work with.
Package vec is the three-float vectors the cameras and the billboards work with.
Package plugin is the extension contract: what a Plugin is, what it is handed at install time, and how a game's rules are hosted inside a plugin's own pass.
Package plugin is the extension contract: what a Plugin is, what it is handed at install time, and how a game's rules are hosted inside a plugin's own pass.
section
Package section names the parts a Stage is defined in, in their order, and lets a plugin refuse what is defined in the wrong one.
Package section names the parts a Stage is defined in, in their order, and lets a plugin refuse what is defined in the wrong one.
plugins
atmosphere
Package atmosphere is the sky over a world on the world's clock: the calendar, the light of the day, the climate and its weather, what falls, and what the weather does to the ground.
Package atmosphere is the sky over a world on the world's clock: the calendar, the light of the day, the climate and its weather, what falls, and what the weather does to the ground.
atmosphere/air
Package air is the weather over a world as it is felt and drawn: the Weather the climate makes, and what it does to what is drawn.
Package air is the weather over a world as it is felt and drawn: the Weather the climate makes, and what it does to what is drawn.
atmosphere/aloft
Package aloft draws the clouds seen from above: a layer the sky shows from below, the heaps as bodies the line of sight passes through, lit from above, the shreds as thin sheets at their heights, half see-through over their shadows, thinning away into the ground; and the heaps seen from under their top before the slopes that stand up into them.
Package aloft draws the clouds seen from above: a layer the sky shows from below, the heaps as bodies the line of sight passes through, lit from above, the shreds as thin sheets at their heights, half see-through over their shadows, thinning away into the ground; and the heaps seen from under their top before the slopes that stand up into them.
atmosphere/backdrop
Package backdrop is the sky behind the world, drawn on the GPU before anything else: through a perspective the sky of the day with the sun, the moon, the stars and the clouds on it; through any other camera the viewport filled in the sky's colour wherever the ground does not cover it.
Package backdrop is the sky behind the world, drawn on the GPU before anything else: through a perspective the sky of the day with the sun, the moon, the stars and the clouds on it; through any other camera the viewport filled in the sky's colour wherever the ground does not cover it.
atmosphere/calendar
Package calendar turns the tactical clock's game time into days, seasons and the moon.
Package calendar turns the tactical clock's game time into days, seasons and the moon.
atmosphere/celestial
Package celestial is the celestial sphere over a world: where the sun, the moon and the stars stand as the world turns, and the real stars and the moon's face to draw them with.
Package celestial is the celestial sphere over a world: where the sun, the moon and the stars stand as the world turns, and the real stars and the moon's face to draw them with.
atmosphere/climate
Package climate is the climate of a world: where in the world it lies, and the weather that goes by there.
Package climate is the climate of a world: where in the world it lies, and the weather that goes by there.
atmosphere/climate/weather
Package weather is the kinds of weather a climate goes through, each a State.
Package weather is the kinds of weather a climate goes through, each a State.
atmosphere/precipitation
Package precipitation draws what falls from the world's weather: rain and snow, drop by drop between the low clouds and the ground, only under the clouds it falls from and as thick as they let fall (air.Weather.FallsAt), in the light of the sun.
Package precipitation draws what falls from the world's weather: rain and snow, drop by drop between the low clouds and the ground, only under the clouds it falls from and as thick as they let fall (air.Weather.FallsAt), in the light of the sun.
atmosphere/sky
Package sky is the light of the day over a world: the sun (a light.Distant; DefaultSun without a sky) and the moon of the calendar's hour.
Package sky is the light of the day over a world: the sun (a light.Distant; DefaultSun without a sky) and the moon of the calendar's hour.
atmosphere/weathering
Package weathering is the weather on the board: snow lying, ice on the water, what sways swaying, as effects on the board's cells cast as the world's weather says and taken off again.
Package weathering is the weather on the board: snow lying, ice on the water, what sways swaying, as effects on the board's cells cast as the world's weather says and taken off again.
board
Package board lays a square or hex grid over the game world, with per-cell terrain (who may pass, how fast one goes) and occupancy.
Package board lays a square or hex grid over the game world, with per-cell terrain (who may pass, how fast one goes) and occupancy.
board/cell
Package cell is a board's cell as a place: what it is, who may stand on it, what runs across it and the moment of it rules are written for.
Package cell is a board's cell as a place: what it is, who may stand on it, what runs across it and the moment of it rules are written for.
board/grid
Package grid is a board's topology: a Grid answers which cells neighbour which and in which direction, where a cell lies, how far apart two are, which cells a box covers and every cell in turn; DefaultGrids makes a square or a hex one.
Package grid is a board's topology: a Grid answers which cells neighbour which and in which direction, where a cell lies, how far apart two are, which cells a box covers and every cell in turn; DefaultGrids makes a square or a hex one.
board/ground
Package ground is what a board's ground is to the other plugins: the height of it at a point (Heights; a Profile knows it along a ray exactly), what stands on it and holds sight back (Cover, walked along a ray) and where whoever moves over it stands (Surfaces: the ground or a deck, and the deck over it).
Package ground is what a board's ground is to the other plugins: the height of it at a point (Heights; a Profile knows it along a ray exactly), what stands on it and holds sight back (Cover, walked along a ray) and where whoever moves over it stands (Surfaces: the ground or a deck, and the deck over it).
board/internal/boardtest
Package boardtest is what the board's tests share: an installer without an engine, a world of world, collision, board and vision ticked as a demo ticks them, the rows of its units, a game of one stage.
Package boardtest is what the board's tests share: an installer without an engine, a world of world, collision, board and vision ticked as a demo ticks them, the rows of its units, a game of one stage.
board/internal/draw
Package draw is what the board draws by itself: the simple map's Bands, the ways and the covers the tile map lays over the tiles, and the Clouds' shadows on a flat board's ground under an atmosphere.
Package draw is what the board draws by itself: the simple map's Bands, the ways and the covers the tile map lays over the tiles, and the Clouds' shadows on a flat board's ground under an atmosphere.
board/internal/field
Package field is a board's ground as the other plugins meet it: the cover that holds sight back along a ray (ground.Cover), kept as the cells change, and the solid ground collision pushes colliders out of and never over (collision.Field), read from the cells' terrain.
Package field is a board's ground as the other plugins meet it: the cover that holds sight back along a ray (ground.Cover), kept as the cells change, and the solid ground collision pushes colliders out of and never over (collision.Field), read from the cells' terrain.
board/internal/grids
Package grids is the board's default grids, square and hex, with what the board's own parts read of them: the fields, Fold, SetWrap.
Package grids is the board's default grids, square and hex, with what the board's own parts read of them: the fields, Fold, SetWrap.
board/internal/moments
Package moments runs the board's passes over its units and cells: Rules hosts the rules of a unit.Standing and of a cell.Now and runs them every step, telling each which cells lie round it (AroundPlaces) and, a unit, in front of it (AheadPlaces).
Package moments runs the board's passes over its units and cells: Rules hosts the rules of a unit.Standing and of a cell.Now and runs them every step, telling each which cells lie round it (AroundPlaces) and, a unit, in front of it (AheadPlaces).
board/internal/occupancy
Package occupancy keeps a board's cell.Occupancy true to the world: KeepSystem has every unit hold the cell it stands on, following it wherever it goes, and lets go of the holds of whoever left the world; View draws the cells held.
Package occupancy keeps a board's cell.Occupancy true to the world: KeepSystem has every unit hold the cell it stands on, following it wherever it goes, and lets go of the holds of whoever left the world; View draws the cells held.
board/internal/terrain
Package terrain is the state of a board's cells every part of the board reads: a seed until the ECS is set up, then the cells' entities, with the counts of changes to them and the dictionary of the kinds a game defined (Kinds).
Package terrain is the state of a board's cells every part of the board reads: a seed until the ECS is set up, then the cells' entities, with the counts of changes to them and the dictionary of the kinds a game defined (Kinds).
board/look
Package look is how a board is drawn.
Package look is how a board is drawn.
board/network
Package network is what runs from cell to cell across a board, rivers and roads, as a graph over its grid: the cells it runs through (Network.Set, a Node of a board kind, a width and a fade) and which neighbours each runs on to; a road [Network.Link]s its cells both ways, water [Network.Flow]s down to where it leaves the network.
Package network is what runs from cell to cell across a board, rivers and roads, as a graph over its grid: the cells it runs through (Network.Set, a Node of a board kind, a width and a fade) and which neighbours each runs on to; a road [Network.Link]s its cells both ways, water [Network.Flow]s down to where it leaves the network.
board/unit
Package unit is an entity on a board: the cell it is At, how it moves over the cells and what it weighs (a Mover) and where it stands at a step as a rule gets it (Standing, with its Heading, so a rule's board.Ahead(n) turns to the cells in front of it; its words Fallen where its domain may not be, StandingOn a cell under an effect, OnKind a cell of a kind).
Package unit is an entity on a board: the cell it is At, how it moves over the cells and what it weighs (a Mover) and where it stands at a step as a rule gets it (Standing, with its Heading, so a rule's board.Ahead(n) turns to the cells in front of it; its words Fallen where its domain may not be, StandingOn a cell under an effect, OnKind a cell of a kind).
board/water
Package water works out the running water of a relief: where the rain on it gathers and runs to the sea, the brooks, streams and rivers it makes, the channels they cut and the fords across them.
Package water works out the running water of a relief: where the rain on it gathers and runs to the sea, the brooks, streams and rivers it makes, the channels they cut and the fords across them.
bridges
Package bridges builds bridges by one set of rules, package site's, whoever builds them: a level's file, a player with a bridge in hand, a map maker.
Package bridges builds bridges by one set of rules, package site's, whoever builds them: a level's file, a player with a bridge in hand, a map maker.
bridges/site
Package site is where a bridge may stand: Plan a bridge from one head to another over a Ground under the Rules, or say why not (Refusal).
Package site is where a bridge may stand: Plan a bridge from one head to another over a Ground under the Rules, or say why not (Refusal).
bullet
Package bullet fires shots and flies them: entities of the world a Shoot spawns at a unit's muzzle, flown every step past the world's step cap and swept by collision, so what lies on the path is struck.
Package bullet fires shots and flies them: entities of the world a Shoot spawns at a unit's muzzle, flown every step past the world's step cap and swept by collision, so what lies on the path is struck.
cameras
Package cameras makes the cameras a game looks at its world through and moves them: from above over any world, and over a world in relief on a stick, turned and leaned, orthographically or in perspective, riding with an entity.
Package cameras makes the cameras a game looks at its world through and moves them: from above over any world, and over a world in relief on a stick, turned and leaned, orthographically or in perspective, riding with an entity.
cameras/cameratest
Package cameratest is the cameras plugin's cameras for tests: one from above to draw or cull through when the camera itself is not under test, and a relief camera's keys.
Package cameratest is the cameras plugin's cameras for tests: one from above to draw or cull through when the camera itself is not under test, and a relief camera's keys.
cameras/internal/stick
Package stick is the cameras plugin's views of a world in relief: a camera on a stick, seen through orthographically or in perspective, an eye riding in a unit, and their control.
Package stick is the cameras plugin's views of a world in relief: a camera on a stick, seen through orthographically or in perspective, an eye riding in a unit, and their control.
cameras/internal/topdown
Package topdown holds the cameras plugin's camera from above behind the camera.Camera contract, with its window arithmetic and wrapping.
Package topdown holds the cameras plugin's camera from above behind the camera.Camera contract, with its window arithmetic and wrapping.
collision
Package collision detects overlaps between world entities each tick and records what each struck on its Collider.
Package collision detects overlaps between world entities each tick and records what each struck on its Collider.
collision/internal/collisiontest
Package collisiontest is what the collision's tests share: an installer and a world with motion and collision, stepped as a game steps it.
Package collisiontest is what the collision's tests share: an installer and a world with motion and collision, stepped as a game steps it.
collision/internal/response
Package response is how the collision answers a contact, on numbers alone: the impulse two sides trade along the contact's normal (Exchange) and the footing that keeps a side pushed apart off ground that does not take it (Footing, Worse).
Package response is how the collision answers a contact, on numbers alone: the impulse two sides trade along the contact's normal (Exchange) and the footing that keeps a side pushed apart off ground that does not take it (Footing, Worse).
dialog
Package dialog is conversations written as data: nodes of lines and answers a Stage loads from YAML files, held by its entities and answered by a player through a window pinned to the speaker.
Package dialog is conversations written as data: nodes of lines and answers a Stage loads from YAML files, held by its entities and answered by a player through a window pinned to the speaker.
driving
Package driving drives units by hand: a player's keys, or an entity's own commands, walk, turn, strafe, brake and back a unit away, leap, and fly one that flies.
Package driving drives units by hand: a player's keys, or an entity's own commands, walk, turn, strafe, brake and back a unit away, leap, and fly one that flies.
gravity
Package gravity has bodies fall, stand on what bears them and leap: a character's controller, never rigid bodies.
Package gravity has bodies fall, stand on what bears them and leap: a character's controller, never rigid bodies.
gravity/internal/planar
Package planar is a body's fall across the plane, a platformer's: the pull any way across it, the body borne by whatever collision found it touching against the pull.
Package planar is a body's fall across the plane, a platformer's: the pull any way across it, the body borne by whatever collision found it touching against the pull.
gravity/internal/vertical
Package vertical is a body's fall along Z: a step of the pull along the vertical between the surface under its feet and the slab over its head.
Package vertical is a body's fall along Z: a step of the pull along the vertical between the surface under its feet and the slab over its head.
light
Package light declares the light over a world: a distant light (the sun) and the lamps, how each thing casts its shadow and what shade it takes.
Package light declares the light over a world: a distant light (the sun) and the lamps, how each thing casts its shadow and what shade it takes.
minimap
Package minimap brings minimaps: small pictures of the world round a player's camera, of the ground in miniature and the marks of the kinds that have one, the camera's view outlined on it; a click on one takes the camera there.
Package minimap brings minimaps: small pictures of the world round a player's camera, of the ground in miniature and the marks of the kinds that have one, the camera's view outlined on it; a click on one takes the camera there.
motion
Package motion moves the world's entities: every step it steers them, runs the rules of a Moving over them, moves each by its velocity, never further than Position.MaxStep, and deals with those gone past an open edge.
Package motion moves the world's entities: every step it steers them, runs the rules of a Moving over them, moves each by its velocity, never further than Position.MaxStep, and deals with those gone past an open edge.
motion/internal/motiontest
Package motiontest is what motion's tests share: an installer and a world with motion, stepped as a game steps it.
Package motiontest is what motion's tests share: an installer and a world with motion, stepped as a game steps it.
motion/steering
Package steering turns what an entity wants into motion, gradually.
Package steering turns what an entity wants into motion, gradually.
navigation
Package navigation moves entities along a MoveOrder's path across a board, re-pathing when the ground along the route changes, and carries out MoveTo commands for Selected entities.
Package navigation moves entities along a MoveOrder's path across a board, re-pathing when the ground along the route changes, and carries out MoveTo commands for Selected entities.
navigation/internal/bodies
Package bodies is the units of a tick of navigation: each as a Member of the tick and as a Body the others meet, and an Index of the bodies by the cells their boxes touch.
Package bodies is the units of a tick of navigation: each as a Member of the tick and as a Body the others meet, and an Index of the bodies by the cells their boxes touch.
navigation/internal/order
Package order is the order a navigated unit carries — its MoveOrder, Goals, Path and Leg — the commands that give and change it, and the facts and moments told about it; the order's working functions are the systems' alone.
Package order is the order a navigated unit carries — its MoveOrder, Goals, Path and Leg — the commands that give and change it, and the facts and moments told about it; the order's working functions are the systems' alone.
navigation/internal/pathfind
Package pathfind finds routes over a board's grid for the navigation: the cheapest way from cell to cell for an entity moving in a domain, round what may not be entered, what is held and what the caller says is blocked, and the nearest free cell to a taken one.
Package pathfind finds routes over a board's grid for the navigation: the cheapest way from cell to cell for an entity moving in a domain, round what may not be entered, what is held and what the caller says is blocked, and the nearest free cell to a taken one.
navigation/internal/routes
Package routes draws the navigation's routes and goals (Renderer), on the GPU in a world with heights: stretches laid over the ground the frame drew (Lines), lying at the ground's depth, under what stands on it.
Package routes draws the navigation's routes and goals (Renderer), on the GPU in a world with heights: stretches laid over the ground the frame drew (Lines), lying at the ground's depth, under what stands on it.
navigation/internal/routing
Package routing plans where the units go: the System carrying out the commands that send them, each an order with its route.
Package routing plans where the units go: the System carrying out the commands that send them, each an order with its route.
navigation/internal/spacing
Package spacing is how units keep out of each other's way: a Keeping for each Spacing, a cell to a unit (CellKeeping) or boxes kept apart (BodyKeeping), the spots a group stands on, and the board's Finder of routes they plan with.
Package spacing is how units keep out of each other's way: a Keeping for each Spacing, a cell to a unit (CellKeeping) or boxes kept apart (BodyKeeping), the spots a group stands on, and the board's Finder of routes they plan with.
navigation/internal/traffic
Package traffic moves the units along their routes: the System stepping each from cell to cell, holding its steps, turning it and handing the crowd's rules the touches among them.
Package traffic moves the units along their routes: the System stepping each from cell to cell, holding its steps, turning it and handing the crowd's rules the touches among them.
players
Package players is whoever acts in the game: a Player acting through a picture of the world a scene wires it to and, at this keyboard, the bindings that turn its input into commands, carried to the plugin that defined each one.
Package players is whoever acts in the game: a Player acting through a picture of the world a scene wires it to and, at this keyboard, the bindings that turn its input into commands, carried to the plugin that defined each one.
players/owner
Package owner is whose an entity is: a tag of the Family a player (Of), saved by its Name, carried by every entity the player owns.
Package owner is whose an entity is: a tag of the Family a player (Of), saved by its Name, carried by every entity the player owns.
selection
Package selection turns Select commands into a Selected tag on Selectable world entities.
Package selection turns Select commands into a Selected tag on Selectable world entities.
telemetry
Package telemetry is the panel in the top-left corner saying how the game runs: the frame rate, the ticks a second, where a frame's time goes, the entities, the game time, and whatever the plugins and the game add.
Package telemetry is the panel in the top-left corner saying how the game runs: the frame rate, the ticks a second, where a frame's time goes, the entities, the game time, and whatever the plugins and the game add.
topography
Package topography is a map in relief over a board: the ground's heights, the light and the water on them, drawn on the GPU.
Package topography is a map in relief over a board: the ground's heights, the light and the water on them, drawn on the GPU.
topography/internal/billboards
Package billboards is how the world's entities look on a map in relief, drawn on the GPU: in the views in relief they stand as billboards upright in the world on their centres at their altitudes, as tall on the screen as their Height stands there, hidden by the ground where it stands before them; from above they lie over their boxes as the world's own flat look draws them.
Package billboards is how the world's entities look on a map in relief, drawn on the GPU: in the views in relief they stand as billboards upright in the world on their centres at their altitudes, as tall on the screen as their Height stands there, hidden by the ground where it stands before them; from above they lie over their boxes as the world's own flat look draws them.
topography/internal/hexes
Package hexes is the ground of a hex board in relief drawn on the GPU: every cell a prism standing to its top, coloured from the board's tiles and ways drawn from above, lit by the sun and hazed as the terrain is.
Package hexes is the ground of a hex board in relief drawn on the GPU: every cell a prism standing to its top, coloured from the board's tiles and ways drawn from above, lit by the sun and hazed as the terrain is.
topography/internal/painter
Package painter is the topography's painter: the board's Dressing in relief and the board painted flat for the ground drawn on the GPU.
Package painter is the topography's painter: the board's Dressing in relief and the board painted flat for the ground drawn on the GPU.
topography/internal/relief
Package relief is the ground's heights under a board: how high every corner stands, the ground between them, how steep a step is, how it is shaped, and the heights saved with the game.
Package relief is the ground's heights under a board: how high every corner stands, the ground between them, how steep a step is, how it is shaped, and the heights saved with the game.
topography/internal/terrain
Package terrain draws a relief on the GPU as a mesh, every lattice corner a vertex at its height, in place of the board's tiles: a Renderer (New) is a render.Direct source in the opaque pass over a Ground (the relief), looking as its Surface says (Painted: the board painted flat, its water, the shores, the grid) under a Sky, lit by the sun and the lamps the frame holds and shaded as the light baked it (render.GroundShade).
Package terrain draws a relief on the GPU as a mesh, every lattice corner a vertex at its height, in place of the board's tiles: a Renderer (New) is a render.Direct source in the opaque pass over a Ground (the relief), looking as its Surface says (Painted: the board painted flat, its water, the shores, the grid) under a Sky, lit by the sun and the lamps the frame holds and shaded as the light baked it (render.GroundShade).
topography/internal/topotest
Package topotest is what the topography's tests share: an installer without an engine, a world with heights over a board in relief, a level island seen isometrically.
Package topotest is what the topography's tests share: an installer without an engine, a world with heights over a board in relief, a level island seen isometrically.
topography/internal/water
Package water is the topography's water as its shaders draw it: the materials of the sea (Glint) and of running water (Stream), registered with the composer's library; the way to the shore from a point of water (Shore, Shores); how fast water runs (Flow); and the layers the water is painted in for the ground drawn on the GPU (Layers, FlowSpan).
Package water is the topography's water as its shaders draw it: the materials of the sea (Glint) and of running water (Stream), registered with the composer's library; the way to the shore from a point of water (Shore, Shores); how fast water runs (Flow); and the layers the water is painted in for the ground drawn on the GPU (Layers, FlowSpan).
topography/painter
Package painter is what a game says of how its kinds look in relief beyond their sprites: a Style for each kind's name, with its Detail, the texture over its cells, and a Shading of the light over them all, given to the topography.
Package painter is what a game says of how its kinds look in relief beyond their sprites: a Style for each kind's name, with its Detail, the texture over its cells, and a Shading of the light over them all, given to the topography.
vision
Package vision gives entities a narrowed view of the world: a Sight cone sees what falls inside it, within range and not hidden behind something nearer.
Package vision gives entities a narrowed view of the world: a Sight cone sees what falls inside it, within range and not hidden behind something nearer.
world
Package world is the foundation for a Stage with drawable entities: a Position and Velocity each and a shared spatial index other plugins query; the motion plugin moves them.
Package world is the foundation for a Stage with drawable entities: a Position and Velocity each and a shared spatial index other plugins query; the motion plugin moves them.
world/internal/kinds
Package kinds is the world's register of kinds and tags, the names a save keeps and the remapping of a load to this build's order.
Package kinds is the world's register of kinds and tags, the names a save keeps and the remapping of a load to this build's order.
world/internal/look
Package look is the world's own look: seen from above, each entity's sprite over its box.
Package look is the world's own look: seen from above, each entity's sprite over its box.
world/internal/sectorview
Package sectorview lays the world's sectors over the ground a frame drew, on the GPU, each in its colour (Ground), lying at the ground's depth, under what stands on it.
Package sectorview lays the world's sectors over the ground a frame drew, on the GPU, each in its colour (Ground), lying at the ground's depth, under what stands on it.
world/sector
Package sector is the world cut into sectors and the bands of pace they lie in round the anchors, the points the players observe.
Package sector is the world cut into sectors and the bands of pace they lie in round the anchors, the points the players observe.
world/view
Package view is what one pair of eyes sees of a world.
Package view is what one pair of eyes sees of a world.
Package render is the drawing side of gram, knowing nothing of Stages, Scenes or plugins: what a Scene and a plugin draw with.
Package render is the drawing side of gram, knowing nothing of Stages, Scenes or plugins: what a Scene and a plugin draw with.
gputest
Package gputest readies the GPU for a test that draws.
Package gputest readies the GPU for a test that draws.
internal/atlas
Package atlas is sprites painted on the CPU, each on a Canvas, laid out on one sheet and baked to the GPU.
Package atlas is sprites painted on the CPU, each on a Canvas, laid out on one sheet and baked to the GPU.
internal/compose
Package compose is the world's picture: Sources hand their pieces to a Frame where they lie (At); the Composer draws the opaque ground, then the rest back to front against the depth, the Direct sources in the passes they ask for, then the marks.
Package compose is the world's picture: Sources hand their pieces to a Frame where they lie (At); the Composer draws the opaque ground, then the rest back to front against the depth, the Direct sources in the passes they ask for, then the marks.
internal/feed
Package feed is the world seen through a camera at a size: a Picture drawn whole, in layers from one composition (Laid) or with its figures sharp over its ground.
Package feed is the world seen through a camera at a size: a Picture drawn whole, in layers from one composition (Laid) or with its figures sharp over its ground.
internal/gfx
Package gfx is what draws straight into an image on the GPU: images and their depths, meshes and shaders built on the materials, the 2D fills and the soft blit, and the sprite sheet a frame draws from.
Package gfx is what draws straight into an image on the GPU: images and their depths, meshes and shaders built on the materials, the 2D fills and the soft blit, and the sprite sheet a frame draws from.
internal/gpu
Package gpu draws for render on WebGPU (gogpu/wgpu): textures images live in, programs drawing triangles into them with a fragment written in WGSL, and the frame's commands, gathered and submitted at once.
Package gpu draws for render on WebGPU (gogpu/wgpu): textures images live in, programs drawing triangles into them with a fragment written in WGSL, and the frame's commands, gathered and submitted at once.
internal/instanced
Package instanced is the sprites a Direct source draws on the GPU as instances, by layer or in the order they came.
Package instanced is the sprites a Direct source draws on the GPU as instances, by layer or in the order they came.
internal/light
Package light is how render lights a scene: the distant light and the lamps, the light on what is drawn, and the shadows cast.
Package light is how render lights a scene: the distant light and the lamps, the light on what is drawn, and the shadows cast.
internal/text
Package text is fonts, their glyphs drawn on demand into a sheet of their own, and the fixed debug text.
Package text is fonts, their glyphs drawn on demand into a sheet of their own, and the fixed debug text.
internal/wgsl
Package wgsl is what every shader built on the materials shares: the library's WGSL and uniforms, the materials registered and the frame's images, sealed once a shader is built on them.
Package wgsl is what every shader built on the materials shares: the library's WGSL and uniforms, the materials registered and the frame's images, sealed once a shader is built on them.
Package ui composes a scene's screen out of elements: panels, labels, windows, buttons and pictures of the world, laid out in a tree.
Package ui composes a scene's screen out of elements: panels, labels, windows, buttons and pictures of the world, laid out in a tree.

Jump to

Keyboard shortcuts

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