core

package
v0.3.28 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package core contains platform-agnostic game engine logic. This file defines the Camera — the scene's viewport into the world.

Package core contains platform-agnostic game engine logic. This file defines the Component system - the building blocks of game objects.

Package core contains platform-agnostic game engine logic. This file defines the main Game engine and its lifecycle.

Package core contains platform-agnostic game engine logic. This file defines the event system for inter-component communication.

Package core contains platform-agnostic game engine logic. This file defines the interfaces that platform-specific implementations must satisfy.

Package core contains platform-agnostic game engine logic. This file defines the Object system - the fundamental entity in the game world.

Package core contains platform-agnostic game engine logic. This file defines the Scene system - a container for game objects.

Package core contains platform-agnostic game engine logic. This file defines the named style (theme) system backed by styles.imge.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DrawNineSlice added in v0.3.21

func DrawNineSlice(r Renderer, textureID string, border math.Border, dst math.Rect)

DrawNineSlice draws textureID as a nine-sliced image filling dst, using border (in texture pixels) to split it into corner/edge/center regions so the corners keep their natural size while the center and edges stretch. A zero border means the whole texture stretches to fill dst.

dst is in the current draw space (world or screen), so call it after setting the camera appropriately. This is the shared 9-slice routine used by UI components (@Panel, @Button, @TextInput) and available to any custom component or world object that wants a sliceable image.

func DrawNineSliceTransform added in v0.3.21

func DrawNineSliceTransform(r Renderer, textureID string, border math.Border, dst math.Rect, transform math.ColorTransform)

DrawNineSliceTransform is DrawNineSlice with a color transform applied to every slice, so callers can tint the whole nine-slice (e.g. a button state tint) in a single call. An identity transform is a plain draw.

func GetAllFrom added in v0.3.4

func GetAllFrom[T Component](obj *Object) []T

GetAllFrom returns every component of type T attached to obj, in insertion order. Returns nil if obj is nil or has no component of that type.

func GetFrom added in v0.3.4

func GetFrom[T Component](obj *Object) T

GetFrom returns the first component of type T attached to obj, in insertion order. It lets a component reach a sibling component's methods directly:

if collider := core.GetFrom[*Collider](owner); collider != nil { ... }

It returns the zero value of T (a nil pointer for pointer types) when obj is nil or has no component of that type.

func GetFromNamed added in v0.3.4

func GetFromNamed[T Component](obj *Object, name string) T

GetFromNamed returns the component of type T attached to obj with the given name, or the zero value of T if no such component exists (or it is of a different type). Unlike GetFrom, this is a direct O(1) name lookup and ignores insertion order.

func IsComponentRegistered

func IsComponentRegistered(kind string) bool

IsComponentRegistered checks if a component kind is registered.

func LoadStyles added in v0.3.22

func LoadStyles(data []byte) error

LoadStyles parses a styles.imge file's bytes and installs them as the active style sheet. Styles are keyed by component kind (e.g. "@Button", "@Panel", or a custom component's kind), then by style name:

{
  "@Button": { "primary": { "color": "#2e7d32" } },
  "@Panel":  { "window":  { "color": "#14141e", "outline_color": "#3b3b4d" } }
}

A later LoadStyles replaces the previous sheet.

func LoadStylesFromFS added in v0.3.22

func LoadStylesFromFS(fsys fs.FS, path string) error

LoadStylesFromFS reads and installs a styles.imge file from the given filesystem (used by web builds where game data is embedded rather than on disk).

func LoadStylesFromFile added in v0.3.22

func LoadStylesFromFile(path string) error

LoadStylesFromFile reads and installs a styles.imge file from disk.

func RegisterComponent

func RegisterComponent(kind string, factory ComponentFactory)

RegisterComponent registers a component factory. This is called automatically by the generated components/registry.go for every component in the project, so user component files do not need an init() of their own.

func ResolveComponentKind

func ResolveComponentKind(kind string) string

ResolveComponentKind resolves a component kind string. If kind starts with '@', it's a built-in component. Currently returns the kind as-is (registration handles mapping).

func UnregisterComponent

func UnregisterComponent(kind string)

UnregisterComponent removes a component factory from the registry.

Types

type Audio

type Audio interface {
	// PlaySound plays a sound effect once.
	// soundID identifies a previously loaded sound.
	// volume ranges from 0.0 (silent) to 1.0 (full volume).
	// pitch ranges from 0.5 (half speed) to 2.0 (double speed).
	PlaySound(soundID string, volume, pitch float64)

	// PlayMusic starts playing background music.
	// musicID identifies a previously loaded music track.
	// loop determines if the music should repeat.
	PlayMusic(musicID string, loop bool)

	// StopMusic stops any currently playing music.
	StopMusic()

	// PauseMusic pauses the current music (can be resumed with ResumeMusic).
	PauseMusic()

	// ResumeMusic resumes paused music.
	ResumeMusic()

	// SetMasterVolume sets the overall volume (0.0 to 1.0).
	SetMasterVolume(volume float64)

	// SetSoundVolume sets the volume for sound effects.
	SetSoundVolume(volume float64)

	// SetMusicVolume sets the volume for music.
	SetMusicVolume(volume float64)
}

Audio handles sound and music playback.

type BaseComponent

type BaseComponent struct {

	// DrawLayer orders this component's Draw relative to the object's other
	// components. Lower layers draw first (behind); equal layers keep insertion
	// order. Populated from the "draw_layer" JSON arg.
	DrawLayer int `json:"draw_layer"`

	// Group is an optional developer-facing label that groups related components on
	// an object (e.g. "movement", "combat", "ui"). It is metadata only: it does not
	// affect update/draw order or any runtime behavior. The editor uses it to present
	// components as though they were organized in folders while they still run flat.
	Group string `json:"group"`
	// contains filtered or unexported fields
}

BaseComponent provides default implementations for the Component interface, plus the event helpers (On/Emit) and scene access. All components should embed BaseComponent to get common functionality.

func (*BaseComponent) Draw

func (c *BaseComponent) Draw(renderer Renderer)

Draw is a default empty implementation. Components should override this method if they need rendering logic.

func (*BaseComponent) Emit added in v0.3.2

func (c *BaseComponent) Emit(name string, data any)

Emit broadcasts an event to the scene's event queue. It is delivered to every component that registered a handler for `name` via On(), after all Update() calls for this frame complete.

c.Emit("damaged", 10.0)

func (*BaseComponent) EventNames added in v0.3.2

func (c *BaseComponent) EventNames() []string

EventNames returns the event names this component has handlers for. Used by the EventManager to sync subscriptions after Initialize.

func (*BaseComponent) GetDrawLayer added in v0.3.6

func (c *BaseComponent) GetDrawLayer() int

GetDrawLayer returns the component's draw layer (see DrawLayer).

func (*BaseComponent) GetKind

func (c *BaseComponent) GetKind() string

GetKind returns the component's kind identifier.

func (*BaseComponent) GetName

func (c *BaseComponent) GetName() string

GetName returns the component's name.

func (*BaseComponent) GetOwner

func (c *BaseComponent) GetOwner() *Object

GetOwner returns the parent object that owns this component.

func (*BaseComponent) GetScene added in v0.3.10

func (c *BaseComponent) GetScene() *Scene

GetScene returns the scene that contains this component's owner, or nil if the owner isn't in a scene yet.

func (*BaseComponent) HandleEvent added in v0.3.2

func (c *BaseComponent) HandleEvent(event *Event)

HandleEvent delivers an event to this component's registered handlers. Used internally by the EventManager.

func (*BaseComponent) Initialize

func (c *BaseComponent) Initialize()

Initialize is a default empty implementation. Components should override this method if they need initialization or defaults.

func (*BaseComponent) On added in v0.3.2

func (c *BaseComponent) On(name string, handler func(any))

On registers a handler for an event name. Handlers are typically registered in Initialize, before the first Update. Multiple handlers may be registered for the same name; they run in registration order when the event is delivered.

c.On("damaged", func(data any) {
    amount := data.(float64)
    ...
})

func (*BaseComponent) OnDisable

func (c *BaseComponent) OnDisable()

OnDisable is a default empty implementation. Components should override this method if they need deactivation logic.

func (*BaseComponent) OnEnable

func (c *BaseComponent) OnEnable()

OnEnable is a default empty implementation. Components should override this method if they need activation logic.

func (*BaseComponent) SetKind

func (c *BaseComponent) SetKind(kind string)

SetKind sets the component's kind identifier (file path).

func (*BaseComponent) SetName

func (c *BaseComponent) SetName(name string)

SetName sets the component's name (unique within the object).

func (*BaseComponent) SetOwner

func (c *BaseComponent) SetOwner(obj *Object)

SetOwner sets the parent object that owns this component.

func (*BaseComponent) Update

func (c *BaseComponent) Update(ctx *Context)

Update is a default empty implementation. Components should override this method if they need update logic.

type BaseUIComponent added in v0.3.21

type BaseUIComponent struct {
	BaseComponent

	// Offset is the element's top-left position relative to the owner object.
	Offset math.Vector2 `json:"offset"`

	// Width and Height are the element's extent in logical units.
	Width  float64 `json:"width"`
	Height float64 `json:"height"`

	// Visible controls whether the element draws. nil means true.
	Visible *bool `json:"visible"`

	// Enabled controls whether the element receives input. nil means true.
	// A disabled element still draws but ignores pointer/keyboard events.
	Enabled *bool `json:"enabled"`

	// Focusable reports whether the element can take keyboard focus (e.g. a text
	// input). Default false.
	Focusable bool `json:"focusable"`

	// Blocking reports whether the element swallows pointer events: when it is the
	// topmost element under the cursor it is the exclusive target, so nothing drawn
	// behind it receives hover/click. A nil Blocking defaults to false here; the
	// built-in interactive components (@Panel/@Button/@TextInput) opt into blocking
	// in Initialize, and a JSON "blocking": true/false overrides any component.
	Blocking *bool `json:"blocking"`
}

BaseUIComponent is the shared base for UI components (@Label, @Panel, @Button, @TextInput, and any custom UI component). A UI component is a screen-space element positioned relative to its owner object: the element's top-left is owner.Position + Offset, and its extent is Width×Height. The owner object is a "window" (UI=true); its components are that window's elements.

It exposes the fields a @UIManager needs to route input and manage focus: Rect() for hit-testing and occlusion, IsEnabled for interaction, and Focusable for keyboard focus. In Faz 2 each widget drives itself; the manager (Faz 3) uses these to coordinate input across widgets without each widget depending on focus or selection state.

func (*BaseUIComponent) BlocksPointer added in v0.3.22

func (c *BaseUIComponent) BlocksPointer() bool

BlocksPointer reports whether the element swallows pointer events (occludes the elements drawn behind it). See the Blocking field.

func (*BaseUIComponent) Contains added in v0.3.21

func (c *BaseUIComponent) Contains(p math.Vector2) bool

Contains reports whether a point (in screen space) is inside the element.

func (*BaseUIComponent) IsEnabled added in v0.3.21

func (c *BaseUIComponent) IsEnabled() bool

IsEnabled reports whether the element receives input.

func (*BaseUIComponent) IsFocusable added in v0.3.22

func (c *BaseUIComponent) IsFocusable() bool

IsFocusable reports whether the element can take keyboard focus.

func (*BaseUIComponent) IsVisible added in v0.3.21

func (c *BaseUIComponent) IsVisible() bool

IsVisible reports whether the element draws.

func (*BaseUIComponent) Position added in v0.3.21

func (c *BaseUIComponent) Position() math.Vector2

Position returns the element's top-left corner in screen space.

func (*BaseUIComponent) Rect added in v0.3.21

func (c *BaseUIComponent) Rect() math.Rect

Rect returns the element's screen-space rectangle: top-left at Position(), size Width×Height. A nil owner means the owner's position is treated as (0,0).

func (*BaseUIComponent) SetEnabled added in v0.3.21

func (c *BaseUIComponent) SetEnabled(v bool)

SetEnabled sets whether the element receives input.

func (*BaseUIComponent) SetVisible added in v0.3.21

func (c *BaseUIComponent) SetVisible(v bool)

SetVisible sets whether the element draws.

type Camera added in v0.3.6

type Camera struct {
	X    float64 `json:"x"`
	Y    float64 `json:"y"`
	Zoom float64 `json:"zoom"`

	Smoothing float64 `json:"smoothing"`
	LockX     bool    `json:"lock_x"`
	LockY     bool    `json:"lock_y"`
	// contains filtered or unexported fields
}

Camera defines what part of the world a scene renders. It is core-level state on a Scene (not an object or component), so a scene can follow an object and the renderer can transform world coordinates into screen coordinates.

X/Y are the world coordinates of the viewport's TOP-LEFT corner, so the world origin (0,0) appears at the top-left of the screen. Zoom scales the view around its center (1 = 1:1). Smoothing eases the camera toward its follow target: 0 snaps instantly (the default), while a small value like 0.1 trails smoothly. LockX / LockY stop the camera from moving along that axis (e.g. a side-scroller locks Y).

A scene with no camera (Camera == nil) draws with world = screen (the default).

func NewCamera added in v0.3.6

func NewCamera() *Camera

NewCamera returns a camera with the view's top-left corner at the origin and 1x zoom.

func (*Camera) Follow added in v0.3.6

func (c *Camera) Follow(obj *Object)

Follow makes the camera track an object's position (its transform origin).

func (*Camera) FollowPoint added in v0.3.6

func (c *Camera) FollowPoint(x, y float64)

FollowPoint makes the camera track a fixed world point.

func (*Camera) LookAt added in v0.3.6

func (c *Camera) LookAt(x, y float64)

LookAt immediately centers the camera on a point and stops following.

func (*Camera) ScreenToWorld added in v0.3.6

func (c *Camera) ScreenToWorld(screen math.Vector2) math.Vector2

ScreenToWorld converts a screen point to world coordinates.

func (*Camera) StopFollow added in v0.3.6

func (c *Camera) StopFollow()

StopFollow stops following, leaving the camera where it is.

func (*Camera) Tick added in v0.3.6

func (c *Camera) Tick()

Tick advances the camera toward its follow target, applying smoothing. Called once per frame by the scene after objects update.

func (*Camera) WorldToScreen added in v0.3.6

func (c *Camera) WorldToScreen(world math.Vector2) math.Vector2

WorldToScreen converts a world point to screen coordinates.

type Component

type Component interface {
	// Initialize is called exactly once, after the object is in a fully-loaded
	// scene and before its first Update. This is where defaults are set and any
	// scene-dependent setup happens (c.GetScene() is available here).
	Initialize()

	// Update is called every frame for logic updates.
	// ctx provides access to engine services (Input, Audio, Time, Scene, etc.)
	Update(ctx *Context)

	// Draw is called every frame for rendering.
	Draw(renderer Renderer)

	// SetOwner sets the parent object that owns this component.
	SetOwner(obj *Object)

	// GetOwner returns the parent object that owns this component.
	GetOwner() *Object

	// GetScene returns the scene that contains the component's owner, or nil if
	// the owner isn't in a scene yet.
	GetScene() *Scene

	// OnEnable is called when the component becomes active.
	OnEnable()

	// OnDisable is called when the component becomes inactive.
	OnDisable()

	// GetName returns the component's name (unique within the object).
	GetName() string

	// SetName sets the component's name.
	SetName(name string)

	// GetKind returns the component's kind identifier (file path).
	// For built-in: "@Collider", "@Mover", etc.
	// For user-defined: "components/player.go", etc.
	GetKind() string

	// SetKind sets the component's kind identifier.
	SetKind(kind string)
}

Component is the interface that all game components must implement. Both built-in and user-defined components use this same interface.

A component's exported, JSON-tagged fields are its "export variables": they are populated from the component's `args` object in .obj/.scene files. Unexported fields stay private to the component (local state).

func CreateComponent

func CreateComponent(kind string, args map[string]interface{}) (Component, error)

CreateComponent creates a component from a kind identifier and its JSON args. It looks up the factory, constructs the component, then injects the args by unmarshaling them into the component's exported (json-tagged) fields. Returns error if the kind is not registered or the args fail to decode.

func CreateComponentFromJSON

func CreateComponentFromJSON(kind, name string, args map[string]interface{}) (Component, error)

CreateComponentFromJSON creates a named component from its JSON configuration.

type ComponentError

type ComponentError struct {
	Kind   string
	Reason string
}

ComponentError represents an error that occurred during component creation.

func (*ComponentError) Error

func (e *ComponentError) Error() string

type ComponentFactory

type ComponentFactory func() Component

ComponentFactory is a function that creates a new, zero-valued component instance. Config (args) is injected afterward by json unmarshaling into the component's exported fields.

type Config

type Config struct {
	// Window settings
	Window WindowConfig

	// Game settings
	TargetFPS   int
	FixedUpdate bool

	// Scene settings
	InitialScene string
}

Config holds game configuration settings.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a default configuration.

type Context added in v0.3.2

type Context struct {
	Input Input
	Audio Audio
	Time  Time
	Scene *Scene
	Game  *Game
}

Context provides access to engine services from within components. Passed to Component.Update() method each frame. Scene is set to the active scene before updates run; Renderer is passed separately to Draw().

func (*Context) DeltaTime added in v0.3.2

func (c *Context) DeltaTime() float64

DeltaTime returns the seconds elapsed since the last frame. Returns 0 if no Time service is available.

type Dependable added in v0.3.4

type Dependable interface {
	// Requires returns the component kinds this component depends on.
	Requires() []string
}

Dependable is an optional interface a component may implement to declare the component kinds it needs to function (e.g. @Animator requires @Sprite). The declaration is informational: the build tool reads it to warn when an object uses a component without also giving it the components it declares it needs.

type DrawLayerProvider added in v0.3.6

type DrawLayerProvider interface {
	GetDrawLayer() int
}

DrawLayerProvider is an optional interface a component may implement to declare its draw order within its object. BaseComponent implements it via DrawLayer and GetDrawLayer, so any component embedding BaseComponent gets this for free.

type Event added in v0.2.7

type Event struct {
	// Name identifies the event type (e.g., "collision", "player_died").
	Name string

	// Data holds arbitrary extra information associated with the event.
	// The interpretation depends on the event Name (user-defined).
	Data interface{}

	// Source is the component that emitted the event, or nil for engine-generated
	// events. Listeners can filter by it (e.g. a @StateMachine's "from" scope).
	Source Component
}

Event represents a message sent between components. Components emit events via BaseComponent.Emit(name, data) and receive them via BaseComponent.On(name, handler).

type EventManager added in v0.2.7

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

EventManager manages event subscriptions and queuing for a scene. Events are emitted by components via Emit(), queued, and processed after all component Update() calls complete for the frame.

func NewEventManager added in v0.2.7

func NewEventManager() *EventManager

NewEventManager creates a new EventManager with empty queue and subscriptions.

func (*EventManager) Emit added in v0.2.7

func (em *EventManager) Emit(event *Event)

Emit adds an event to the processing queue. Called by components via their Emit() method.

func (*EventManager) Process added in v0.2.7

func (em *EventManager) Process()

Process delivers all queued events to their subscribers and clears the queue. Called once per frame by Scene.Update() after all component Update() calls.

func (*EventManager) Subscribe added in v0.2.7

func (em *EventManager) Subscribe(component Component, eventName string)

Subscribe registers a component's interest in an event name. Multiple calls with the same component+name are idempotent.

func (*EventManager) SubscribeAll added in v0.3.2

func (em *EventManager) SubscribeAll(component Component)

SubscribeAll registers a component for every event name it has On() handlers for. Called once per component after its Initialize runs.

func (*EventManager) Unsubscribe added in v0.2.7

func (em *EventManager) Unsubscribe(component Component, eventName string)

Unsubscribe removes a component's interest in an event name.

func (*EventManager) UnsubscribeAll added in v0.2.7

func (em *EventManager) UnsubscribeAll(component Component)

UnsubscribeAll removes a component from ALL event subscriptions.

type FileSystem

type FileSystem interface {
	// ReadFile reads the entire contents of a file.
	ReadFile(path string) ([]byte, error)

	// WriteFile writes data to a file.
	WriteFile(path string, data []byte) error

	// FileExists checks if a file exists.
	FileExists(path string) bool

	// ListFiles lists all files in a directory (non-recursive).
	ListFiles(dir string) ([]string, error)

	// ListFilesRecursive lists all files in a directory recursively.
	ListFilesRecursive(dir string) ([]string, error)

	// CreateDirectory creates a new directory.
	CreateDirectory(path string) error

	// Delete deletes a file or empty directory.
	Delete(path string) error
}

FileSystem handles file operations and asset loading.

type Game

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

Game is the main game engine struct.

func NewGame

func NewGame() *Game

NewGame creates a new game instance with default configuration.

func NewGameWithConfig

func NewGameWithConfig(config Config) *Game

NewGameWithConfig creates a new game instance with custom configuration.

func (*Game) AddScene

func (g *Game) AddScene(scene *Scene)

AddScene adds a scene to the game.

func (*Game) Draw

func (g *Game) Draw()

Draw renders the game for the current frame. It clears the screen with the active scene's background color, then draws that scene.

func (*Game) GetActiveScene

func (g *Game) GetActiveScene() *Scene

GetActiveScene returns the currently active scene.

func (*Game) GetScene

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

GetScene returns a scene by name, or nil if not found.

func (*Game) Init

func (g *Game) Init() error

Init initializes the game engine. Must be called after SetPlatform() and before Run().

func (*Game) IsRunning

func (g *Game) IsRunning() bool

IsRunning returns true if the game is currently running.

func (*Game) Run

func (g *Game) Run() error

Run starts the main game loop. Blocks until the game exits.

func (*Game) SetActiveScene

func (g *Game) SetActiveScene(name string) bool

SetActiveScene sets the active scene by name. Returns false if the scene doesn't exist.

func (*Game) SetPlatform

func (g *Game) SetPlatform(platform Platform)

SetPlatform sets the platform implementations for the game. Must be called before Init().

func (*Game) Shutdown

func (g *Game) Shutdown() error

Shutdown cleans up resources and shuts down the game.

func (*Game) Stop

func (g *Game) Stop()

Stop gracefully stops the game loop.

func (*Game) SwitchScene added in v0.3.6

func (g *Game) SwitchScene(name string) bool

SwitchScene queues a scene change to take effect at the start of the next frame. Deferring avoids drawing the new scene before its objects' Initialize() has run (which is what would happen with an immediate SetActiveScene from inside a component's Update). Components reach this via ctx.Game.SwitchScene. Returns false if the scene doesn't exist.

func (*Game) Update

func (g *Game) Update(ctx *Context)

Update updates game logic for the current frame.

type GameError

type GameError struct {
	Stage  string
	Reason string
}

GameError represents an error that occurred during game operation.

func (*GameError) Error

func (e *GameError) Error() string

type Input

type Input interface {
	// IsKeyPressed checks if a key is currently pressed.
	IsKeyPressed(key KeyCode) bool

	// IsKeyJustPressed checks if a key was pressed this frame (not held).
	IsKeyJustPressed(key KeyCode) bool

	// IsKeyJustReleased checks if a key was released this frame.
	IsKeyJustReleased(key KeyCode) bool

	// IsMouseButtonPressed checks if a mouse button is currently pressed.
	IsMouseButtonPressed(button MouseButton) bool

	// IsMouseButtonJustPressed checks if a mouse button was pressed this frame.
	IsMouseButtonJustPressed(button MouseButton) bool

	// IsMouseButtonJustReleased checks if a mouse button was released this frame.
	IsMouseButtonJustReleased(button MouseButton) bool

	// GetMousePosition returns the current mouse position in screen coordinates.
	GetMousePosition() math.Vector2

	// GetMouseDelta returns the mouse movement since last frame.
	GetMouseDelta() math.Vector2

	// GetMouseScroll returns the mouse wheel scroll delta.
	GetMouseScroll() math.Vector2

	// InputChars returns the characters typed this frame (runes from the keyboard,
	// including IME input). Use it for text entry: the platform maps physical keys
	// to characters, so shift/case/layout are handled for you. Returns nil when
	// nothing was typed.
	InputChars() []rune

	// Update should be called once per frame to update input state.
	Update()
}

Input handles user input from keyboard and mouse.

type KeyCode

type KeyCode int

KeyCode represents a keyboard key. Platform implementations will map physical keys to these codes.

const (
	KeyUnknown KeyCode = iota
	KeyA
	KeyB
	KeyC
	KeyD
	KeyE
	KeyF
	KeyG
	KeyH
	KeyI
	KeyJ
	KeyK
	KeyL
	KeyM
	KeyN
	KeyO
	KeyP
	KeyQ
	KeyR
	KeyS
	KeyT
	KeyU
	KeyV
	KeyW
	KeyX
	KeyY
	KeyZ
	Key0
	Key1
	Key2
	Key3
	Key4
	Key5
	Key6
	Key7
	Key8
	Key9
	KeySpace
	KeyEnter
	KeyEscape
	KeyBackspace
	KeyDelete
	KeyTab
	KeyShift
	KeyControl
	KeyAlt
	KeyLeft
	KeyRight
	KeyUp
	KeyDown
	KeyHome
	KeyEnd
	KeyF1
	KeyF2
	KeyF3
	KeyF4
	KeyF5
	KeyF6
	KeyF7
	KeyF8
	KeyF9
	KeyF10
	KeyF11
	KeyF12
)

Common keyboard keys (partial list, can be extended).

type MouseButton

type MouseButton int

MouseButton represents a mouse button.

const (
	MouseButtonLeft MouseButton = iota
	MouseButtonRight
	MouseButtonMiddle
	MouseButton4
	MouseButton5
)

type Object

type Object struct {
	// ID is a unique integer identifier within the scene (runtime-generated)
	ID uint64

	// Name is a unique human-readable identifier within the scene (auto-generated if duplicate)
	Name string

	// Components stores all components attached to this object.
	// Key: component name (unique within object), Value: component instance
	Components map[string]Component

	// Tags is a set of tags assigned to this object (for quick filtering)
	Tags map[string]bool

	// Transform defines the object's position, rotation, and scale in world space
	Transform math.Transform

	// Depth determines drawing order within a layer (higher depth = drawn last/on top)
	Depth float64

	// Layer is the primary drawing-order dimension: objects are sorted by layer
	// first (lower layer draws first/behind), then by depth within the layer. It
	// separates fixed chrome (e.g. an always-on-top header) from ordinary windows
	// so click-to-front can reorder windows without ever crossing a higher layer.
	Layer int

	// UI marks the object as screen-space: its position is in screen pixels, it
	// ignores the camera, and it draws after all world objects.
	UI bool

	// Draggable lets a @UIManager drag this object by its non-interactive surface
	// (the window background), used for moving UI windows. Ignored for non-UI
	// objects. Default false.
	Draggable bool

	// Active controls whether the object is updated and drawn
	Active bool

	// Scene is a reference to the parent scene (set when added to a scene)
	Scene *Scene
	// contains filtered or unexported fields
}

Object represents an entity in the game world. Objects are composed of components and can be positioned, rotated, and scaled.

func LoadObjectFromFile

func LoadObjectFromFile(path string) (*Object, error)

LoadObjectFromFile loads an object from a JSON file.

func LoadObjectFromJSON

func LoadObjectFromJSON(data []byte) (*Object, error)

LoadFromJSON loads object data from JSON configuration. Note: This creates a new object from JSON data, it doesn't update an existing object.

func NewObject

func NewObject(name string) *Object

NewObject creates a new object with default values. Note: ID must be set by the scene when adding the object.

func NewObjectWithTransform

func NewObjectWithTransform(name string, transform math.Transform) *Object

NewObjectWithTransform creates a new object with a specific transform.

func (*Object) AddComponent

func (obj *Object) AddComponent(component Component) error

AddComponent adds a component to the object. Returns an error if a component with the same name already exists. The component's Initialize() is deferred until the object is in a scene and about to be updated (see initializeComponents).

func (*Object) AddComponentFromKind

func (obj *Object) AddComponentFromKind(kind string, args map[string]interface{}) error

AddComponentFromKind creates and adds a component from a kind identifier and args.

func (*Object) AddTag

func (obj *Object) AddTag(tag string)

AddTag adds a tag to the object. Also updates the scene's tag mapping if the object is in a scene.

func (*Object) ComponentsInDrawOrder added in v0.3.22

func (obj *Object) ComponentsInDrawOrder() []Component

ComponentsInDrawOrder returns the object's components in draw order (ascending draw layer, stable for equal layers) — the same order Draw renders them. A @UIManager uses this to hit-test elements back-to-front within an object.

func (*Object) Destroy

func (obj *Object) Destroy()

Destroy marks the object for destruction. The object will be removed from the scene at the end of the frame.

func (*Object) Draw

func (obj *Object) Draw(renderer Renderer)

Draw calls Draw on all components, ordered by draw layer (ascending; equal layers keep insertion order).

func (*Object) GetComponent

func (obj *Object) GetComponent(name string) Component

GetComponent retrieves a component by name (O(1) lookup). Returns nil if the component doesn't exist.

func (*Object) GetComponentByKind added in v0.2.10

func (obj *Object) GetComponentByKind(kind string) Component

GetComponentByKind retrieves the first component matching the given kind, in insertion order (O(n) search). Returns nil if no component of that kind exists. Kind is the component identifier (e.g., "@Collider", "@Mover", "components/sprite.go").

func (*Object) GetComponentsByKind

func (obj *Object) GetComponentsByKind(kind string) []Component

GetComponentsByKind retrieves all components of a specific kind, in insertion order (O(n) search).

func (*Object) GetDepth

func (obj *Object) GetDepth() float64

GetDepth returns the object's depth value.

func (*Object) GetID

func (obj *Object) GetID() uint64

GetID returns the object's unique integer ID.

func (*Object) GetLayer added in v0.3.22

func (obj *Object) GetLayer() int

GetLayer returns the object's layer.

func (*Object) GetName

func (obj *Object) GetName() string

GetName returns the object's human-readable name.

func (*Object) GetPosition

func (obj *Object) GetPosition() math.Vector2

GetPosition returns the object's position.

func (*Object) GetRotation

func (obj *Object) GetRotation() float64

GetRotation returns the object's rotation (in radians).

func (*Object) GetScale

func (obj *Object) GetScale() math.Vector2

GetScale returns the object's scale factors.

func (*Object) HasTag

func (obj *Object) HasTag(tag string) bool

HasTag checks if the object has a specific tag (O(1) lookup).

func (*Object) IsDestroyed

func (obj *Object) IsDestroyed() bool

IsDestroyed returns true if the object is marked for destruction.

func (*Object) RemoveComponent

func (obj *Object) RemoveComponent(name string)

RemoveComponent removes a component by name. Unsubscribes the component from all events before removal.

func (*Object) RemoveTag

func (obj *Object) RemoveTag(tag string)

RemoveTag removes a tag from the object. Also updates the scene's tag mapping if the object is in a scene.

func (*Object) SaveToFile

func (obj *Object) SaveToFile(path string) error

SaveToFile saves the object to a JSON file.

func (*Object) SaveToJSON

func (obj *Object) SaveToJSON() ([]byte, error)

SaveToJSON saves the object to JSON format.

func (*Object) SetActive added in v0.3.0

func (obj *Object) SetActive(active bool)

SetActive enables or disables the object. Toggling fires OnEnable/OnDisable on every component so they can react to activation changes (e.g. pause timers).

func (*Object) SetDepth

func (obj *Object) SetDepth(depth float64) error

SetDepth sets the object's depth value and marks the scene for re-sorting. Returns an error if depth is NaN or Infinity.

func (*Object) SetID

func (obj *Object) SetID(id uint64)

SetID sets the object's unique integer ID. Should only be called by the scene when adding the object.

func (*Object) SetLayer added in v0.3.22

func (obj *Object) SetLayer(layer int)

SetLayer sets the object's layer and marks the scene for re-sorting.

func (*Object) SetName

func (obj *Object) SetName(name string) error

SetName sets the object's name and updates scene mapping if in a scene.

func (*Object) SetPosition

func (obj *Object) SetPosition(x, y float64)

SetPosition sets the object's position.

func (*Object) SetRotation

func (obj *Object) SetRotation(rotation float64)

SetRotation sets the object's rotation (in radians).

func (*Object) SetScale

func (obj *Object) SetScale(x, y float64)

SetScale sets the object's scale factors.

func (*Object) ToJSONConfig

func (obj *Object) ToJSONConfig() *corejson.ObjectConfig

ToJSONConfig converts the object to JSON configuration. Note: Transform is not included in ObjectConfig (only in scene references).

func (*Object) Update

func (obj *Object) Update(ctx *Context)

Update calls Update on all components in insertion order.

type Platform

type Platform interface {
	// Renderer returns the renderer interface for drawing operations.
	Renderer() Renderer

	// Input returns the input interface for user input handling.
	Input() Input

	// Audio returns the audio interface for sound and music playback.
	Audio() Audio

	// Time returns the time interface for timing information.
	Time() Time

	// Window returns the window interface for window management.
	Window() Window

	// FileSystem returns the filesystem interface for file operations.
	FileSystem() FileSystem

	// Init initializes the platform with the given window configuration.
	// This should create the window, initialize subsystems, etc.
	Init(cfg WindowConfig) error

	// Update is called each frame to update platform state.
	Update()
}

Platform is a convenience interface that groups all platform interfaces. Implementations can choose to implement this or individual interfaces.

type Renderer

type Renderer interface {
	// Clear clears the entire screen with the specified color.
	Clear(color math.Color)

	// DrawRect draws a filled rectangle.
	DrawRect(rect math.Rect, color math.Color)

	// DrawRectOutline draws a rectangle outline (border only).
	DrawRectOutline(rect math.Rect, color math.Color, thickness float64)

	// DrawCircle draws a filled circle.
	DrawCircle(center math.Vector2, radius float64, color math.Color)

	// DrawCircleOutline draws a circle outline.
	DrawCircleOutline(center math.Vector2, radius float64, color math.Color, thickness float64)

	// DrawLine draws a line between two points.
	DrawLine(start, end math.Vector2, color math.Color, thickness float64)

	// DrawTexture draws a texture (or a region of it) at the specified position
	// with transformations. textureID identifies a previously loaded texture.
	// src is the source region in the texture; a zero Rect means the entire texture.
	// transform is the color transform applied to the texture (an identity
	// transform is a plain draw).
	DrawTexture(textureID string, src math.Rect, position math.Vector2, scale math.Vector2, rotation float64, transform math.ColorTransform)

	// GetTextureSize returns the natural pixel size of a loaded texture.
	// Returns (0, 0) if the texture cannot be loaded.
	GetTextureSize(textureID string) (width, height float64)

	// DrawText draws a single line of text with its top-left corner at position.
	// fontID "" (or "imge-font") selects the built-in default font; otherwise it is
	// a project-root-relative path to a .ttf/.otf font file, loaded on demand.
	// size is the font size in logical units; size <= 0 selects the font's default
	// size. Text is always rendered chunky (like textures and sprites), so a pixel
	// font drawn at an integer size stays crisp at any pixel_per_unit.
	DrawText(text string, fontID string, size float64, position math.Vector2, color math.Color)

	// MeasureText returns the width and height (in logical units) the given text
	// occupies at the given size — the same box DrawText places starting at
	// position. Use it for layout (centering, wrapping, hit-testing).
	// Returns (0, 0) when the font cannot be loaded.
	MeasureText(text string, fontID string, size float64) (width, height float64)

	// DrawTextWrapped draws text constrained to maxWidth, wrapping or clipping it
	// into multiple lines according to wrap. position is the top-left corner of the
	// whole block; each line advances by the font's line height. A maxWidth <= 0
	// disables width-based breaking (explicit "\n" still starts a new line). Like
	// DrawText, an empty fontID selects the built-in font and size <= 0 the default.
	//
	// ellipsis affects only WrapClip: when a clipped line is truncated, true appends
	// a trailing "..." that still fits maxWidth (the default); false cuts with no
	// marker.
	DrawTextWrapped(text string, fontID string, size float64, maxWidth float64, wrap WrapMode, ellipsis bool, position math.Vector2, color math.Color)

	// MeasureTextWrapped returns the width (the widest line) and height (line count
	// × line height) the given text occupies once wrapped to maxWidth with the
	// given wrap mode and ellipsis setting — the same box DrawTextWrapped places.
	// Returns (0, 0) when the font cannot be loaded.
	MeasureTextWrapped(text string, fontID string, size float64, maxWidth float64, wrap WrapMode, ellipsis bool) (width, height float64)

	// SetCamera applies a world-to-screen camera transform to subsequent draw
	// calls. (cx, cy) is the view center in world coordinates and zoom is the scale
	// factor (1 = 1:1). A zoom <= 0 disables the transform (raw screen space).
	SetCamera(cx, cy, zoom float64)

	// Present presents the rendered frame to the screen (swap buffers).
	Present()

	// SetViewport sets the rendering viewport size.
	SetViewport(width, height int)

	// GetViewportSize returns the current viewport size.
	GetViewportSize() (width, height int)
}

Renderer handles all 2D drawing operations. Platform implementations will provide actual rendering (OpenGL, DirectX, software, etc.).

type Scene

type Scene struct {
	// Objects maps object ID to object pointer for O(1) lookup
	Objects map[uint64]*Object

	// Tags maps tag name to set of object IDs that have that tag
	Tags map[string]map[uint64]bool

	// SortedObjects contains object IDs sorted by depth (ascending)
	// Lower depth drawn first, higher depth drawn last (on top)
	SortedObjects []uint64

	// Name is the scene's identifier
	Name string

	// BackgroundColor is the clear color used each frame before objects draw.
	BackgroundColor math.Color

	// Camera transforms world coordinates to screen coordinates when drawing. Nil
	// means no transform (world = screen).
	Camera *Camera

	// Active controls whether the scene is updated and drawn
	Active bool

	// EventManager handles the event queue and subscriptions for this scene.
	// Processed after all component Update() calls each frame.
	EventManager *EventManager
	// contains filtered or unexported fields
}

Scene represents a collection of game objects that can be updated and drawn together.

func NewScene

func NewScene(name string) *Scene

NewScene creates a new empty scene.

func (*Scene) AddObject

func (s *Scene) AddObject(obj *Object) error

AddObject adds an object to the scene. Assigns a unique ID and updates all internal mappings. Returns an error if the object's name conflicts with an existing object.

func (*Scene) Draw

func (s *Scene) Draw(renderer Renderer)

Draw calls Draw on all active objects in the scene, sorted by depth. World objects (UI=false) draw under the camera transform; UI objects draw afterward in screen space (no camera), so they always sit on top of the world.

func (*Scene) FindObjectsWithTag

func (s *Scene) FindObjectsWithTag(tag string) []*Object

FindObjectsWithTag returns all objects with the given tag (O(1) lookup).

func (*Scene) FrameNumber added in v0.3.6

func (s *Scene) FrameNumber() uint64

FrameNumber returns the number of update cycles that have begun (1-based). It increments once per Scene.Update, so components can use it to detect "this frame" conditions (e.g. a @StateMachine's JustEntered).

func (*Scene) GetObjectByID

func (s *Scene) GetObjectByID(id uint64) *Object

GetObjectByID retrieves an object by its ID (O(1) lookup). Returns nil if the object doesn't exist.

func (*Scene) GetObjectByName

func (s *Scene) GetObjectByName(name string) *Object

GetObjectByName retrieves an object by its name (O(1) lookup via nameToID). Returns nil if the object doesn't exist.

func (*Scene) GetSortedObjects

func (s *Scene) GetSortedObjects() []*Object

GetSortedObjects returns objects in depth order (ascending). Calls updateSortedObjects first to ensure the list is up-to-date.

func (*Scene) InstantiateFromTemplate

func (s *Scene) InstantiateFromTemplate(templatePath string, transform *math.Transform) (*Object, error)

InstantiateFromTemplate creates an object from a template file and adds it to the scene. Returns the created object or error.

func (*Scene) InstantiateObject

func (s *Scene) InstantiateObject(data []byte, transform *math.Transform) (*Object, error)

InstantiateObject creates an object from JSON data and adds it to the scene. Useful for runtime object creation from component scripts.

func (*Scene) LoadFromFS added in v0.3.0

func (s *Scene) LoadFromFS(fsys fs.FS, path string) error

LoadFromFS loads a scene from the given filesystem, resolving any referenced object files through the same filesystem. This is used by web builds, where game data is embedded rather than read from a real filesystem.

func (*Scene) LoadFromFile

func (s *Scene) LoadFromFile(path string) error

LoadFromFile loads a scene from a JSON file.

func (*Scene) LoadFromJSON

func (s *Scene) LoadFromJSON(data []byte) error

LoadFromJSON loads a scene from JSON data.

func (*Scene) RemoveObject

func (s *Scene) RemoveObject(id uint64)

RemoveObject removes an object from the scene by ID. Unsubscribes all components from events before removal.

func (*Scene) SaveToJSON

func (s *Scene) SaveToJSON() ([]byte, error)

SaveToJSON saves the scene to JSON format. TODO: Implement JSON serialization based on the defined format.

func (*Scene) Update

func (s *Scene) Update(ctx *Context)

Update calls Update on all active objects in the scene. Before the first update, it runs each object's component Initialize() (once, after the scene is fully assembled). After all component updates, it processes the event queue. Depth order doesn't matter for updates.

type Time

type Time interface {
	// DeltaTime returns the time elapsed since the last frame in seconds.
	DeltaTime() float64

	// TotalTime returns the total time elapsed since the game started in seconds.
	TotalTime() float64

	// FPS returns the current frames per second.
	FPS() float64

	// Tick should be called once per frame to update timing.
	Tick()

	// Sleep pauses execution for the specified number of seconds.
	Sleep(seconds float64)
}

Time provides timing information for game loop and animations.

type Window

type Window interface {
	// Create creates a new window with the given configuration.
	Create(cfg WindowConfig) error

	// Destroy closes and cleans up the window.
	Destroy()

	// ShouldClose returns true if the window should close (e.g., user clicked X).
	ShouldClose() bool

	// GetSize returns the current window size in pixels.
	GetSize() (width, height int)

	// SetTitle sets the window title.
	SetTitle(title string)

	// SetSize sets the window size.
	SetSize(width, height int)

	// SetFullscreen toggles fullscreen mode.
	SetFullscreen(fullscreen bool)

	// PollEvents processes window events (should be called each frame).
	PollEvents()
}

Window handles window management and events.

type WindowConfig added in v0.3.7

type WindowConfig struct {
	Title      string
	Width      int // logical (game) resolution, in game units
	Height     int // logical (game) resolution, in game units
	Fullscreen bool
	// PixelPerUnit is the number of framebuffer pixels per logical unit along one
	// axis (>= 1). The render target is Width*PixelPerUnit x Height*PixelPerUnit,
	// so a value > 1 lets the rasterizer show sub-unit (fractional) positions — the
	// world still moves in whole units, but the extra resolution makes that motion
	// smooth instead of snapping to whole pixels. 1 (the default) is pixel-perfect.
	PixelPerUnit int
	// SmoothShapes opts vector shapes into framebuffer-resolution rasterization
	// (fine, 1px edges). The default (false) renders them "chunky": each shape is
	// rasterized at logical resolution (its anchor quantized to whole units, so
	// its pixel pattern is deterministic) and upscaled by PixelPerUnit, matching
	// how textures already render. Applies at any PixelPerUnit — at 1 it still
	// keeps shapes pixel-perfect and stable instead of re-rasterizing at
	// fractional positions (which wobbles as the shape moves).
	SmoothShapes bool
}

WindowConfig describes how the window should be created: its logical (game) resolution and whether it starts fullscreen. The logical resolution is what the renderer draws at; the platform scales it to fit the actual window/browser, letterboxing to preserve the aspect ratio.

type WrapMode added in v0.3.19

type WrapMode int

WrapMode controls how wrapped text (DrawTextWrapped) fits a line into maxWidth.

const (
	// WrapWord breaks lines on whitespace so whole words stay together. A single
	// word wider than maxWidth is still placed on its own line (and overflows) —
	// the standard word-wrap behavior for dialogue and UI text.
	WrapWord WrapMode = iota

	// WrapChar breaks lines exactly at maxWidth, splitting a word mid-way if it
	// doesn't fit — the terminal/log style of hard line wrapping.
	WrapChar

	// WrapClip does not wrap at all: the text is truncated to a single line that
	// fits within maxWidth, and anything past that is dropped. A trailing "..." is
	// appended by default (ellipsis=true) so the cut is visible; pass ellipsis=false
	// to truncate with no marker.
	WrapClip
)

func (*WrapMode) UnmarshalJSON added in v0.3.21

func (w *WrapMode) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts a WrapMode written as a string name ("word", "char", or "clip"; case-insensitive) so config files stay readable instead of forcing magic numbers.

Directories

Path Synopsis
Package math provides mathematical utilities for the game engine.
Package math provides mathematical utilities for the game engine.

Jump to

Keyboard shortcuts

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