willow

package module
v0.0.0-...-5e2a49b Latest Latest
Warning

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

Go to latest
Published: Mar 16, 2026 License: MIT Imports: 17 Imported by: 0

README

Willow

Go Reference Go Report Card

A retained-mode 2D game framework for Ebitengine - scene graph, batching, cameras, interaction, and effects. Inspired by Starling, Flash display lists, and PixiJS - adapted for Go's strengths.

Status: Functional and actively developed. Core systems are working and used across all included examples. API may change before v1.0.0.

Shapes demo Masks demo Shaders demo Watermesh demo

New here? Check out the Getting Started Guide - tutorials, examples, and everything you need to start building with Willow.


What is Willow?

Willow is a 2D game framework built on Ebitengine. Ebitengine is immediate-mode - every frame you must issue every draw command from scratch, and nothing persists between frames. Willow adds a retained-mode-inspired layer on top: you create a tree of nodes representing your game objects, and Willow traverses that tree each frame to produce draw commands for Ebitengine. You describe what exists in your scene, not how to render it each frame. This is the same pattern used by engines like Unity, Godot, and PixiJS - a persistent scene graph driving an immediate-mode renderer.

A main focus of Willow is performance - it is designed to minimize heap allocations and maximize batching, with features like subtree command caching for static content, and a zero-allocation-per-frame contract on the hot path. While managing the display tree does have a slight runtime cost, in some instances Willow can be faster than raw Ebitengine due to better batching and caching strategies.

It sits between Ebitengine and your game:

Your Game             - gameplay, content, logic
Willow                - scene graph, rendering, interaction
Ebitengine            - GPU backend, window, audio, platform

Why does Willow exist?

Ebitengine is an excellent, minimal 2D engine for Go - but every project beyond a prototype ends up building the same infrastructure from scratch: transform hierarchies, batching, hit testing, camera viewports, text layout, sprite atlases.

Willow exists so you don't have to rebuild that foundation every time.

Ebitengine is intentionally low-level - that's its strength. Willow is a higher-level framework on top of it, so you can focus on gameplay instead of rendering infrastructure.

Inspired by Starling, Flash display lists, and PixiJS - scene graph architectures that powered millions of 2D games - adapted for Go's strengths: simplicity and performance.


What Willow Is Not

  • Not a full game engine - no built-in physics, networking, or asset pipelines
  • Not a UI layout framework (a companion willowui library is planned)
  • Not a replacement for Ebitengine - it builds on top of it

Willow focuses on structured rendering and scene composition. You bring the gameplay and domain logic.


Goals

  1. Structure without handcuffs. Willow provides hierarchy, transforms, and batching without imposing game architecture. Any genre, any pattern, any scale.
  2. Performance as a contract. Zero heap allocations per frame on the hot path. 10,000 sprites at 120+ FPS on desktop, 60+ FPS on mobile and web. Verified with compiler escape analysis and benchmark suites.
  3. Wrap Ebitengine, never fight it. Willow uses Ebitengine's lifecycle hooks, image types, and threading model directly.
  4. Cross Platform. Windows, macOS, Linux, iOS, Android, WebAssembly - wherever Ebitengine runs.

Use Cases

Willow is well suited for:

  • 2D games requiring structured layering and scene composition
  • Games with worlds with large tile maps, cameras, and movement
  • Game tooling and level editors built on a display tree
  • Rapidly prototyping game ideas with minimal boilerplate on top of Ebitengine

Quick start

go get github.com/devthicket/willow@latest

For quick setup, call willow.Run(scene, config) and Willow handles the window and game loop. For full control, implement ebiten.Game yourself and call scene.Update() and scene.Draw(screen) directly - both paths are first-class.

package main

import (
	"log"

	"github.com/devthicket/willow"
)

func main() {
	scene := willow.NewScene()

	sprite := willow.NewSprite("hero", willow.TextureRegion{})
	sprite.SetSize(40, 40)
	sprite.SetColor(willow.RGBA(0.3, 0.7, 1, 1))
	sprite.SetPosition(300, 220)
	scene.Root().AddChild(sprite)

	if err := willow.Run(scene, willow.RunConfig{
		Title:  "My Game",
		Width:  640,
		Height: 480,
	}); err != nil {
		log.Fatal(err)
	}
}

Examples

20+ runnable examples are included in the examples/ directory, covering everything from basic sprites to full scenes combining lighting, meshes, particles, and masks. Several are also available as live WASM demos in the docs.

go run ./examples/basic    # simplest possible Willow app
go run ./examples/shapes   # parent/child transforms
go run ./examples/lighting # dungeon scene with torches and wisps

Documentation


Features

  • Scene graph - Parent/child transform inheritance (position, rotation, scale, skew, pivot) with alpha propagation and Pixi-style ZIndex sibling reordering. Tree search by name with FindChild/FindDescendant (supports % wildcards).
  • Sprite batching - TexturePacker JSON atlas loading with multi-page, trimmed, and rotated region support. Consecutive draws are grouped automatically into single DrawImage calls.
  • Camera system - Multiple independent viewports with smooth follow, scroll-to animation (45+ easings), bounds clamping, frustum culling, and world/screen coordinate conversion.
  • Input and interaction - Hierarchical hit testing with pluggable shapes (rect, circle, polygon). Pointer capture, drag dead zones, multi-touch, and two-finger pinch with rotation. Callbacks per-node or scene-wide.
  • Text rendering - Two font systems: DistanceFieldFont (SDF) for TTF/OTF with resolution-independent scaling, GPU-accelerated outlines, shadows, and glow; PixelFont (Bitmap) for pixel-perfect bitmap spritesheet fonts with integer-only scaling (1x, 2x, 3x) and cell trimming. Both support alignment, word wrapping, and line height overrides. Offline fontgen CLI to pre-bake SDF atlases, or generate at runtime.
  • Particle system - CPU-simulated with preallocated pools. Configurable emit rate, lifetime, speed, gravity, and scale/alpha/color interpolation. Optional world-space emission.
  • Mesh support - DrawTriangles with preallocated vertex and index buffers. High-level helpers for rope meshes, filled polygons, and deformable grids.
  • Subtree command caching - SetCacheAsTree caches all render commands for a container's subtree and replays them with delta transform remapping. Camera panning, parent movement, and alpha changes never invalidate the cache. Animated tiles (same-page UV swaps) are handled automatically via a two-tier source pointer - no invalidation, no API overhead. Manual and auto-invalidation modes. Includes sort-skip optimization when the entire scene is cache hits.
  • Filters and effects - Composable filter chains via Kage shaders. Built-in: color matrix, blur, outline, pixel-perfect outline, pixel-perfect inline, palette swap. Render-target masking and CacheAsTexture.
  • Lighting - Dedicated lighting layer using erase-blend render targets with automatic compositing.
  • Node index - Opt-in NodeIndex registry for tag-based grouping and O(1) lookups by name or tag. Supports % wildcards, multi-tag intersection queries, and zero-allocation iteration. No overhead for nodes that aren't indexed.
  • Animation - Tweening via gween with 45+ easing functions re-exported as willow.Ease* for autocomplete discoverability. Convenience wrappers for position, scale, rotation, alpha, and color. Auto-stops on node disposal.
  • Debug mode - Performance timers, batch counting, tree depth warnings, and disposed-node assertions via scene.SetDebugMode(true).

Performance

Willow is designed around a zero-allocation-per-frame contract on the hot path:

  • Preallocated command buffer reused each frame
  • Dirty flag propagation - static subtrees skip transform recomputation entirely
  • Custom merge sort with preallocated scratch buffer (no sort.SliceStable allocations)
  • Typed callback slices - no interface{} boxing in event dispatch
  • Render-texture pooling by power-of-two size buckets
  • Value-type DrawImageOptions declared once, reused per iteration

Subtree command caching (SetCacheAsTree) avoids re-traversing static subtrees entirely. Commands are stored at cache time and replayed with a single matrix multiply per command. Camera movement, parent transforms, and alpha changes are handled via delta remapping. Animated tiles (UV swaps within the same atlas page) are handled automatically via a two-tier source pointer indirection - no invalidation, no API overhead. This is designed to allow batch group of tilemaps with animated tiles (e.g. water) to be performance-optimized by avoiding full subtree invalidation on every frame.

Scenario (10K sprites) Time vs uncached
Manual cache, camera scrolling ~39 μs ~125x faster
Manual cache, 100 animated tile UV swaps ~1.97 ms ~2.5x faster
Auto cache, 1% of children moving ~4.0 ms ~1.2x faster
No cache (baseline) ~4.9 ms -

The cache is per-container, and will be invalidated if a child within the container moves. It is recommended to separate static content (tilemaps, UI panels) from dynamic content (players, projectiles) into different containers for best results.

Benchmark suite included: go test -bench . -benchmem


Roadmap

  • UI widget layer (buttons, text input, layout, focus traversal) as a separate companion library (willowui)
  • Example projects and starter templates
  • Comprehensive API documentation and guides
  • Tutorials and integration walkthroughs
  • Performance profiling across mobile and WebAssembly targets
  • Community feedback and API stabilization

Built with

  • Go 1.24+
  • Ebitengine v2.9+
  • Currently tested on: macOS and WebAssembly

Contributing

Contributions are welcome. Please a pull request and ensure tests pass. For major changes, open an issue first to discuss the design and implementation.


License

MIT - see LICENSE for details.

Documentation

Overview

Package willow is a retained-mode 2D game framework for Ebitengine.

Ebitengine is immediate-mode: every frame you issue draw commands from scratch, and nothing persists. Willow adds a retained-mode layer on top - you build a persistent scene graph of nodes, and Willow traverses it each frame to produce draw commands for Ebitengine.

Willow provides the scene graph, transform hierarchy, sprite batching, input handling, camera viewports, text rendering, particle systems, and more that every non-trivial 2D game needs.

Full documentation, tutorials, and examples are available at:

https://devthicket.github.io/willow/

Quick start

The simplest way to get started is Run, which creates a window and game loop for you:

scene := willow.NewScene()
// ... add nodes ...
willow.Run(scene, willow.RunConfig{
	Title: "My Game", Width: 640, Height: 480,
})

For full control, implement ebiten.Game yourself and call [Scene.Update] and [Scene.Draw] directly:

type Game struct{ scene *willow.Scene }

func (g *Game) Update() error         { g.Scene_.Update(); return nil }
func (g *Game) Draw(s *ebiten.Image)  { g.Scene_.Draw(s) }
func (g *Game) Layout(w, h int) (int, int) { return w, h }

Scene graph

Every visual element is a Node. Nodes form a tree rooted at [Scene.Root]. Children inherit their parent's transform and alpha.

Create nodes with typed constructors: NewContainer, NewSprite, NewText, NewParticleEmitter, NewMesh, NewPolygon, and others.

container := willow.NewContainer("ui")
scene.Root().AddChild(container)

sprite := willow.NewSprite("hero", atlas.Region("hero_idle"))
sprite.SetPosition(100, 50)
container.AddChild(sprite)

For solid-color rectangles, use NewSprite with a zero-value TextureRegion and set color and size:

box := willow.NewSprite("box", willow.TextureRegion{})
box.SetSize(80, 40)
box.SetColor(willow.RGBA(0.3, 0.7, 1, 1))

Finding nodes

For quick tree searches, use [Node.FindChild] (direct children) or [Node.FindDescendant] (recursive depth-first). Both support % wildcards:

bar := enemy.FindChild("health_bar")
boss := scene.Root().FindDescendant("boss%")  // starts with "boss"

For repeated lookups or tag-based grouping, use NodeIndex:

idx := willow.NewNodeIndex()
idx.Add(enemy, "enemy", "damageable")
enemies := idx.FindByTag("enemy")
boss := idx.FindByName("boss%")

Key features

Willow includes cameras with follow/scroll-to/zoom, two text systems (SDF-based DistanceFieldFont for smooth TTF/OTF scaling with outlines, glows, and shadows; pixel-perfect PixelFont for bitmap spritesheet fonts with integer-only scaling), CPU-simulated particles, mesh/polygon/rope geometry, Kage shader filters, texture caching, masking, blend modes, lighting layers, and tweens (via gween).

All 45 gween easing functions are re-exported as EaseLinear, EaseOutCubic, EaseOutBounce, etc. for autocomplete discoverability without an extra import.

See the full docs for guides on each feature: https://devthicket.github.io/willow/

Index

Constants

View Source
const (
	BlendNormal   = types.BlendNormal
	BlendAdd      = types.BlendAdd
	BlendMultiply = types.BlendMultiply
	BlendScreen   = types.BlendScreen
	BlendErase    = types.BlendErase
	BlendMask     = types.BlendMask
	BlendBelow    = types.BlendBelow
	BlendNone     = types.BlendNone
)

Blend modes.

View Source
const (
	NodeTypeContainer       = types.NodeTypeContainer
	NodeTypeSprite          = types.NodeTypeSprite
	NodeTypeMesh            = types.NodeTypeMesh
	NodeTypeParticleEmitter = types.NodeTypeParticleEmitter
	NodeTypeText            = types.NodeTypeText
)

Node types.

View Source
const (
	EventPointerDown  = types.EventPointerDown
	EventPointerUp    = types.EventPointerUp
	EventPointerMove  = types.EventPointerMove
	EventClick        = types.EventClick
	EventDragStart    = types.EventDragStart
	EventDrag         = types.EventDrag
	EventDragEnd      = types.EventDragEnd
	EventPinch        = types.EventPinch
	EventPointerEnter = types.EventPointerEnter
	EventPointerLeave = types.EventPointerLeave
)

Event types.

View Source
const (
	MouseButtonLeft   = types.MouseButtonLeft
	MouseButtonRight  = types.MouseButtonRight
	MouseButtonMiddle = types.MouseButtonMiddle
)

Mouse buttons.

View Source
const (
	ModShift = types.ModShift
	ModCtrl  = types.ModCtrl
	ModAlt   = types.ModAlt
	ModMeta  = types.ModMeta
)

Modifier keys.

View Source
const (
	TextAlignLeft   = types.TextAlignLeft
	TextAlignCenter = types.TextAlignCenter
	TextAlignRight  = types.TextAlignRight
)

Text alignment.

View Source
const (
	CacheTreeManual = types.CacheTreeManual
	CacheTreeAuto   = types.CacheTreeAuto
)

Cache tree modes.

View Source
const (
	BatchModeCoalesced = render.BatchModeCoalesced
	BatchModeImmediate = render.BatchModeImmediate
)

Batch modes.

View Source
const (
	CommandSprite     = render.CommandSprite
	CommandMesh       = render.CommandMesh
	CommandParticle   = render.CommandParticle
	CommandTilemap    = render.CommandTilemap
	CommandSDF        = render.CommandSDF
	CommandBitmapText = render.CommandBitmapText
)

Command types.

View Source
const (
	RopeJoinMiter = mesh.RopeJoinMiter
	RopeJoinBevel = mesh.RopeJoinBevel
)

Rope join modes.

View Source
const (
	RopeCurveLine        = mesh.RopeCurveLine
	RopeCurveCatenary    = mesh.RopeCurveCatenary
	RopeCurveQuadBezier  = mesh.RopeCurveQuadBezier
	RopeCurveCubicBezier = mesh.RopeCurveCubicBezier
	RopeCurveWave        = mesh.RopeCurveWave
	RopeCurveCustom      = mesh.RopeCurveCustom
)

Rope curve modes.

Variables

View Source
var (
	RGB              = types.RGB
	ColorFromRGBA    = types.ColorFromRGBA
	ColorFromHSV     = types.ColorFromHSV
	ColorWhite       = types.ColorWhite
	ColorBlack       = types.ColorBlack
	ColorTransparent = types.ColorTransparent
)

Color constructors and constants.

View Source
var (
	NewAtlas      = atlas.New
	NewBatchAtlas = atlas.NewBatch
	LoadAtlas     = atlas.LoadAtlas
)

Atlas constructors.

View Source
var (
	LoadDistanceFieldFont        = text.LoadDistanceFieldFont
	LoadDistanceFieldFontFromTTF = text.LoadDistanceFieldFontFromTTF
	GenerateSDFFromBitmaps       = text.GenerateSDFFromBitmaps
)

Text / Font constructors.

View Source
var (
	NewColorMatrixFilter         = filter.NewColorMatrixFilter
	NewBlurFilter                = filter.NewBlurFilter
	NewOutlineFilter             = filter.NewOutlineFilter
	NewPixelPerfectOutlineFilter = filter.NewPixelPerfectOutlineFilter
	NewPixelPerfectInlineFilter  = filter.NewPixelPerfectInlineFilter
	NewPaletteFilter             = filter.NewPaletteFilter
	NewCustomShaderFilter        = filter.NewCustomShaderFilter
)

Filter constructors.

View Source
var (
	NewRope            = mesh.NewRope
	NewDistortionGrid  = mesh.NewDistortionGrid
	NewPolygon         = mesh.NewPolygon
	NewRegularPolygon  = mesh.NewRegularPolygon
	NewStar            = mesh.NewStar
	NewPolygonTextured = mesh.NewPolygonTextured
	SetPolygonPoints   = mesh.SetPolygonPoints
)

Mesh constructors.

View Source
var (
	TweenPosition = core.TweenPosition
	TweenScale    = core.TweenScale
	TweenColor    = core.TweenColor
	TweenAlpha    = core.TweenAlpha
	TweenRotation = core.TweenRotation
)

Tweens.

View Source
var DefaultFXAAConfig = render.DefaultFXAAConfig

DefaultFXAAConfig returns an FXAAConfig with FXAA 3.11 quality-15 defaults.

View Source
var LoadTestScript = core.LoadTestScript

Test runner.

View Source
var NewLightLayer = lighting.NewLightLayer

Lighting.

View Source
var NewNodeIndex = node.NewNodeIndex

Node index.

View Source
var NewRenderTexture = render.NewRenderTexture

Render.

View Source
var ToTexture = core.ToTexture

Render to texture.

View Source
var WhitePixel *ebiten.Image

WhitePixel is a 1x1 white image used by default for solid color sprites.

Functions

func LoadFontFromPathAsTtf

func LoadFontFromPathAsTtf(path string) ([]byte, error)

LoadFontFromPathAsTtf reads a TTF/OTF file from disk.

func LoadFontFromSystemAsTtf

func LoadFontFromSystemAsTtf(name string) ([]byte, error)

LoadFontFromSystemAsTtf searches OS system font directories for a font by name.

func Run

func Run(scene *Scene, cfg RunConfig) error

Run is a convenience entry point that creates an Ebitengine game loop around the given Scene.

Types

type AnimFrame

type AnimFrame = tilemap.AnimFrame

AnimFrame describes a single frame in a tile animation sequence.

type Atlas

type Atlas = atlas.Atlas

Atlas holds one or more atlas page images and a map of named regions.

func LoadSceneAtlas

func LoadSceneAtlas(s *Scene, jsonData []byte, pages []*ebiten.Image) (*Atlas, error)

LoadSceneAtlas parses TexturePacker JSON, registers atlas pages with the scene, and returns the Atlas for region lookups.

type BatchMode

type BatchMode = render.BatchMode

BatchMode controls how the render pipeline submits draw calls.

type BlendMode

type BlendMode = types.BlendMode

BlendMode selects a compositing operation.

type BlurFilter

type BlurFilter = filter.BlurFilter

BlurFilter applies a Kawase iterative blur.

type CacheTreeMode

type CacheTreeMode = types.CacheTreeMode

CacheTreeMode controls how a cached subtree invalidates.

type CallbackHandle

type CallbackHandle = input.CallbackHandle

CallbackHandle allows removing a registered scene-level callback.

type Camera

type Camera = camera.Camera

Camera controls the view into the scene: position, zoom, rotation, viewport.

func Cameras

func Cameras(s *Scene) []*Camera

Cameras returns the scene's camera list.

func NewCamera

func NewCamera(viewport Rect) *Camera

NewCamera creates a standalone camera with the given viewport.

type ClickContext

type ClickContext = node.ClickContext

ClickContext carries click event data.

type Color

type Color = types.Color

Color represents an RGBA color with components in [0, 1].

func RGBA

func RGBA(r, g, b, a float64) Color

RGBA creates a Color from red, green, blue, alpha components in [0, 1].

type ColorMatrixFilter

type ColorMatrixFilter = filter.ColorMatrixFilter

ColorMatrixFilter applies a 4x5 color matrix transformation.

type CommandType

type CommandType = render.CommandType

CommandType identifies the kind of render command.

type CustomShaderFilter

type CustomShaderFilter = filter.CustomShaderFilter

CustomShaderFilter wraps a user-provided Kage shader.

type DistanceFieldFont

type DistanceFieldFont = text.DistanceFieldFont

DistanceFieldFont renders text from a pre-generated SDF or MSDF atlas.

func NewFontFromTTF

func NewFontFromTTF(ttfData []byte, size float64) (*DistanceFieldFont, error)

NewFontFromTTF generates an SDF font from TTF/OTF data, registers the atlas page, and returns the font ready to use.

func NewFontFromTTFOpts

func NewFontFromTTFOpts(ttfData []byte, opts SDFGenOptions) (*DistanceFieldFont, error)

NewFontFromTTFOpts generates an SDF font using explicit SDFGenOptions.

type DistortionGrid

type DistortionGrid = mesh.DistortionGrid

DistortionGrid provides a grid mesh that can be deformed per-vertex.

type DragContext

type DragContext = node.DragContext

DragContext carries drag event data.

type EaseFunc

type EaseFunc = ease.TweenFunc

EaseFunc is the signature for easing functions used by TweenConfig.

var (
	EaseLinear       EaseFunc = ease.Linear
	EaseInQuad       EaseFunc = ease.InQuad
	EaseOutQuad      EaseFunc = ease.OutQuad
	EaseInOutQuad    EaseFunc = ease.InOutQuad
	EaseOutInQuad    EaseFunc = ease.OutInQuad
	EaseInCubic      EaseFunc = ease.InCubic
	EaseOutCubic     EaseFunc = ease.OutCubic
	EaseInOutCubic   EaseFunc = ease.InOutCubic
	EaseOutInCubic   EaseFunc = ease.OutInCubic
	EaseInQuart      EaseFunc = ease.InQuart
	EaseOutQuart     EaseFunc = ease.OutQuart
	EaseInOutQuart   EaseFunc = ease.InOutQuart
	EaseOutInQuart   EaseFunc = ease.OutInQuart
	EaseInQuint      EaseFunc = ease.InQuint
	EaseOutQuint     EaseFunc = ease.OutQuint
	EaseInOutQuint   EaseFunc = ease.InOutQuint
	EaseOutInQuint   EaseFunc = ease.OutInQuint
	EaseInSine       EaseFunc = ease.InSine
	EaseOutSine      EaseFunc = ease.OutSine
	EaseInOutSine    EaseFunc = ease.InOutSine
	EaseOutInSine    EaseFunc = ease.OutInSine
	EaseInExpo       EaseFunc = ease.InExpo
	EaseOutExpo      EaseFunc = ease.OutExpo
	EaseInOutExpo    EaseFunc = ease.InOutExpo
	EaseOutInExpo    EaseFunc = ease.OutInExpo
	EaseInCirc       EaseFunc = ease.InCirc
	EaseOutCirc      EaseFunc = ease.OutCirc
	EaseInOutCirc    EaseFunc = ease.InOutCirc
	EaseOutInCirc    EaseFunc = ease.OutInCirc
	EaseInElastic    EaseFunc = ease.InElastic
	EaseOutElastic   EaseFunc = ease.OutElastic
	EaseInOutElastic EaseFunc = ease.InOutElastic
	EaseOutInElastic EaseFunc = ease.OutInElastic
	EaseInBack       EaseFunc = ease.InBack
	EaseOutBack      EaseFunc = ease.OutBack
	EaseInOutBack    EaseFunc = ease.InOutBack
	EaseOutInBack    EaseFunc = ease.OutInBack
	EaseInBounce     EaseFunc = ease.InBounce
	EaseOutBounce    EaseFunc = ease.OutBounce
	EaseInOutBounce  EaseFunc = ease.InOutBounce
	EaseOutInBounce  EaseFunc = ease.OutInBounce
)

type EmitterConfig

type EmitterConfig = particle.EmitterConfig

EmitterConfig controls how particles are spawned and behave.

type EntityStore

type EntityStore = core.EntityStore

EntityStore is the interface for optional ECS integration.

type EventType

type EventType = types.EventType

EventType identifies a kind of interaction event.

type FXAAConfig

type FXAAConfig = render.FXAAConfig

FXAAConfig holds tunable parameters for the FXAA post-process pass. Use DefaultFXAAConfig for sensible defaults.

type Filter

type Filter = filter.Filter

Filter is the interface for visual effects applied to a node.

type Font

type Font = text.Font

Font is the interface for text measurement and layout.

type Glyph

type Glyph = text.Glyph

Glyph holds glyph metrics and atlas position.

type GlyphBitmap

type GlyphBitmap = text.GlyphBitmap

GlyphBitmap holds a rasterized glyph and its metrics for atlas packing.

type HitCircle

type HitCircle = input.HitCircle

HitCircle is a circular hit area in local coordinates.

type HitPolygon

type HitPolygon = input.HitPolygon

HitPolygon is a convex polygon hit area in local coordinates.

type HitRect

type HitRect = input.HitRect

HitRect is an axis-aligned rectangular hit area in local coordinates.

type HitShape

type HitShape = types.HitShape

HitShape is implemented by custom hit-test shapes attached to a Node.

type InteractionEvent

type InteractionEvent = core.InteractionEvent

InteractionEvent carries interaction data for the ECS bridge.

type KeyModifiers

type KeyModifiers = types.KeyModifiers

KeyModifiers is a bitmask of keyboard modifier keys.

type Light

type Light = lighting.Light

Light represents a light source in a LightLayer.

type LightLayer

type LightLayer = lighting.LightLayer

LightLayer provides a convenient 2D lighting effect using erase blending.

type MouseButton

type MouseButton = types.MouseButton

MouseButton identifies a mouse button.

type Node

type Node = node.Node

Node is the fundamental scene graph element.

func NewCircle

func NewCircle(name string, radius float64, c Color) *Node

NewCircle creates a solid-color circle node with the given radius. The circle is approximated with 32 segments.

func NewContainer

func NewContainer(name string) *Node

NewContainer creates a container node with no visual representation.

func NewLine

func NewLine(name string, x1, y1, x2, y2, thickness float64, c Color) *Node

NewLine creates a solid-color line node between two points with a given thickness. The line is built as a thin rotated rectangle sprite for efficient batching.

func NewMesh

func NewMesh(name string, img *ebiten.Image, vertices []ebiten.Vertex, indices []uint16) *Node

NewMesh creates a mesh node that uses DrawTriangles for rendering.

func NewParticleEmitter

func NewParticleEmitter(name string, cfg EmitterConfig) *Node

NewParticleEmitter creates a particle emitter node with a preallocated pool.

func NewRect

func NewRect(name string, w, h float64, c Color) *Node

NewRect creates a solid-color rectangle node.

func NewSprite

func NewSprite(name string, region TextureRegion) *Node

NewSprite creates a sprite node that renders a texture region.

func NewText

func NewText(name string, content string, font Font) *Node

NewText creates a text node that renders the given string using font.

func NewTriangle

func NewTriangle(name string, p1, p2, p3 Vec2, c Color) *Node

NewTriangle creates a solid-color triangle node from three points.

func Root

func Root(s *Scene) *Node

Root returns the scene's root container node.

type NodeIndex

type NodeIndex = node.NodeIndex

NodeIndex is an opt-in registry for looking up nodes by name or tag.

type NodeType

type NodeType = types.NodeType

NodeType distinguishes rendering behavior for a Node.

type OutlineFilter

type OutlineFilter = filter.OutlineFilter

OutlineFilter draws a multi-pixel outline around the source.

type PackerConfig

type PackerConfig = atlas.PackerConfig

PackerConfig controls the dynamic atlas packer.

type PaletteFilter

type PaletteFilter = filter.PaletteFilter

PaletteFilter remaps pixel colors through a palette based on luminance.

type ParticleEmitter

type ParticleEmitter = particle.Emitter

ParticleEmitter manages a pool of particles with CPU-based simulation.

type PinchContext

type PinchContext = node.PinchContext

PinchContext carries two-finger pinch/rotate gesture data.

type PixelFont

type PixelFont = text.PixelFont

PixelFont is a pixel-perfect bitmap font renderer.

func NewPixelFont

func NewPixelFont(img *ebiten.Image, cellW, cellH int, chars string) *PixelFont

NewPixelFont creates a pixel font from a spritesheet image.

type PixelPerfectInlineFilter

type PixelPerfectInlineFilter = filter.PixelPerfectInlineFilter

PixelPerfectInlineFilter recolors edge pixels via Kage shader.

type PixelPerfectOutlineFilter

type PixelPerfectOutlineFilter = filter.PixelPerfectOutlineFilter

PixelPerfectOutlineFilter draws a 1-pixel outline via Kage shader.

type PointerContext

type PointerContext = node.PointerContext

PointerContext carries pointer event data.

type Range

type Range = types.Range

Range is a general-purpose min/max range.

type Rect

type Rect = types.Rect

Rect is an axis-aligned rectangle (origin top-left, Y down).

type RenderCommand

type RenderCommand = render.RenderCommand

RenderCommand is a single draw instruction emitted during scene traversal.

type RenderTexture

type RenderTexture = render.RenderTexture

RenderTexture is a persistent offscreen canvas.

type RenderTextureDrawOpts

type RenderTextureDrawOpts = render.RenderTextureDrawOpts

RenderTextureDrawOpts controls how an image or sprite is drawn onto a RenderTexture.

type Rope

type Rope = mesh.Rope

Rope generates a ribbon/rope mesh that follows a polyline path.

type RopeConfig

type RopeConfig = mesh.RopeConfig

RopeConfig configures a Rope mesh.

type RopeCurveMode

type RopeCurveMode = mesh.RopeCurveMode

RopeCurveMode selects the curve algorithm used by Rope.Update().

type RopeJoinMode

type RopeJoinMode = mesh.RopeJoinMode

RopeJoinMode controls how segments join in a Rope mesh.

type RunConfig

type RunConfig struct {
	Title         string
	Width, Height int
	Background    Color
	ShowFPS       bool
	// FXAA enables full-screen fast approximate anti-aliasing as a post-process
	// pass. Nil disables FXAA. Use DefaultFXAAConfig() for sensible defaults.
	FXAA *FXAAConfig
}

RunConfig holds optional configuration for Run.

type SDFGenOptions

type SDFGenOptions = text.SDFGenOptions

SDFGenOptions configures SDF atlas generation.

type Scene

type Scene = core.Scene

Scene is the top-level object that owns the node tree, cameras, input state, and render buffers.

func NewScene

func NewScene() *Scene

NewScene creates a new scene with a pre-created root container.

type TestRunner

type TestRunner = core.TestRunner

TestRunner sequences injected input events and screenshots across frames.

type TextAlign

type TextAlign = types.TextAlign

TextAlign controls horizontal text alignment within a TextBlock.

type TextBlock

type TextBlock = text.TextBlock

TextBlock holds text content, formatting, and cached layout state.

type TextEffects

type TextEffects = text.TextEffects

TextEffects configures text effects (outline, glow, shadow).

type TextureRegion

type TextureRegion = types.TextureRegion

TextureRegion describes a sub-rectangle within an atlas page.

type TileLayerConfig

type TileLayerConfig = tilemap.LayerConfig

TileLayerConfig holds the parameters for creating a tile layer.

type TileMapLayer

type TileMapLayer = tilemap.Layer

TileMapLayer is a single layer of tile data.

type TileMapViewport

type TileMapViewport = tilemap.Viewport

TileMapViewport is a scene graph node that manages a viewport into a tilemap.

func NewTileMapViewport

func NewTileMapViewport(name string, tileWidth, tileHeight int) *TileMapViewport

NewTileMapViewport creates a new tilemap viewport node.

type TweenConfig

type TweenConfig = types.TweenConfig

TweenConfig holds the duration and easing function for a tween.

type TweenGroup

type TweenGroup = core.TweenGroup

TweenGroup animates up to 4 float64 fields on a Node simultaneously.

type Vec2

type Vec2 = types.Vec2

Vec2 is a 2D vector.

Directories

Path Synopsis
cmd
hellodemo command
examples
atlas command
Atlas demonstrates the TexturePacker atlas system and dynamic page registration.
Atlas demonstrates the TexturePacker atlas system and dynamic page registration.
basic command
Basic demonstrates a minimal willow scene with a colored sprite bouncing around the window.
Basic demonstrates a minimal willow scene with a colored sprite bouncing around the window.
filtergallery command
Filter Gallery showcases every built-in Willow filter applied to a whelp sprite.
Filter Gallery showcases every built-in Willow filter applied to a whelp sprite.
interaction command
Interaction demonstrates draggable colored rectangles with click callbacks using willow.Run for a minimal game loop.
Interaction demonstrates draggable colored rectangles with click callbacks using willow.Run for a minimal game loop.
lighting command
Lighting Demo showcases the LightLayer system in a dark dungeon scene.
Lighting Demo showcases the LightLayer system in a dark dungeon scene.
masks command
Masks demonstrates three node-masking techniques in Willow across three equal full-height panels:
Masks demonstrates three node-masking techniques in Willow across three equal full-height panels:
outline command
Outline demonstrates outline and inline filters applied to a sprite with alpha transparency (whelp.png).
Outline demonstrates outline and inline filters applied to a sprite with alpha transparency (whelp.png).
particles command
Particles demonstrates the ParticleEmitter system with three distinct effects and two blend modes.
Particles demonstrates the ParticleEmitter system with three distinct effects and two blend modes.
physics command
physics spawns random shapes with gravity, collisions, and click-to-explode.
physics spawns random shapes with gravity, collisions, and click-to-explode.
rope command
Rope demonstrates the Rope mesh helper by connecting two draggable nodes with a textured rope that sags under gravity.
Rope demonstrates the Rope mesh helper by connecting two draggable nodes with a textured rope that sags under gravity.
ropegarden command
Rope Garden - a cable-untangling puzzle.
Rope Garden - a cable-untangling puzzle.
shaders command
Shaders showcases Willow's built-in filter system by displaying all shader effects simultaneously in a 3x3 grid, each applied to a pre-rendered tilemap panel with animated parameters.
Shaders showcases Willow's built-in filter system by displaying all shader effects simultaneously in a 3x3 grid, each applied to a pre-rendered tilemap panel with animated parameters.
shapes command
Shapes demonstrates scene graph hierarchy with polygons and containers.
Shapes demonstrates scene graph hierarchy with polygons and containers.
sprites10k command
sprites10k spawns 10,000 whelp sprites that rotate, scale, fade, and bounce around the screen simultaneously.
sprites10k spawns 10,000 whelp sprites that rotate, scale, fade, and bounce around the screen simultaneously.
text command
Text demonstrates font rendering with willow.NewText and willow.NewFontFromTTF.
Text demonstrates font rendering with willow.NewText and willow.NewFontFromTTF.
text-pixelfont command
Text-pixelfont demonstrates pixel-perfect bitmap font rendering using willow.NewPixelFont.
Text-pixelfont demonstrates pixel-perfect bitmap font rendering using willow.NewPixelFont.
tilemap command
Tilemap demonstrates a grid-based tilemap with camera panning.
Tilemap demonstrates a grid-based tilemap with camera panning.
tilemapviewport command
TileMapViewport demonstrates the geometry-buffer tilemap renderer with camera panning, multiple tile layers, and a sandwich entity layer.
TileMapViewport demonstrates the geometry-buffer tilemap renderer with camera panning, multiple tile layers, and a sandwich entity layer.
tweengallery command
Tween Gallery showcases every easing function available in Willow's tween system.
Tween Gallery showcases every easing function available in Willow's tween system.
tweens command
Tweens demonstrates the tween animation system using tiles from the shared tileset.
Tweens demonstrates the tween animation system using tiles from the shared tileset.
underwater command
Underwater demonstrates a layered underwater scene revealed through a circular porthole mask that follows the cursor.
Underwater demonstrates a layered underwater scene revealed through a circular porthole mask that follows the cursor.
watermesh command
Watermesh demonstrates per-vertex wave animation using a DistortionGrid textured with tile 13 (the water tile) from the bundled tileset.
Watermesh demonstrates per-vertex wave animation using a DistortionGrid textured with tile 13 (the water tile) from the bundled tileset.
internal
integration
Package integration contains integration tests for the willow engine.
Package integration contains integration tests for the willow engine.

Jump to

Keyboard shortcuts

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