Documentation
¶
Overview ¶
Package willow is a retained-mode 2D game framework for Ebitengine.
Willow provides the scene graph, transform hierarchy, sprite batching, input handling, camera viewports, text rendering, and particle systems that every non-trivial 2D game needs.
Game loop ¶
There are two ways to integrate Willow into your game.
The simplest 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,
})
Register a callback with Scene.SetUpdateFunc to run your game logic each tick:
scene.SetUpdateFunc(func() error {
dt := float32(1.0 / float64(ebiten.TPS()))
myTween.Update(dt)
hero.X += speed
hero.Invalidate()
return nil
})
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 }
Both approaches are fully supported. Run is a thin wrapper around ebiten.RunGame — it does not add hidden behavior.
Nodes and the scene graph ¶
Every visual element is a Node. Nodes form a tree rooted at Scene.Root. Children inherit their parent's transform (position, rotation, scale, skew) and alpha.
Create nodes with the typed constructors:
- NewContainer — group node, no visual output
- NewSprite — renders a TextureRegion (or a solid color via WhitePixel)
- NewText — renders text using a BitmapFont or TTFFont
- NewParticleEmitter — CPU-simulated particle system
- NewMesh — low-level DrawTriangles
- NewPolygon / NewPolygonTextured — filled polygon helper
Add nodes to the tree with Node.AddChild:
container := willow.NewContainer("ui")
scene.Root().AddChild(container)
btn := willow.NewSprite("btn", willow.TextureRegion{})
btn.X, btn.Y = 100, 50
container.AddChild(btn)
Sprites and solid colors ¶
NewSprite with a zero-value TextureRegion produces a 1x1 white pixel. Use [Node.ScaleX], [Node.ScaleY], and [Node.Color] to turn it into a solid-color rectangle of any size:
box := willow.NewSprite("box", willow.TextureRegion{})
box.ScaleX = 80
box.ScaleY = 40
box.Color = willow.Color{R: 0.3, G: 0.7, B: 1, A: 1}
For atlas-based sprites, load a TexturePacker JSON with LoadAtlas and look up regions by name:
atlas, _ := willow.LoadAtlas(jsonBytes, pages)
hero := willow.NewSprite("hero", atlas.Region("hero_idle"))
Transforms ¶
Each node has local transform fields: X, Y, ScaleX, ScaleY, Rotation, SkewX, SkewY, PivotX, PivotY. World transforms are computed lazily via dirty-flag propagation — static subtrees skip recomputation entirely.
Call Node.Invalidate after changing a transform field at runtime (X, Y, Rotation, etc.) to ensure the change takes effect:
sprite.X += 5 sprite.Invalidate()
PivotX and PivotY set the transform origin as a fraction of the node's size (0.5, 0.5 = center). By default pivots are (0, 0) meaning the top-left corner.
Cameras and viewports ¶
A Camera defines a viewport rectangle on screen and a position in world space. Create cameras with Scene.NewCamera:
cam := scene.NewCamera(willow.Rect{X: 0, Y: 0, Width: 640, Height: 480})
cam.X = worldCenterX
cam.Y = worldCenterY
cam.Invalidate()
Cameras support smooth follow, animated scroll-to with 45+ easing functions, zoom, rotation, bounds clamping, and frustum culling. Convert between coordinate spaces with Camera.WorldToScreen and Camera.ScreenToWorld.
When no cameras are created, the scene renders with a default 1:1 mapping from world to screen coordinates.
Interaction and input ¶
Set [Node.Interactable] to true and assign a HitShape to make a node respond to pointer input. Assign callback functions directly to node fields:
btn.Interactable = true
btn.HitShape = willow.HitRect{Width: 80, Height: 40}
btn.OnClick = func(ctx willow.ClickContext) {
fmt.Println("clicked at", ctx.WorldX, ctx.WorldY)
}
btn.OnDrag = func(ctx willow.DragContext) {
btn.X += ctx.DeltaX
btn.Y += ctx.DeltaY
btn.Invalidate()
}
Available callbacks: OnPointerDown, OnPointerUp, OnPointerMove, OnClick, OnDragStart, OnDrag, OnDragEnd, OnPinch, OnPointerEnter, OnPointerLeave.
Hit testing runs in reverse painter order (front-to-back). Built-in hit shapes are HitRect, HitCircle, and HitPolygon.
Per-node update callbacks ¶
Each node has an [Node.OnUpdate] callback that fires every frame during Scene.Update. Use it for self-contained per-node logic like spinning, bobbing, or AI:
sprite.OnUpdate = func(dt float64) {
sprite.Rotation += 0.02
}
Filters and visual effects ¶
Assign a slice of Filter implementations to [Node.Filters] to apply shader effects. Filters are applied in order during rendering:
sprite.Filters = []willow.Filter{
willow.NewBlurFilter(3),
willow.NewOutlineFilter(2, willow.Color{R: 1, G: 1, B: 0, A: 1}),
}
Built-in filters: ColorMatrixFilter (brightness, contrast, saturation, and arbitrary 4x5 matrix), BlurFilter, OutlineFilter, PixelPerfectOutlineFilter, PixelPerfectInlineFilter, PaletteFilter, and CustomShaderFilter for user-provided Kage shaders.
Nodes can also be cached as textures (Node.SetCacheAsTexture) or masked by another node (Node.SetMask).
Animation and tweens ¶
Willow includes tween helpers built on gween:
tween := willow.TweenPosition(sprite, 500, 300, 1.5, ease.OutBounce)
Advance tweens manually each frame:
dt := float32(1.0 / float64(ebiten.TPS()))
tween.Update(dt)
if tween.Done { /* finished */ }
Convenience constructors: TweenPosition, TweenScale, TweenRotation, TweenAlpha, TweenColor. Tweens automatically stop if their target node is disposed.
There is no global tween manager — you own the TweenGroup values and call Update yourself, giving you full control over timing and lifetime.
Text rendering ¶
Create text nodes with NewText and either a BitmapFont (pixel-perfect BMFont .fnt files) or a TTFFont (Ebitengine text/v2 wrapper):
font, _ := willow.LoadBitmapFont(fntData, pageImages)
label := willow.NewText("title", "Hello Willow", font)
label.TextBlock.Align = willow.TextAlignCenter
label.TextBlock.WrapWidth = 200
Particles ¶
Create emitters with NewParticleEmitter and an EmitterConfig:
emitter := willow.NewParticleEmitter("sparks", willow.EmitterConfig{
MaxParticles: 200,
EmitRate: 60,
Lifetime: willow.Range{Min: 0.5, Max: 1.5},
Speed: willow.Range{Min: 50, Max: 150},
})
scene.Root().AddChild(emitter)
emitter.Emitter.Start()
Particles are CPU-simulated in Update (not Draw) with preallocated pools. Set WorldSpace to true in the config to emit particles in world coordinates instead of local to the emitter.
Meshes and polygons ¶
For custom geometry, use NewMesh with vertex and index buffers, or the higher-level helpers:
- NewPolygon — solid-color convex polygon
- NewPolygonTextured — textured convex polygon
- NewRope — textured ribbon along a point path
- NewDistortionGrid — deformable texture grid
Blend modes ¶
Set [Node.BlendMode] to control compositing. Available modes: BlendNormal (default source-over), BlendAdd, BlendMultiply, BlendScreen, BlendErase, BlendMask, BlendBelow, BlendNone.
Draw ordering ¶
Siblings are drawn in child-list order by default. Use Node.SetZIndex to reorder among siblings without changing the tree. For coarser control, [Node.RenderLayer] provides a primary sort key across the entire scene.
Lighting ¶
A LightLayer creates a dark overlay with soft circles of light cut through it. Add the layer as the topmost scene node so it composites over all content:
ll := willow.NewLightLayer(640, 480, 0.9) // ambientAlpha: 1=black, 0=fully lit scene.Root().AddChild(ll.Node())
Add point lights with LightLayer.AddLight:
torch := &willow.Light{
X: 200, Y: 300,
Radius: 120, Intensity: 1.0,
Color: willow.Color{R: 1, G: 0.7, B: 0.3, A: 1},
Enabled: true,
}
ll.AddLight(torch)
To attach a light to a moving node, set [Light.Target] instead of fixed X/Y coordinates. Call LightLayer.Redraw each frame to rebuild the light texture before Scene.Draw.
ECS integration ¶
Set a node's [Node.EntityID] and call Scene.SetEntityStore with an EntityStore implementation. Interaction events are forwarded as InteractionEvent values, bridging the scene graph into your entity-component system. A Donburi adapter ships in the willow/ecs submodule.
Subtree command caching ¶
Node.SetCacheAsTree caches all render commands emitted by a container's subtree. On subsequent frames the cached commands are replayed with a delta transform remap instead of walking the tree — the CPU cost drops from O(N) traversal to O(N) memcpy with a matrix multiply per command.
Camera panning, parent movement, and parent alpha changes are handled automatically via delta remapping and never invalidate the cache.
Two modes are available:
- CacheTreeAuto (default) — setters on descendant nodes auto-invalidate the cache. Always correct, small per-setter overhead.
- CacheTreeManual — only Node.InvalidateCacheTree triggers a rebuild. Zero setter overhead. Best for large tilemaps where the developer knows exactly when tiles change.
Basic usage:
tilemap := willow.NewContainer("tilemap")
for _, tile := range tiles {
tilemap.AddChild(tile)
}
tilemap.SetCacheAsTree(true) // auto mode (default)
For maximum performance with large tilemaps:
tilemap.SetCacheAsTree(true, willow.CacheTreeManual) // ... later, when tiles change: tilemap.InvalidateCacheTree()
Animated tiles (texture swaps) ¶
Animated tiles (water, lava, torches) that swap UV coordinates on the same atlas page work without cache invalidation. The first Node.SetTextureRegion call with a same-page region automatically registers the node as "animated" — subsequent replays read the live TextureRegion from the node instead of the cached snapshot:
// waterTile is a child of a cached tilemap container. // This does NOT invalidate the cache: waterTile.SetTextureRegion(waterFrames[frame])
Changing to a different atlas page does invalidate the cache, since page changes affect batch keys. All animation frames for a tile should be on the same atlas page (TexturePacker typically does this automatically for related frames).
When to use SetCacheAsTree ¶
The cache stores commands per-container. Any mutation to a child invalidates the entire container's cache (in auto mode) or produces stale output (in manual mode until you call InvalidateCacheTree).
This makes it ideal for large, mostly-static subtrees:
- Tilemaps (thousands of tiles, camera scrolling every frame)
- Static UI panels (dozens of widgets, occasionally updated)
- Background decoration layers
It is NOT useful for containers where children move individually every frame — one child's Node.SetPosition dirties the whole container, so you pay rebuild cost plus cache management overhead.
The recommended pattern is to separate static and dynamic content:
// Cached: 10K tiles, camera scrolls for free
tilemap := willow.NewContainer("tilemap")
tilemap.SetCacheAsTree(true, willow.CacheTreeManual)
// NOT cached: entities move every frame
entities := willow.NewContainer("entities")
scene.Root().AddChild(tilemap)
scene.Root().AddChild(entities)
Mesh nodes and particle emitters inside a cached subtree block caching — the cache stays dirty and falls back to normal traversal. Move particles and meshes to a separate uncached container.
SetCacheAsTree vs SetCacheAsTexture ¶
Willow has two user-facing caching mechanisms:
- Node.SetCacheAsTree skips CPU traversal. Output is N render commands replayed from cache. Pixel-perfect at any zoom. Animated tiles work for free.
- Node.SetCacheAsTexture skips GPU draw calls. Output is a single texture. Blurs if zoomed past cached resolution. Best for filtered/masked nodes and complex visual effects.
Performance ¶
Willow targets zero heap allocations per frame on the hot path. Render commands, sort buffers, and vertex arrays are preallocated and reused. Dirty flags skip transform recomputation for static subtrees. Typed callback slices avoid interface boxing in event dispatch.
Caching strategy ¶
Willow provides two caching mechanisms that solve different bottlenecks. Choosing the right one (or combining both) is the single biggest lever for frame-time optimization.
SetCacheAsTree — skip CPU traversal ¶
Node.SetCacheAsTree stores the render commands emitted by a container's subtree and replays them on subsequent frames with a matrix multiply per command instead of re-walking the tree. This targets CPU time: the traversal, transform computation, and command emission for N children collapse to a memcpy + delta remap.
When to use it:
- Large, mostly-static containers (tilemaps, background layers, UI panels)
- Scenes where the camera scrolls every frame but the content does not move
- Containers with animated tiles that swap UV coordinates on the same atlas page
When NOT to use it:
- Containers where many children move individually every frame — one child's Node.SetPosition invalidates the entire container's cache (auto mode) or produces stale output (manual mode)
- Containers that hold mesh nodes or particle emitters — these block caching entirely and fall back to normal traversal
Two modes are available:
- CacheTreeAuto (default) — descendant setters auto-invalidate the cache. Always correct, small per-setter overhead. Good for UI panels that update occasionally.
- CacheTreeManual — only Node.InvalidateCacheTree triggers a rebuild. Zero setter overhead. Best for large tilemaps where you control exactly when tiles change.
Setup example (tilemap with animated water):
tilemap := willow.NewContainer("tilemap")
tilemap.SetCacheAsTree(true, willow.CacheTreeManual)
for _, tile := range tiles {
tilemap.AddChild(tile)
}
scene.Root().AddChild(tilemap)
// Animate water tiles every N frames — does NOT invalidate the cache
// because the UV swap stays on the same atlas page:
waterTile.SetTextureRegion(waterFrames[frame])
// If you add/remove tiles at runtime, invalidate manually:
tilemap.InvalidateCacheTree()
Caveats:
- The cache is per-container. Separate static content (tilemaps) from dynamic content (players, projectiles) into different containers.
- Mesh and particle emitter children block caching — move them to an uncached sibling container.
- Changing a tile's texture to a different atlas page invalidates the cache because page changes affect batch keys. Keep all animation frames on the same atlas page.
- In manual mode, forgetting to call Node.InvalidateCacheTree after structural changes (AddChild, RemoveChild, SetVisible) produces stale visual output. Prefer auto mode unless profiling shows the setter overhead matters.
Benchmark results (10K sprites):
Manual cache, camera scrolling ~39 µs (~125x faster than uncached) Manual cache, 100 animated UV swaps ~1.97 ms (~2.5x faster) Auto cache, 1% children moving ~4.0 ms (~1.2x faster) No cache (baseline) ~4.9 ms
SetCacheAsTexture — skip GPU draw calls ¶
Node.SetCacheAsTexture renders a node's entire subtree to an offscreen image once, then draws that single texture on subsequent frames. This targets GPU draw-call count: N children become one textured quad.
When to use it:
- Nodes with expensive filter chains (blur, outline, palette swap) — the filter is applied once and the result is reused
- Complex visual effects that combine masking and filters
- Small, visually-rich subtrees where draw-call reduction matters more than pixel-perfect scaling
When NOT to use it:
- Large scrolling tilemaps — the texture is rasterized at a fixed resolution and will blur if the camera zooms in past that resolution
- Subtrees that change frequently — every change requires a full re-render to the offscreen texture
- Nodes that need pixel-perfect rendering at varying zoom levels
Setup example (filtered badge):
badge := willow.NewContainer("badge")
badge.AddChild(icon)
badge.AddChild(label)
badge.Filters = []willow.Filter{
willow.NewOutlineFilter(2, willow.Color{R: 1, G: 1, B: 0, A: 1}),
}
badge.SetCacheAsTexture(true)
scene.Root().AddChild(badge)
// When the badge content changes, invalidate:
badge.InvalidateCache()
Caveats:
- The offscreen texture is allocated at the subtree's bounding-box size (rounded up to the next power of two). Very large subtrees consume significant GPU memory.
- Zooming the camera past the cached resolution produces blurry output. If the camera zooms dynamically, prefer Node.SetCacheAsTree instead.
- The texture is re-rendered from scratch on invalidation — there is no partial update. Frequent invalidation can be worse than no caching.
Choosing between the two ¶
Use Node.SetCacheAsTree when the bottleneck is CPU traversal of large static subtrees (tilemaps, backgrounds). The output is N render commands replayed from cache — still pixel-perfect at any zoom, animated tiles work for free, and camera movement never invalidates.
Use Node.SetCacheAsTexture when the bottleneck is GPU draw calls or filter cost. The output is a single textured quad — minimal GPU work, but locked to a fixed resolution.
They can be combined: a tilemap container uses SetCacheAsTree for fast traversal, while a filtered HUD badge inside it uses SetCacheAsTexture to avoid re-applying shaders every frame.
Recommended scene layout for performance ¶
Organize your scene tree to maximize cache effectiveness:
scene.Root()
├── tilemap (SetCacheAsTree, manual mode — thousands of tiles)
├── entities (NO cache — players, enemies, projectiles move every frame)
├── particles (NO cache — emitters block tree caching)
└── ui (SetCacheAsTree, auto mode — panels that update occasionally)
└── badge (SetCacheAsTexture — filtered, rarely changes)
Index ¶
- Variables
- func NewDistortionGrid(name string, img *ebiten.Image, cols, rows int) (*DistortionGrid, *Node)
- func NewRope(name string, img *ebiten.Image, points []Vec2, cfg RopeConfig) (*Rope, *Node)
- func Run(scene *Scene, cfg RunConfig) error
- func SetPolygonPoints(n *Node, points []Vec2)
- type AnimFrame
- type Atlas
- type BatchMode
- type BitmapFont
- type BlendMode
- type BlurFilter
- type CacheTreeMode
- type CallbackHandle
- type Camera
- func (c *Camera) ClampToBounds()
- func (c *Camera) ClearBounds()
- func (c *Camera) Follow(node *Node, offsetX, offsetY, lerp float64)
- func (c *Camera) Invalidate()
- func (c *Camera) ScreenToWorld(sx, sy float64) (wx, wy float64)
- func (c *Camera) ScrollTo(x, y float64, duration float32, easeFn ease.TweenFunc)
- func (c *Camera) ScrollToTile(tileX, tileY int, tileW, tileH float64, duration float32, ...)
- func (c *Camera) SetBounds(bounds Rect)
- func (c *Camera) Unfollow()
- func (c *Camera) VisibleBounds() Rect
- func (c *Camera) WorldToScreen(wx, wy float64) (sx, sy float64)
- type ClickContext
- type Color
- type ColorMatrixFilter
- type CommandType
- type CustomShaderFilter
- type DistortionGrid
- func (g *DistortionGrid) Cols() int
- func (g *DistortionGrid) Node() *Node
- func (g *DistortionGrid) Reset()
- func (g *DistortionGrid) Rows() int
- func (g *DistortionGrid) SetAllVertices(fn func(col, row int, restX, restY float64) (dx, dy float64))
- func (g *DistortionGrid) SetVertex(col, row int, dx, dy float64)
- type DragContext
- type EmitterConfig
- type EntityStore
- type EventType
- type Filter
- type Font
- type HitCircle
- type HitPolygon
- type HitRect
- type HitShape
- type InteractionEvent
- type KeyModifiers
- type Light
- type LightLayer
- func (ll *LightLayer) AddLight(l *Light)
- func (ll *LightLayer) AmbientAlpha() float64
- func (ll *LightLayer) ClearLights()
- func (ll *LightLayer) Dispose()
- func (ll *LightLayer) Lights() []*Light
- func (ll *LightLayer) Node() *Node
- func (ll *LightLayer) Redraw()
- func (ll *LightLayer) RemoveLight(l *Light)
- func (ll *LightLayer) RenderTexture() *RenderTexture
- func (ll *LightLayer) SetAmbientAlpha(a float64)
- func (ll *LightLayer) SetCircleRadius(radius float64)
- func (ll *LightLayer) SetPages(pages []*ebiten.Image)
- type MouseButton
- type Node
- func NewContainer(name string) *Node
- func NewFPSWidget() *Node
- func NewMesh(name string, img *ebiten.Image, vertices []ebiten.Vertex, indices []uint16) *Node
- func NewParticleEmitter(name string, cfg EmitterConfig) *Node
- func NewPolygon(name string, points []Vec2) *Node
- func NewPolygonTextured(name string, img *ebiten.Image, points []Vec2) *Node
- func NewSprite(name string, region TextureRegion) *Node
- func NewText(name string, content string, font Font) *Node
- func (n *Node) AddChild(child *Node)
- func (n *Node) AddChildAt(child *Node, index int)
- func (n *Node) ChildAt(index int) *Node
- func (n *Node) Children() []*Node
- func (n *Node) ClearMask()
- func (n *Node) CustomImage() *ebiten.Image
- func (n *Node) Dispose()
- func (n *Node) GetMask() *Node
- func (n *Node) Invalidate()
- func (n *Node) InvalidateCache()
- func (n *Node) InvalidateCacheTree()
- func (n *Node) InvalidateMeshAABB()
- func (n *Node) IsCacheAsTreeEnabled() bool
- func (n *Node) IsCacheEnabled() bool
- func (n *Node) IsDisposed() bool
- func (n *Node) LocalToWorld(lx, ly float64) (wx, wy float64)
- func (n *Node) NumChildren() int
- func (n *Node) RemoveChild(child *Node)
- func (n *Node) RemoveChildAt(index int) *Node
- func (n *Node) RemoveChildren()
- func (n *Node) RemoveFromParent()
- func (n *Node) SetAlpha(a float64)
- func (n *Node) SetBlendMode(b BlendMode)
- func (n *Node) SetCacheAsTexture(enabled bool)
- func (n *Node) SetCacheAsTree(enabled bool, mode ...CacheTreeMode)
- func (n *Node) SetChildIndex(child *Node, index int)
- func (n *Node) SetColor(c Color)
- func (n *Node) SetCustomImage(img *ebiten.Image)
- func (n *Node) SetGlobalOrder(o int)
- func (n *Node) SetMask(maskNode *Node)
- func (n *Node) SetPivot(px, py float64)
- func (n *Node) SetPosition(x, y float64)
- func (n *Node) SetRenderLayer(l uint8)
- func (n *Node) SetRenderable(r bool)
- func (n *Node) SetRotation(r float64)
- func (n *Node) SetScale(sx, sy float64)
- func (n *Node) SetSkew(sx, sy float64)
- func (n *Node) SetTextureRegion(r TextureRegion)
- func (n *Node) SetVisible(v bool)
- func (n *Node) SetZIndex(z int)
- func (n *Node) ToTexture(s *Scene) *ebiten.Image
- func (n *Node) WorldToLocal(wx, wy float64) (lx, ly float64)
- type NodeType
- type Outline
- type OutlineFilter
- type PaletteFilter
- type ParticleEmitter
- type PinchContext
- type PixelPerfectInlineFilter
- type PixelPerfectOutlineFilter
- type PointerContext
- type Range
- type Rect
- type RenderCommand
- type RenderTexture
- func (rt *RenderTexture) Clear()
- func (rt *RenderTexture) Dispose()
- func (rt *RenderTexture) DrawImage(src *ebiten.Image, op *ebiten.DrawImageOptions)
- func (rt *RenderTexture) DrawImageAt(src *ebiten.Image, x, y float64, blend BlendMode)
- func (rt *RenderTexture) DrawImageColored(img *ebiten.Image, opts RenderTextureDrawOpts)
- func (rt *RenderTexture) DrawSprite(region TextureRegion, x, y float64, blend BlendMode, pages []*ebiten.Image)
- func (rt *RenderTexture) DrawSpriteColored(region TextureRegion, opts RenderTextureDrawOpts, pages []*ebiten.Image)
- func (rt *RenderTexture) Fill(c Color)
- func (rt *RenderTexture) Height() int
- func (rt *RenderTexture) Image() *ebiten.Image
- func (rt *RenderTexture) NewSpriteNode(name string) *Node
- func (rt *RenderTexture) Resize(width, height int)
- func (rt *RenderTexture) Width() int
- type RenderTextureDrawOpts
- type Rope
- type RopeConfig
- type RopeCurveMode
- type RopeJoinMode
- type RunConfig
- type Scene
- func (s *Scene) Cameras() []*Camera
- func (s *Scene) CapturePointer(pointerID int, node *Node)
- func (s *Scene) Draw(screen *ebiten.Image)
- func (s *Scene) GetBatchMode() BatchMode
- func (s *Scene) InjectClick(x, y float64)
- func (s *Scene) InjectDrag(fromX, fromY, toX, toY float64, frames int)
- func (s *Scene) InjectMove(x, y float64)
- func (s *Scene) InjectPress(x, y float64)
- func (s *Scene) InjectRelease(x, y float64)
- func (s *Scene) LoadAtlas(jsonData []byte, pages []*ebiten.Image) (*Atlas, error)
- func (s *Scene) NewCamera(viewport Rect) *Camera
- func (s *Scene) OnClick(fn func(ClickContext)) CallbackHandle
- func (s *Scene) OnDrag(fn func(DragContext)) CallbackHandle
- func (s *Scene) OnDragEnd(fn func(DragContext)) CallbackHandle
- func (s *Scene) OnDragStart(fn func(DragContext)) CallbackHandle
- func (s *Scene) OnPinch(fn func(PinchContext)) CallbackHandle
- func (s *Scene) OnPointerDown(fn func(PointerContext)) CallbackHandle
- func (s *Scene) OnPointerEnter(fn func(PointerContext)) CallbackHandle
- func (s *Scene) OnPointerLeave(fn func(PointerContext)) CallbackHandle
- func (s *Scene) OnPointerMove(fn func(PointerContext)) CallbackHandle
- func (s *Scene) OnPointerUp(fn func(PointerContext)) CallbackHandle
- func (s *Scene) RegisterPage(index int, img *ebiten.Image)
- func (s *Scene) ReleasePointer(pointerID int)
- func (s *Scene) RemoveCamera(cam *Camera)
- func (s *Scene) Root() *Node
- func (s *Scene) Screenshot(label string)
- func (s *Scene) SetBatchMode(mode BatchMode)
- func (s *Scene) SetDebugMode(enabled bool)
- func (s *Scene) SetDragDeadZone(pixels float64)
- func (s *Scene) SetEntityStore(store EntityStore)
- func (s *Scene) SetPostDrawFunc(fn func(screen *ebiten.Image))
- func (s *Scene) SetTestRunner(runner *TestRunner)
- func (s *Scene) SetUpdateFunc(fn func() error)
- func (s *Scene) Update()
- type TTFFont
- type TestRunner
- type TextAlign
- type TextBlock
- type TextureRegion
- type TileMapLayer
- type TileMapViewport
- type TweenGroup
- func TweenAlpha(node *Node, to float64, duration float32, fn ease.TweenFunc) *TweenGroup
- func TweenColor(node *Node, to Color, duration float32, fn ease.TweenFunc) *TweenGroup
- func TweenPosition(node *Node, toX, toY float64, duration float32, fn ease.TweenFunc) *TweenGroup
- func TweenRotation(node *Node, to float64, duration float32, fn ease.TweenFunc) *TweenGroup
- func TweenScale(node *Node, toSX, toSY float64, duration float32, fn ease.TweenFunc) *TweenGroup
- type Vec2
Constants ¶
This section is empty.
Variables ¶
var ColorWhite = Color{1, 1, 1, 1}
ColorWhite is the default tint (no color modification).
var WhitePixel *ebiten.Image
WhitePixel is a 1x1 white image used by default for solid color sprites.
Functions ¶
func NewDistortionGrid ¶
NewDistortionGrid creates a grid mesh over the given image. cols and rows define the number of cells (vertices = (cols+1) * (rows+1)).
func NewRope ¶
NewRope creates a rope mesh node that renders a textured ribbon along the given points. The image is tiled along the path (SrcX) and spans the full image height (SrcY).
func Run ¶
Run is a convenience entry point that creates an Ebitengine game loop around the given Scene. It configures the window and calls ebiten.RunGame.
For full control over the game loop, skip Run and implement ebiten.Game yourself, calling Scene.Update and Scene.Draw directly.
func SetPolygonPoints ¶
SetPolygonPoints updates the polygon's vertices. Maintains fan triangulation. If textured is true and img is non-nil, UVs are mapped to the bounding box.
Types ¶
type AnimFrame ¶ added in v0.1.3
type AnimFrame struct {
GID uint32 // tile GID for this frame (no flag bits)
Duration int // milliseconds
}
AnimFrame describes a single frame in a tile animation sequence.
type Atlas ¶
type Atlas struct {
// Pages contains the atlas page images indexed by page number.
Pages []*ebiten.Image
// contains filtered or unexported fields
}
Atlas holds one or more atlas page images and a map of named regions.
func LoadAtlas ¶
LoadAtlas parses TexturePacker JSON data and associates the given page images. Supports both the hash format (single "frames" object) and the array format ("textures" array with per-page frame lists).
func (*Atlas) Region ¶
func (a *Atlas) Region(name string) TextureRegion
Region returns the TextureRegion for the given name. If the name doesn't exist, it logs a warning (debug stderr) and returns a 1×1 magenta placeholder region on page index magentaPlaceholderPage.
type BatchMode ¶ added in v0.1.2
type BatchMode uint8
BatchMode controls how the render pipeline submits draw calls.
type BitmapFont ¶
type BitmapFont struct {
// contains filtered or unexported fields
}
BitmapFont renders text from pre-rasterized glyph atlases in BMFont format.
func LoadBitmapFont ¶
func LoadBitmapFont(fntData []byte) (*BitmapFont, error)
LoadBitmapFont parses BMFont .fnt text-format data. The page index defaults to 0. Register the atlas page image on the Scene via Scene.RegisterPage.
func LoadBitmapFontPage ¶
func LoadBitmapFontPage(fntData []byte, pageIndex uint16) (*BitmapFont, error)
LoadBitmapFontPage parses BMFont .fnt text-format data with an explicit page index.
func (*BitmapFont) LineHeight ¶
func (f *BitmapFont) LineHeight() float64
LineHeight returns the vertical distance between baselines.
func (*BitmapFont) MeasureString ¶
func (f *BitmapFont) MeasureString(s string) (width, height float64)
MeasureString returns the width and height of the rendered text.
type BlendMode ¶
type BlendMode uint8
BlendMode selects a compositing operation. Each maps to a specific ebiten.Blend value.
const ( BlendNormal BlendMode = iota // source-over (standard alpha blending) BlendAdd // additive / lighter BlendMultiply // multiply (source * destination; only darkens) BlendScreen // screen (1 - (1-src)*(1-dst); only brightens) BlendErase // destination-out (punch transparent holes) BlendMask // clip destination to source alpha BlendBelow // destination-over (draw behind existing content) BlendNone // opaque copy (skip blending) )
func (BlendMode) EbitenBlend ¶
EbitenBlend returns the ebiten.Blend value corresponding to this BlendMode.
type BlurFilter ¶
type BlurFilter struct {
Radius int
// contains filtered or unexported fields
}
BlurFilter applies a Kawase iterative blur using downscale/upscale passes. No Kage shader needed — bilinear filtering during DrawImage does the work.
func NewBlurFilter ¶
func NewBlurFilter(radius int) *BlurFilter
NewBlurFilter creates a blur filter with the given radius (in pixels).
func (*BlurFilter) Apply ¶
func (f *BlurFilter) Apply(src, dst *ebiten.Image)
Apply renders a Kawase blur from src into dst using iterative downscale/upscale.
func (*BlurFilter) Padding ¶
func (f *BlurFilter) Padding() int
Padding returns the blur radius; the offscreen buffer is expanded to avoid clipping.
type CacheTreeMode ¶ added in v0.1.2
type CacheTreeMode uint8
CacheTreeMode controls how a SetCacheAsTree node detects stale caches.
const ( // CacheTreeManual requires the user to call InvalidateCacheTree() when // the subtree changes. Zero overhead on setters. Best for large tilemaps. CacheTreeManual CacheTreeMode = iota + 1 // CacheTreeAuto (the default) auto-invalidates the cache when setters on // descendant nodes are called. Small per-setter overhead. Always correct. CacheTreeAuto )
type CallbackHandle ¶
type CallbackHandle struct {
// contains filtered or unexported fields
}
CallbackHandle allows removing a registered scene-level callback.
func (CallbackHandle) Remove ¶
func (h CallbackHandle) Remove()
Remove unregisters this callback so it no longer fires. The entry is removed from the slice to avoid nil iteration waste.
type Camera ¶
type Camera struct {
// X and Y are the world-space position the camera centers on.
X, Y float64
// Zoom is the scale factor (1.0 = no zoom, >1 = zoom in, <1 = zoom out).
Zoom float64
// Rotation is the camera rotation in radians (clockwise).
Rotation float64
// Viewport is the screen-space rectangle this camera renders into.
Viewport Rect
// CullEnabled skips nodes whose world AABB doesn't intersect the
// camera's visible bounds.
CullEnabled bool
// BoundsEnabled clamps the camera position so the visible area stays
// within Bounds.
BoundsEnabled bool
// Bounds is the world-space rectangle the camera is clamped to when
// BoundsEnabled is true.
Bounds Rect
// contains filtered or unexported fields
}
Camera controls the view into the scene: position, zoom, rotation, and viewport.
func (*Camera) ClampToBounds ¶ added in v0.1.3
func (c *Camera) ClampToBounds()
ClampToBounds immediately clamps the camera position so the visible area stays within Bounds. Call this after modifying X/Y directly (e.g. in a drag callback) to prevent a single frame where the camera sees outside the bounds. No-op if BoundsEnabled is false.
func (*Camera) ClearBounds ¶
func (c *Camera) ClearBounds()
ClearBounds disables camera bounds clamping.
func (*Camera) Follow ¶
Follow makes the camera track a target node with the given offset and lerp factor. A lerp of 1.0 snaps immediately; lower values give smoother following.
func (*Camera) Invalidate ¶ added in v0.1.3
func (c *Camera) Invalidate()
Invalidate forces a recomputation of the view matrix.
func (*Camera) ScreenToWorld ¶
ScreenToWorld converts screen coordinates to world coordinates.
func (*Camera) ScrollTo ¶
ScrollTo animates the camera to the given world position over duration seconds.
func (*Camera) ScrollToTile ¶
func (c *Camera) ScrollToTile(tileX, tileY int, tileW, tileH float64, duration float32, easeFn ease.TweenFunc)
ScrollToTile scrolls to the center of the given tile in a tile-based layout.
func (*Camera) Unfollow ¶
func (c *Camera) Unfollow()
Unfollow stops tracking the current target node.
func (*Camera) VisibleBounds ¶
VisibleBounds returns the axis-aligned bounding rect of the camera's visible area in world space.
func (*Camera) WorldToScreen ¶
WorldToScreen converts world coordinates to screen coordinates.
type ClickContext ¶
type ClickContext struct {
Node *Node // the clicked node
EntityID uint32 // the clicked node's EntityID (for ECS bridging)
UserData any // the clicked node's UserData
GlobalX float64 // click X in world coordinates
GlobalY float64 // click Y in world coordinates
LocalX float64 // click X in the node's local coordinates
LocalY float64 // click Y in the node's local coordinates
Button MouseButton // which mouse button was clicked
PointerID int // 0 = mouse, 1-9 = touch contacts
Modifiers KeyModifiers // keyboard modifier keys held during the click
}
ClickContext carries click event data passed to click callbacks.
type Color ¶
type Color struct {
R, G, B, A float64
}
Color represents an RGBA color with components in [0, 1]. Not premultiplied. Premultiplication occurs at render submission time.
type ColorMatrixFilter ¶
type ColorMatrixFilter struct {
Matrix [20]float64
// contains filtered or unexported fields
}
ColorMatrixFilter applies a 4x5 color matrix transformation using a Kage shader. The matrix is stored in row-major order: [R_r, R_g, R_b, R_a, R_offset, G_r, ...].
func NewColorMatrixFilter ¶
func NewColorMatrixFilter() *ColorMatrixFilter
NewColorMatrixFilter creates a color matrix filter initialized to the identity.
func (*ColorMatrixFilter) Apply ¶
func (f *ColorMatrixFilter) Apply(src, dst *ebiten.Image)
Apply renders the color matrix transformation from src into dst.
func (*ColorMatrixFilter) Padding ¶
func (f *ColorMatrixFilter) Padding() int
Padding returns 0; color matrix transforms don't expand the image bounds.
func (*ColorMatrixFilter) SetBrightness ¶
func (f *ColorMatrixFilter) SetBrightness(b float64)
SetBrightness sets the matrix to adjust brightness by the given offset [-1, 1].
func (*ColorMatrixFilter) SetContrast ¶
func (f *ColorMatrixFilter) SetContrast(c float64)
SetContrast sets the matrix to adjust contrast. c=1 is normal, 0=gray, >1 is higher.
func (*ColorMatrixFilter) SetSaturation ¶
func (f *ColorMatrixFilter) SetSaturation(s float64)
SetSaturation sets the matrix to adjust saturation. s=1 is normal, 0=grayscale.
type CommandType ¶
type CommandType uint8
CommandType identifies the kind of render command.
const ( CommandSprite CommandType = iota // DrawImage CommandMesh // DrawTriangles CommandParticle // particle quads (batches as sprites) CommandTilemap // DrawTriangles for tilemap layers )
type CustomShaderFilter ¶
type CustomShaderFilter struct {
Shader *ebiten.Shader
Uniforms map[string]any
Images [3]*ebiten.Image
// contains filtered or unexported fields
}
CustomShaderFilter wraps a user-provided Kage shader, exposing Ebitengine's shader system directly. Images[0] is auto-filled with the source texture; the user may set Images[1] and Images[2] for additional textures.
func NewCustomShaderFilter ¶
func NewCustomShaderFilter(shader *ebiten.Shader, padding int) *CustomShaderFilter
NewCustomShaderFilter creates a custom shader filter with the given shader and padding.
func (*CustomShaderFilter) Apply ¶
func (f *CustomShaderFilter) Apply(src, dst *ebiten.Image)
Apply runs the user-provided Kage shader with src as Images[0].
func (*CustomShaderFilter) Padding ¶
func (f *CustomShaderFilter) Padding() int
Padding returns the padding value set at construction time.
type DistortionGrid ¶
type DistortionGrid struct {
// contains filtered or unexported fields
}
DistortionGrid provides a grid mesh that can be deformed per-vertex.
func (*DistortionGrid) Cols ¶
func (g *DistortionGrid) Cols() int
Cols returns the number of grid columns.
func (*DistortionGrid) Node ¶
func (g *DistortionGrid) Node() *Node
Node returns the underlying mesh node.
func (*DistortionGrid) Reset ¶
func (g *DistortionGrid) Reset()
Reset returns all vertices to their original positions.
func (*DistortionGrid) Rows ¶
func (g *DistortionGrid) Rows() int
Rows returns the number of grid rows.
func (*DistortionGrid) SetAllVertices ¶
func (g *DistortionGrid) SetAllVertices(fn func(col, row int, restX, restY float64) (dx, dy float64))
SetAllVertices calls fn for each vertex, passing (col, row, restX, restY). fn returns the (dx, dy) displacement from the rest position.
func (*DistortionGrid) SetVertex ¶
func (g *DistortionGrid) SetVertex(col, row int, dx, dy float64)
SetVertex offsets a single grid vertex by (dx, dy) from its rest position.
type DragContext ¶
type DragContext struct {
Node *Node // the node being dragged
EntityID uint32 // the dragged node's EntityID (for ECS bridging)
UserData any // the dragged node's UserData
GlobalX float64 // current pointer X in world coordinates
GlobalY float64 // current pointer Y in world coordinates
LocalX float64 // current pointer X in the node's local coordinates
LocalY float64 // current pointer Y in the node's local coordinates
StartX float64 // world X where the drag began
StartY float64 // world Y where the drag began
DeltaX float64 // X movement since the previous drag event
DeltaY float64 // Y movement since the previous drag event
ScreenDeltaX float64 // X movement in screen pixels since the previous drag event
ScreenDeltaY float64 // Y movement in screen pixels since the previous drag event
Button MouseButton // which mouse button initiated the drag
PointerID int // 0 = mouse, 1-9 = touch contacts
Modifiers KeyModifiers // keyboard modifier keys held during the drag
}
DragContext carries drag event data passed to drag callbacks.
type EmitterConfig ¶
type EmitterConfig struct {
// MaxParticles is the pool size. New particles are silently dropped when full.
MaxParticles int
// EmitRate is the number of particles spawned per second.
EmitRate float64
// Lifetime is the range of particle lifetimes in seconds.
Lifetime Range
// Speed is the range of initial particle speeds in pixels per second.
Speed Range
// Angle is the range of emission angles in radians.
Angle Range
// StartScale is the range of scale factors at birth, interpolated to EndScale over lifetime.
StartScale Range
// EndScale is the range of scale factors at death.
EndScale Range
// StartAlpha is the range of alpha values at birth, interpolated to EndAlpha over lifetime.
StartAlpha Range
// EndAlpha is the range of alpha values at death.
EndAlpha Range
// Gravity is the constant acceleration applied to all particles each frame.
Gravity Vec2
// StartColor is the tint at birth, interpolated to EndColor over lifetime.
StartColor Color
// EndColor is the tint at death.
EndColor Color
// Region is the TextureRegion used to render each particle.
Region TextureRegion
// BlendMode is the compositing operation for particle rendering.
BlendMode BlendMode
// WorldSpace, when true, causes particles to keep their world position
// once emitted rather than following the emitter node.
WorldSpace bool
}
EmitterConfig controls how particles are spawned and behave.
type EntityStore ¶
type EntityStore interface {
// EmitEvent delivers an interaction event to the ECS.
EmitEvent(event InteractionEvent)
}
EntityStore is the interface for optional ECS integration. When set on a Scene via SetEntityStore, interaction events on nodes with a non-zero EntityID are forwarded to the ECS.
type EventType ¶
type EventType uint8
EventType identifies a kind of interaction event.
const ( EventPointerDown EventType = iota // fires when a pointer button is pressed EventPointerUp // fires when a pointer button is released EventPointerMove // fires when the pointer moves (hover, no button) EventClick // fires on press then release over the same node EventDragStart // fires when movement exceeds the drag dead zone EventDrag // fires each frame while dragging EventDragEnd // fires when the pointer is released after dragging EventPinch // fires during a two-finger pinch/rotate gesture EventPointerEnter // fires when the pointer enters a node's bounds EventPointerLeave // fires when the pointer leaves a node's bounds )
type Filter ¶
type Filter interface {
// Apply renders src into dst with the filter effect.
Apply(src, dst *ebiten.Image)
// Padding returns the extra pixels needed around the source to accommodate
// the effect (e.g. blur radius, outline thickness). Zero means no padding.
Padding() int
}
Filter is the interface for visual effects applied to a node's rendered output.
type Font ¶
type Font interface {
// MeasureString returns the pixel width and height of the rendered text,
// accounting for newlines and the font's line height.
MeasureString(text string) (width, height float64)
// LineHeight returns the vertical distance between baselines in pixels.
LineHeight() float64
}
Font is the interface for text measurement and layout. Implemented by BitmapFont and TTFFont.
type HitCircle ¶
type HitCircle struct {
CenterX, CenterY, Radius float64
}
HitCircle is a circular hit area in local coordinates.
type HitPolygon ¶
type HitPolygon struct {
Points []Vec2
}
HitPolygon is a convex polygon hit area in local coordinates. Points must define a convex polygon in either winding order. Concave polygons will produce incorrect results.
func (HitPolygon) Contains ¶
func (p HitPolygon) Contains(x, y float64) bool
Contains reports whether (x, y) lies inside a convex polygon using cross-product sign test.
type HitRect ¶
type HitRect struct {
X, Y, Width, Height float64
}
HitRect is an axis-aligned rectangular hit area in local coordinates.
type HitShape ¶
type HitShape interface {
// Contains reports whether the local-space point (x, y) is inside the shape.
Contains(x, y float64) bool
}
HitShape defines a custom hit testing region in local coordinates. Implement this interface and assign it to Node.HitShape to override the default axis-aligned bounding box test.
type InteractionEvent ¶
type InteractionEvent struct {
Type EventType // which kind of interaction occurred
EntityID uint32 // the ECS entity associated with the hit node
GlobalX float64 // pointer X in world coordinates
GlobalY float64 // pointer Y in world coordinates
LocalX float64 // pointer X in the hit node's local coordinates
LocalY float64 // pointer Y in the hit node's local coordinates
Button MouseButton // which mouse button is involved
Modifiers KeyModifiers // keyboard modifier keys held during the event
// Drag fields (valid for EventDragStart, EventDrag, EventDragEnd)
StartX float64 // world X where the drag began
StartY float64 // world Y where the drag began
DeltaX float64 // X movement since the previous drag event
DeltaY float64 // Y movement since the previous drag event
ScreenDeltaX float64 // X movement in screen pixels since the previous drag event
ScreenDeltaY float64 // Y movement in screen pixels since the previous drag event
// Pinch fields (valid for EventPinch)
Scale float64 // cumulative scale factor since pinch start
ScaleDelta float64 // frame-to-frame scale change
Rotation float64 // cumulative rotation in radians since pinch start
RotDelta float64 // frame-to-frame rotation change in radians
}
InteractionEvent carries interaction data for the ECS bridge.
type KeyModifiers ¶
type KeyModifiers uint8
KeyModifiers is a bitmask of keyboard modifier keys. Values can be combined with bitwise OR (e.g. ModShift | ModCtrl).
const ( ModShift KeyModifiers = 1 << iota // Shift key ModCtrl // Control key ModAlt // Alt / Option key ModMeta // Meta / Command / Windows key )
type Light ¶
type Light struct {
// X and Y are the light's position in the light layer's local coordinate space.
X, Y float64
// Radius controls the drawn size (diameter = Radius*2 pixels).
Radius float64
// Rotation is the light's rotation in radians; useful for directional shapes.
Rotation float64
// Intensity controls light brightness in the range [0, 1].
Intensity float64
// Enabled determines whether this light is drawn during Redraw.
// Disabled lights are skipped entirely.
Enabled bool
// Color is the tint color. Zero value or white means neutral (no tint).
Color Color
// TextureRegion, if non-zero, uses this sprite sheet region instead of
// the default feathered circle.
TextureRegion TextureRegion
// Target, if set, makes the light follow this node's pivot point each Redraw.
Target *Node
// OffsetX and OffsetY offset the light from the target's pivot in
// light-layer space.
OffsetX float64
OffsetY float64
}
Light represents a light source in a LightLayer.
type LightLayer ¶
type LightLayer struct {
// contains filtered or unexported fields
}
LightLayer provides a convenient 2D lighting effect using erase blending. It manages a set of lights, renders them into an offscreen texture filled with an ambient darkness color, and erases feathered circles at each light position. The resulting texture is displayed as a sprite node with BlendMultiply so it darkens the scene everywhere except where lights shine.
func NewLightLayer ¶
func NewLightLayer(w, h int, ambientAlpha float64) *LightLayer
NewLightLayer creates a light layer covering (w x h) pixels. ambientAlpha controls the base darkness (0 = fully transparent, 1 = fully opaque black).
func (*LightLayer) AddLight ¶
func (ll *LightLayer) AddLight(l *Light)
AddLight adds a light to the layer.
func (*LightLayer) AmbientAlpha ¶
func (ll *LightLayer) AmbientAlpha() float64
AmbientAlpha returns the current ambient darkness level.
func (*LightLayer) ClearLights ¶
func (ll *LightLayer) ClearLights()
ClearLights removes all lights from the layer.
func (*LightLayer) Dispose ¶
func (ll *LightLayer) Dispose()
Dispose releases all resources owned by the light layer.
func (*LightLayer) Lights ¶
func (ll *LightLayer) Lights() []*Light
Lights returns the current light list. The returned slice MUST NOT be mutated.
func (*LightLayer) Node ¶
func (ll *LightLayer) Node() *Node
Node returns the sprite node that displays the light layer. Add this to the scene graph to render the lighting effect.
func (*LightLayer) Redraw ¶
func (ll *LightLayer) Redraw()
Redraw fills the texture with ambient darkness then erases light shapes at each enabled light position. Lights with a TextureRegion use that sprite; lights without fall back to a generated feathered circle. Call this every frame (or whenever lights change) before drawing the scene.
func (*LightLayer) RemoveLight ¶
func (ll *LightLayer) RemoveLight(l *Light)
RemoveLight removes a light from the layer.
func (*LightLayer) RenderTexture ¶
func (ll *LightLayer) RenderTexture() *RenderTexture
RenderTexture returns the underlying RenderTexture.
func (*LightLayer) SetAmbientAlpha ¶
func (ll *LightLayer) SetAmbientAlpha(a float64)
SetAmbientAlpha sets the base darkness level.
func (*LightLayer) SetCircleRadius ¶
func (ll *LightLayer) SetCircleRadius(radius float64)
SetCircleRadius pre-generates a feathered circle texture at the given radius and stores it in the cache.
func (*LightLayer) SetPages ¶
func (ll *LightLayer) SetPages(pages []*ebiten.Image)
SetPages stores the atlas page images used to resolve Light.TextureRegion. Typically called with the Scene's pages after loading atlases.
type MouseButton ¶
type MouseButton uint8
MouseButton identifies a mouse button.
const ( MouseButtonLeft MouseButton = iota // primary (left) mouse button MouseButtonRight // secondary (right) mouse button MouseButtonMiddle // middle mouse button (scroll wheel click) )
type Node ¶
type Node struct {
// Visible controls whether this node and its subtree are drawn.
// An invisible node is also excluded from hit testing.
Visible bool
// Renderable controls whether this node emits render commands. When false
// the node is skipped during drawing but its children are still traversed.
Renderable bool
// Type determines how this node is rendered (container, sprite, mesh, etc.).
Type NodeType
// RenderLayer is the primary sort key for render commands.
// All commands in a lower layer draw before any command in a higher layer.
RenderLayer uint8
// BlendMode selects the compositing operation used when drawing this node.
BlendMode BlendMode
// Alpha is the node's opacity in [0, 1]. Multiplied with the parent's
// computed alpha, so children inherit transparency.
Alpha float64
// GlobalOrder is a secondary sort key within the same RenderLayer.
// Set it to override the default tree-order sorting.
GlobalOrder int
// TextureRegion identifies the sub-image within an atlas page to draw.
TextureRegion TextureRegion
// Color is a multiplicative tint applied to the sprite. The default
// {1,1,1,1} means no tint.
Color Color
// X and Y are the local-space position in pixels (origin at top-left, Y down).
X, Y float64
// ScaleX and ScaleY are the local scale factors (1.0 = no scaling).
ScaleX float64
ScaleY float64
// Rotation is the local rotation in radians (clockwise).
Rotation float64
// SkewX and SkewY are shear angles in radians.
SkewX, SkewY float64
// PivotX and PivotY are the transform origin in local pixels. Scale,
// rotation, and skew are applied around this point.
PivotX float64
PivotY float64
// Parent points to this node's parent, or nil for the root.
Parent *Node
// ID is a unique auto-assigned identifier (never zero for live nodes).
ID uint32
// ZIndex controls draw order among siblings. Higher values draw on top.
// Use SetZIndex to change this so the parent is notified to re-sort.
ZIndex int
// EntityID links this node to an ECS entity. When non-zero, interaction
// events on this node are forwarded to the Scene's EntityStore.
EntityID uint32
// Name is a human-readable label for debugging; not used for lookups.
Name string
// UserData is an arbitrary value the application can attach to a node.
UserData any
// Vertices holds the mesh vertex data for DrawTriangles.
Vertices []ebiten.Vertex
// Indices holds the triangle index list for DrawTriangles.
Indices []uint16
// MeshImage is the texture sampled by DrawTriangles.
MeshImage *ebiten.Image
// Emitter manages the particle pool and simulation for this node.
Emitter *ParticleEmitter
// TextBlock holds the text content, font, and cached layout state.
TextBlock *TextBlock
// OnUpdate is called once per tick during Scene.Update if set.
OnUpdate func(dt float64)
// Interactable controls whether this node responds to pointer events.
// When false the entire subtree is excluded from hit testing.
Interactable bool
// HitShape overrides the default AABB hit test with a custom shape.
// Nil means use the node's bounding box.
HitShape HitShape
// Filters is the chain of visual effects applied to this node's rendered
// output. Filters are applied in order; each reads from the previous
// result and writes to a new buffer.
Filters []Filter
// OnPointerDown fires when a pointer button is pressed over this node.
OnPointerDown func(PointerContext)
// OnPointerUp fires when a pointer button is released over this node.
OnPointerUp func(PointerContext)
// OnPointerMove fires when the pointer moves over this node (hover).
OnPointerMove func(PointerContext)
// OnClick fires on press then release over this node.
OnClick func(ClickContext)
// OnDragStart fires when a drag gesture begins on this node.
OnDragStart func(DragContext)
// OnDrag fires each frame while this node is being dragged.
OnDrag func(DragContext)
// OnDragEnd fires when a drag gesture ends on this node.
OnDragEnd func(DragContext)
// OnPinch fires during a two-finger pinch gesture over this node.
OnPinch func(PinchContext)
// OnPointerEnter fires when the pointer enters this node's bounds.
OnPointerEnter func(PointerContext)
// OnPointerLeave fires when the pointer leaves this node's bounds.
OnPointerLeave func(PointerContext)
// contains filtered or unexported fields
}
Node is the fundamental scene graph element. A single flat struct is used for all node types to avoid interface dispatch on the hot path.
Field order is performance-critical: the gc compiler lays out fields in declaration order. Hot-path fields (traverse, updateWorldTransform) are packed first so they share cache lines. Cold fields (callbacks, mesh data, metadata) are pushed to the tail. Do not reorder without benchmarking.
func NewContainer ¶
NewContainer creates a container node with no visual representation.
func NewFPSWidget ¶
func NewFPSWidget() *Node
NewFPSWidget creates a new Node that displays the current FPS and TPS. The widget is transparently updated every ~0.5 seconds. It uses a custom internal image and ebitenutil.DebugPrint for rendering.
func NewParticleEmitter ¶
func NewParticleEmitter(name string, cfg EmitterConfig) *Node
NewParticleEmitter creates a particle emitter node with a preallocated pool.
func NewPolygon ¶
NewPolygon creates an untextured polygon mesh from the given vertices. Uses fan triangulation (convex polygons). The polygon is drawn with a shared 1x1 white pixel image; color comes from the node's Color field.
func NewPolygonTextured ¶
NewPolygonTextured creates a textured polygon mesh. UVs are mapped to the bounding box of the points, so (0,0)→top-left and (imgW,imgH)→bottom-right.
func NewSprite ¶
func NewSprite(name string, region TextureRegion) *Node
NewSprite creates a sprite node that renders a texture region.
func NewText ¶
NewText creates a text node that renders the given string using font. The node's TextBlock is initialized with white color and dirty layout.
func (*Node) AddChild ¶
AddChild appends child to this node's children. If child already has a parent, it is removed from that parent first. Panics if child is nil or child is an ancestor of this node (cycle).
func (*Node) AddChildAt ¶
AddChildAt inserts child at the given index. Same reparenting and cycle-check behavior as AddChild.
func (*Node) ChildAt ¶
ChildAt returns the child at the given index. Panics if the index is out of range.
func (*Node) Children ¶
Children returns the child list. The returned slice MUST NOT be mutated by the caller.
func (*Node) CustomImage ¶
CustomImage returns the user-provided image, or nil if not set.
func (*Node) Dispose ¶
func (n *Node) Dispose()
Dispose removes this node from its parent, marks it as disposed, and recursively disposes all descendants.
func (*Node) Invalidate ¶ added in v0.1.3
func (n *Node) Invalidate()
Invalidate marks the node's transform and alpha as dirty, forcing recomputation on the next frame. Useful after bulk-setting fields directly.
func (*Node) InvalidateCache ¶
func (n *Node) InvalidateCache()
InvalidateCache marks the cached texture as dirty so it will be re-rendered on the next frame. No-op if caching is not enabled.
func (*Node) InvalidateCacheTree ¶ added in v0.1.2
func (n *Node) InvalidateCacheTree()
InvalidateCacheTree marks the cache as stale. Next Draw() re-traverses. Works with both Auto and Manual modes.
func (*Node) InvalidateMeshAABB ¶
func (n *Node) InvalidateMeshAABB()
InvalidateMeshAABB marks the mesh's cached AABB as needing recomputation. Call this after modifying Vertices.
func (*Node) IsCacheAsTreeEnabled ¶ added in v0.1.2
IsCacheAsTreeEnabled reports whether subtree command caching is enabled.
func (*Node) IsCacheEnabled ¶
IsCacheEnabled reports whether subtree caching is enabled for this node.
func (*Node) IsDisposed ¶
IsDisposed returns true if this node has been disposed.
func (*Node) LocalToWorld ¶
LocalToWorld converts a local-space point to world-space.
func (*Node) NumChildren ¶
NumChildren returns the number of children.
func (*Node) RemoveChild ¶
RemoveChild detaches child from this node. Panics if child.Parent != n.
func (*Node) RemoveChildAt ¶
RemoveChildAt removes and returns the child at the given index. Panics if the index is out of range.
func (*Node) RemoveChildren ¶
func (n *Node) RemoveChildren()
RemoveChildren detaches all children from this node. Children are NOT disposed.
func (*Node) RemoveFromParent ¶
func (n *Node) RemoveFromParent()
RemoveFromParent detaches this node from its parent. No-op if this node has no parent.
func (*Node) SetAlpha ¶
SetAlpha sets the node's alpha and marks it alpha-dirty. Unlike other transform setters, this only triggers a worldAlpha recomputation (a single multiply), skipping the full matrix recompute.
func (*Node) SetBlendMode ¶ added in v0.1.2
SetBlendMode sets the node's blend mode and invalidates ancestor static caches.
func (*Node) SetCacheAsTexture ¶
SetCacheAsTexture enables or disables caching of this node's subtree as a single texture. When enabled, the subtree is rendered to an offscreen image and reused across frames until InvalidateCache is called.
func (*Node) SetCacheAsTree ¶ added in v0.1.2
func (n *Node) SetCacheAsTree(enabled bool, mode ...CacheTreeMode)
SetCacheAsTree enables or disables subtree command caching. When enabled, traverse skips this node's subtree and replays cached commands. Camera movement is handled automatically via delta remapping.
Mode is optional and defaults to CacheTreeAuto (safe, always correct).
Modes:
CacheTreeAuto — (default) setters on descendant nodes auto-invalidate
the cache. Small per-setter overhead. Always correct.
CacheTreeManual — user calls InvalidateCacheTree() when subtree changes.
Zero overhead on setters. Best for large tilemaps where
the developer knows exactly when tiles change.
func (*Node) SetChildIndex ¶
SetChildIndex moves child to a new index among its siblings. Panics if child is not a child of n or if index is out of range.
func (*Node) SetColor ¶ added in v0.1.2
SetColor sets the node's tint color and invalidates ancestor static caches.
func (*Node) SetCustomImage ¶
SetCustomImage sets a user-provided *ebiten.Image to display instead of TextureRegion. Used by RenderTexture to attach a persistent offscreen canvas to a sprite node.
func (*Node) SetGlobalOrder ¶ added in v0.1.2
SetGlobalOrder sets the node's global order and invalidates ancestor static caches.
func (*Node) SetMask ¶
SetMask sets a mask node for this node. The mask node's alpha channel determines which parts of this node are visible. The mask node is NOT part of the scene tree — its transforms are relative to the masked node.
func (*Node) SetPosition ¶
SetPosition sets the node's local X and Y and marks it dirty.
func (*Node) SetRenderLayer ¶ added in v0.1.2
SetRenderLayer sets the node's render layer and invalidates ancestor static caches.
func (*Node) SetRenderable ¶ added in v0.1.2
SetRenderable sets whether the node emits render commands and invalidates ancestor static caches.
func (*Node) SetRotation ¶
SetRotation sets the node's rotation (in radians) and marks it dirty.
func (*Node) SetTextureRegion ¶ added in v0.1.2
func (n *Node) SetTextureRegion(r TextureRegion)
SetTextureRegion sets the node's texture region and invalidates ancestor caches. If the atlas page is unchanged (e.g. animated tile UV swap), the CacheAsTree cache is NOT invalidated — instead the node is registered as animated so replay reads the live TextureRegion. Page changes always invalidate.
func (*Node) SetVisible ¶ added in v0.1.2
SetVisible sets the node's visibility and invalidates ancestor caches.
func (*Node) SetZIndex ¶
SetZIndex sets the node's ZIndex and marks the parent's children as unsorted, so the next traversal will re-sort siblings by ZIndex.
func (*Node) ToTexture ¶
ToTexture renders this node's subtree to a new offscreen image and returns it. The caller owns the returned image (it is NOT pooled). Requires a Scene reference to use the render pipeline.
func (*Node) WorldToLocal ¶
WorldToLocal converts a world-space point to this node's local coordinate space.
type NodeType ¶
type NodeType uint8
NodeType distinguishes rendering behavior for a Node.
const ( NodeTypeContainer NodeType = iota // group node with no visual output NodeTypeSprite // renders a TextureRegion or custom image NodeTypeMesh // renders arbitrary triangles via DrawTriangles NodeTypeParticleEmitter // CPU-simulated particle system NodeTypeText // renders text via BitmapFont glyphs or TTF )
type OutlineFilter ¶
OutlineFilter draws the source in 8 cardinal/diagonal offsets with the outline color, then draws the original on top. Works at any thickness.
func NewOutlineFilter ¶
func NewOutlineFilter(thickness int, c Color) *OutlineFilter
NewOutlineFilter creates an outline filter.
func (*OutlineFilter) Apply ¶
func (f *OutlineFilter) Apply(src, dst *ebiten.Image)
Apply draws an 8-direction offset outline behind the source image.
func (*OutlineFilter) Padding ¶
func (f *OutlineFilter) Padding() int
Padding returns the outline thickness; the offscreen buffer is expanded by this amount.
type PaletteFilter ¶
type PaletteFilter struct {
Palette [256]Color
CycleOffset float64
// contains filtered or unexported fields
}
PaletteFilter remaps pixel colors through a 256-entry color palette based on luminance. Supports a cycle offset for palette animation.
func NewPaletteFilter ¶
func NewPaletteFilter() *PaletteFilter
NewPaletteFilter creates a palette filter with a default grayscale palette.
func (*PaletteFilter) Apply ¶
func (f *PaletteFilter) Apply(src, dst *ebiten.Image)
Apply remaps pixel colors through the palette based on luminance.
func (*PaletteFilter) Padding ¶
func (f *PaletteFilter) Padding() int
Padding returns 0; palette remapping doesn't expand the image bounds.
func (*PaletteFilter) SetPalette ¶
func (f *PaletteFilter) SetPalette(palette [256]Color)
SetPalette sets the palette colors and marks the texture for rebuild.
type ParticleEmitter ¶
type ParticleEmitter struct {
// contains filtered or unexported fields
}
ParticleEmitter manages a pool of particles with CPU-based simulation.
func (*ParticleEmitter) AliveCount ¶
func (e *ParticleEmitter) AliveCount() int
AliveCount returns the number of alive particles.
func (*ParticleEmitter) Config ¶
func (e *ParticleEmitter) Config() *EmitterConfig
Config returns a pointer to the emitter's config for live tuning.
func (*ParticleEmitter) IsActive ¶
func (e *ParticleEmitter) IsActive() bool
IsActive reports whether the emitter is currently emitting new particles.
func (*ParticleEmitter) Reset ¶
func (e *ParticleEmitter) Reset()
Reset stops emitting and kills all alive particles.
func (*ParticleEmitter) Stop ¶
func (e *ParticleEmitter) Stop()
Stop stops emitting new particles. Existing particles continue to live out.
type PinchContext ¶
type PinchContext struct {
CenterX, CenterY float64 // midpoint between the two touch points in world coordinates
Scale, ScaleDelta float64 // cumulative scale factor and frame-to-frame change
Rotation, RotDelta float64 // cumulative rotation (radians) and frame-to-frame change
}
PinchContext carries two-finger pinch/rotate gesture data.
type PixelPerfectInlineFilter ¶
type PixelPerfectInlineFilter struct {
Color Color
// contains filtered or unexported fields
}
PixelPerfectInlineFilter uses a Kage shader to recolor edge pixels that border transparent areas.
func NewPixelPerfectInlineFilter ¶
func NewPixelPerfectInlineFilter(c Color) *PixelPerfectInlineFilter
NewPixelPerfectInlineFilter creates a pixel-perfect inline filter.
func (*PixelPerfectInlineFilter) Apply ¶
func (f *PixelPerfectInlineFilter) Apply(src, dst *ebiten.Image)
Apply recolors edge pixels that border transparent areas via a Kage shader.
func (*PixelPerfectInlineFilter) Padding ¶
func (f *PixelPerfectInlineFilter) Padding() int
Padding returns 0; inlines only affect existing opaque pixels.
type PixelPerfectOutlineFilter ¶
type PixelPerfectOutlineFilter struct {
Color Color
// contains filtered or unexported fields
}
PixelPerfectOutlineFilter uses a Kage shader to draw a 1-pixel outline around non-transparent pixels by testing cardinal neighbors.
func NewPixelPerfectOutlineFilter ¶
func NewPixelPerfectOutlineFilter(c Color) *PixelPerfectOutlineFilter
NewPixelPerfectOutlineFilter creates a pixel-perfect outline filter.
func (*PixelPerfectOutlineFilter) Apply ¶
func (f *PixelPerfectOutlineFilter) Apply(src, dst *ebiten.Image)
Apply renders a 1-pixel outline via a Kage shader testing cardinal neighbors.
func (*PixelPerfectOutlineFilter) Padding ¶
func (f *PixelPerfectOutlineFilter) Padding() int
Padding returns 1; the outline extends 1 pixel beyond the source bounds.
type PointerContext ¶
type PointerContext struct {
Node *Node // the node under the pointer, or nil if none
EntityID uint32 // the hit node's EntityID (for ECS bridging)
UserData any // the hit node's UserData
GlobalX float64 // pointer X in world coordinates
GlobalY float64 // pointer Y in world coordinates
LocalX float64 // pointer X in the hit node's local coordinates
LocalY float64 // pointer Y in the hit node's local coordinates
Button MouseButton // which mouse button is involved
PointerID int // 0 = mouse, 1-9 = touch contacts
Modifiers KeyModifiers // keyboard modifier keys held during the event
}
PointerContext carries pointer event data passed to pointer callbacks.
type Range ¶
type Range struct {
Min, Max float64
}
Range is a general-purpose min/max range. Used by the particle system (EmitterConfig) and potentially other systems.
type Rect ¶
type Rect struct {
X, Y, Width, Height float64
}
Rect is an axis-aligned rectangle. The coordinate system has its origin at the top-left, with Y increasing downward.
func (Rect) Contains ¶
Contains reports whether the point (x, y) lies inside the rectangle. Points on the edge are considered inside.
func (Rect) Intersects ¶
Intersects reports whether r and other overlap. Adjacent rectangles (sharing only an edge) are considered intersecting.
type RenderCommand ¶
type RenderCommand struct {
Type CommandType
Transform [6]float32
TextureRegion TextureRegion
Color color32
BlendMode BlendMode
ShaderID uint16
TargetID uint16
RenderLayer uint8
GlobalOrder int
// contains filtered or unexported fields
}
RenderCommand is a single draw instruction emitted during scene traversal.
type RenderTexture ¶
type RenderTexture struct {
// contains filtered or unexported fields
}
RenderTexture is a persistent offscreen canvas that can be attached to a sprite node via SetCustomImage. Unlike pooled render targets used internally, a RenderTexture is owned by the caller and is NOT recycled between frames.
func NewRenderTexture ¶
func NewRenderTexture(w, h int) *RenderTexture
NewRenderTexture creates a persistent offscreen canvas of the given size.
func (*RenderTexture) Clear ¶
func (rt *RenderTexture) Clear()
Clear fills the texture with transparent black.
func (*RenderTexture) Dispose ¶
func (rt *RenderTexture) Dispose()
Dispose deallocates the underlying image. The RenderTexture should not be used after calling Dispose.
func (*RenderTexture) DrawImage ¶
func (rt *RenderTexture) DrawImage(src *ebiten.Image, op *ebiten.DrawImageOptions)
DrawImage draws src onto this texture using the provided options.
func (*RenderTexture) DrawImageAt ¶
func (rt *RenderTexture) DrawImageAt(src *ebiten.Image, x, y float64, blend BlendMode)
DrawImageAt draws src at the given position with the specified blend mode.
func (*RenderTexture) DrawImageColored ¶
func (rt *RenderTexture) DrawImageColored(img *ebiten.Image, opts RenderTextureDrawOpts)
DrawImageColored draws a raw *ebiten.Image with full transform, color, and alpha.
func (*RenderTexture) DrawSprite ¶
func (rt *RenderTexture) DrawSprite(region TextureRegion, x, y float64, blend BlendMode, pages []*ebiten.Image)
DrawSprite draws a TextureRegion from the atlas onto this texture at (x, y).
func (*RenderTexture) DrawSpriteColored ¶
func (rt *RenderTexture) DrawSpriteColored(region TextureRegion, opts RenderTextureDrawOpts, pages []*ebiten.Image)
DrawSpriteColored draws a TextureRegion with full transform, color, and alpha.
func (*RenderTexture) Fill ¶
func (rt *RenderTexture) Fill(c Color)
Fill fills the entire texture with the given color.
func (*RenderTexture) Height ¶
func (rt *RenderTexture) Height() int
Height returns the texture height in pixels.
func (*RenderTexture) Image ¶
func (rt *RenderTexture) Image() *ebiten.Image
Image returns the underlying *ebiten.Image for direct manipulation.
func (*RenderTexture) NewSpriteNode ¶
func (rt *RenderTexture) NewSpriteNode(name string) *Node
NewSpriteNode creates a NodeTypeSprite with customImage pre-set to this texture. The returned node will display the RenderTexture contents.
func (*RenderTexture) Resize ¶
func (rt *RenderTexture) Resize(width, height int)
Resize deallocates the old image and creates a new one at the given dimensions.
func (*RenderTexture) Width ¶
func (rt *RenderTexture) Width() int
Width returns the texture width in pixels.
type RenderTextureDrawOpts ¶
type RenderTextureDrawOpts struct {
// X and Y are the draw position in pixels.
X, Y float64
// ScaleX and ScaleY are scale factors. Zero defaults to 1.0.
ScaleX, ScaleY float64
// Rotation is the rotation in radians (clockwise).
Rotation float64
// PivotX and PivotY are the transform origin for scale and rotation.
PivotX, PivotY float64
// Color is a multiplicative tint. Zero value defaults to white (no tint).
Color Color
// Alpha is the opacity multiplier. Zero defaults to 1.0 (fully opaque).
Alpha float64
// BlendMode selects the compositing operation.
BlendMode BlendMode
}
RenderTextureDrawOpts controls how an image or sprite is drawn onto a RenderTexture when using the "Colored" draw methods.
type Rope ¶
type Rope struct {
// contains filtered or unexported fields
}
Rope generates a ribbon/rope mesh that follows a polyline path.
func (*Rope) Config ¶ added in v0.1.1
func (r *Rope) Config() *RopeConfig
Config returns a pointer to the rope's configuration so callers can mutate fields directly before calling Update().
type RopeConfig ¶
type RopeConfig struct {
Width float64
JoinMode RopeJoinMode
CurveMode RopeCurveMode
Segments int // number of subdivisions (default 20)
// Endpoint positions (pointers). Update() dereferences these each call,
// so you can bind them once and mutate the underlying Vec2 freely.
Start *Vec2
End *Vec2
// Catenary sag in pixels (downward droop).
Sag float64
// Bézier control points (pointers). Quadratic uses Controls[0]; cubic uses both.
Controls [2]*Vec2
// Wave parameters.
Amplitude float64
Frequency float64 // cycles along the rope length
Phase float64 // phase offset in radians
// Custom callback. Receives a preallocated buffer; must return the slice to use.
PointsFunc func(buf []Vec2) []Vec2
}
RopeConfig configures a Rope mesh.
type RopeCurveMode ¶ added in v0.1.1
type RopeCurveMode uint8
RopeCurveMode selects the curve algorithm used by Rope.Update().
const ( // RopeCurveLine draws a straight line between Start and End. RopeCurveLine RopeCurveMode = iota // RopeCurveCatenary simulates a drooping rope with gravity sag. RopeCurveCatenary // RopeCurveQuadBezier uses a quadratic Bézier with one control point. RopeCurveQuadBezier // RopeCurveCubicBezier uses a cubic Bézier with two control points. RopeCurveCubicBezier // RopeCurveWave produces a sinusoidal wave along the line. RopeCurveWave // RopeCurveCustom calls a user-provided PointsFunc callback. RopeCurveCustom )
type RopeJoinMode ¶
type RopeJoinMode uint8
RopeJoinMode controls how segments join in a Rope mesh.
const ( // RopeJoinMiter extends segment corners to a sharp point. RopeJoinMiter RopeJoinMode = iota // RopeJoinBevel flattens corners by inserting extra vertices, avoiding spikes. RopeJoinBevel )
type RunConfig ¶
type RunConfig struct {
// Title sets the window title. Ignored on platforms without a title bar.
Title string
// Width and Height set the window size in device-independent pixels.
// If zero, defaults to 640x480.
Width, Height int
// ShowFPS enables a small FPS/TPS widget in the top-left corner.
ShowFPS bool
}
RunConfig holds optional configuration for Run.
type Scene ¶
type Scene struct {
// ClearColor is the background color used to fill the screen each frame
// when the scene is run via [Run]. If left at the zero value (transparent
// black), the screen is not filled, resulting in a black background.
ClearColor Color
ScreenshotDir string
// contains filtered or unexported fields
}
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.
func (*Scene) Cameras ¶
Cameras returns the scene's camera list. The returned slice MUST NOT be mutated.
func (*Scene) CapturePointer ¶
CapturePointer routes all events for pointerID to the given node.
func (*Scene) Draw ¶
Draw traverses the scene tree, emits render commands, sorts them, and submits batches to the given screen image.
func (*Scene) GetBatchMode ¶ added in v0.1.2
BatchMode returns the current draw-call batching strategy.
func (*Scene) InjectClick ¶
InjectClick is a convenience that queues a press followed by a release at the same screen coordinates. Consumes two frames.
func (*Scene) InjectDrag ¶
InjectDrag queues a full drag sequence: press at (fromX, fromY), linearly interpolated moves over frames-2 intermediate frames, and release at (toX, toY). The total sequence consumes `frames` frames. Minimum frames is 2 (press + release).
func (*Scene) InjectMove ¶
InjectMove queues a pointer move event at the given screen coordinates with the button held down. Use this between InjectPress and InjectRelease to simulate a drag.
func (*Scene) InjectPress ¶
InjectPress queues a pointer press event at the given screen coordinates (left button). The event is consumed on the next frame's processInput call.
func (*Scene) InjectRelease ¶
InjectRelease queues a pointer release event at the given screen coordinates.
func (*Scene) LoadAtlas ¶
LoadAtlas parses TexturePacker JSON, registers atlas pages with the scene, and returns the Atlas for region lookups. Pages are registered starting at the next available page index.
func (*Scene) NewCamera ¶
NewCamera creates a camera with the given viewport and adds it to the scene.
func (*Scene) OnClick ¶
func (s *Scene) OnClick(fn func(ClickContext)) CallbackHandle
OnClick registers a scene-level callback for click events. Multiple registrations are additive. Use CallbackHandle.Remove to unregister.
func (*Scene) OnDrag ¶
func (s *Scene) OnDrag(fn func(DragContext)) CallbackHandle
OnDrag registers a scene-level callback for drag events. Multiple registrations are additive. Use CallbackHandle.Remove to unregister.
func (*Scene) OnDragEnd ¶
func (s *Scene) OnDragEnd(fn func(DragContext)) CallbackHandle
OnDragEnd registers a scene-level callback for drag end events. Multiple registrations are additive. Use CallbackHandle.Remove to unregister.
func (*Scene) OnDragStart ¶
func (s *Scene) OnDragStart(fn func(DragContext)) CallbackHandle
OnDragStart registers a scene-level callback for drag start events. Multiple registrations are additive. Use CallbackHandle.Remove to unregister.
func (*Scene) OnPinch ¶
func (s *Scene) OnPinch(fn func(PinchContext)) CallbackHandle
OnPinch registers a scene-level callback for pinch events. Multiple registrations are additive. Use CallbackHandle.Remove to unregister.
func (*Scene) OnPointerDown ¶
func (s *Scene) OnPointerDown(fn func(PointerContext)) CallbackHandle
OnPointerDown registers a scene-level callback for pointer down events. Multiple registrations are additive; scene-level handlers fire before per-node callbacks. Use CallbackHandle.Remove to unregister.
func (*Scene) OnPointerEnter ¶
func (s *Scene) OnPointerEnter(fn func(PointerContext)) CallbackHandle
OnPointerEnter registers a scene-level callback for pointer enter events. Fired when the pointer moves over a new node (or from nil to a node).
func (*Scene) OnPointerLeave ¶
func (s *Scene) OnPointerLeave(fn func(PointerContext)) CallbackHandle
OnPointerLeave registers a scene-level callback for pointer leave events. Fired when the pointer leaves a node (moves to a different node or to empty space).
func (*Scene) OnPointerMove ¶
func (s *Scene) OnPointerMove(fn func(PointerContext)) CallbackHandle
OnPointerMove registers a scene-level callback for pointer move events. Multiple registrations are additive. Use CallbackHandle.Remove to unregister.
func (*Scene) OnPointerUp ¶
func (s *Scene) OnPointerUp(fn func(PointerContext)) CallbackHandle
OnPointerUp registers a scene-level callback for pointer up events. Multiple registrations are additive. Use CallbackHandle.Remove to unregister.
func (*Scene) RegisterPage ¶
RegisterPage stores an atlas page image at the given index. The render compiler uses these to SubImage sprite regions.
func (*Scene) ReleasePointer ¶
ReleasePointer stops routing events for pointerID to a captured node.
func (*Scene) RemoveCamera ¶
RemoveCamera removes a camera from the scene.
func (*Scene) Root ¶
Root returns the scene's root container node. The root node cannot be removed or disposed; it always exists for the lifetime of the Scene.
func (*Scene) Screenshot ¶
Screenshot queues a labeled screenshot to be captured at the end of the current frame's Draw call. The resulting PNG is written to ScreenshotDir with a timestamped filename. Safe to call from Update or Draw.
func (*Scene) SetBatchMode ¶ added in v0.1.2
SetBatchMode sets the draw-call batching strategy.
func (*Scene) SetDebugMode ¶
SetDebugMode enables or disables debug mode. When enabled, disposed-node access panics, tree depth and child count warnings are printed, and per-frame timing stats are logged to stderr.
func (*Scene) SetDragDeadZone ¶
SetDragDeadZone sets the minimum movement in pixels before a drag starts.
func (*Scene) SetEntityStore ¶
func (s *Scene) SetEntityStore(store EntityStore)
SetEntityStore sets the optional ECS bridge.
func (*Scene) SetPostDrawFunc ¶ added in v0.1.3
SetPostDrawFunc registers a callback that is called after Scene.Draw (and after the FPS widget) when the scene is run via Run. Use it for screen-space debug overlays (e.g. ebitenutil.DebugPrintAt). Pass nil to clear.
func (*Scene) SetTestRunner ¶
func (s *Scene) SetTestRunner(runner *TestRunner)
SetTestRunner attaches a TestRunner to the scene. The runner's step method is called from Scene.Update before processInput each frame.
func (*Scene) SetUpdateFunc ¶
SetUpdateFunc registers a callback that is called once per tick before Scene.Update when the scene is run via Run. Use it for game-specific logic (movement, spawning, etc.). Pass nil to clear.
type TTFFont ¶
type TTFFont struct {
// contains filtered or unexported fields
}
TTFFont wraps Ebitengine's text/v2 for TrueType font rendering.
func LoadTTFFont ¶
LoadTTFFont loads a TrueType font from raw TTF/OTF data at the given size.
func (*TTFFont) Face ¶
func (f *TTFFont) Face() *text.GoTextFace
Face returns the underlying GoTextFace for direct Ebitengine text/v2 rendering.
func (*TTFFont) LineHeight ¶
LineHeight returns the vertical distance between baselines.
func (*TTFFont) MeasureString ¶
MeasureString returns the width and height of the rendered text.
type TestRunner ¶
type TestRunner struct {
// contains filtered or unexported fields
}
TestRunner sequences injected input events and screenshots across frames for automated visual testing. Attach to a Scene via SetTestRunner.
func LoadTestScript ¶
func LoadTestScript(jsonData []byte) (*TestRunner, error)
LoadTestScript parses a JSON test script and returns a TestRunner ready to be attached to a Scene via SetTestRunner.
func (*TestRunner) Done ¶
func (r *TestRunner) Done() bool
Done reports whether all steps in the test script have been executed.
type TextAlign ¶
type TextAlign uint8
TextAlign controls horizontal text alignment within a TextBlock.
type TextBlock ¶
type TextBlock struct {
// Content is the text string to render. Supports embedded newlines.
Content string
// Font is the BitmapFont or TTFFont used for measurement and rendering.
Font Font
// Align controls horizontal alignment within the wrap width or measured bounds.
Align TextAlign
// WrapWidth is the maximum line width in pixels before word wrapping.
// Zero means no wrapping.
WrapWidth float64
// Color is the fill color for the text glyphs.
Color Color
// Outline defines a text stroke rendered behind the fill. Nil means no outline.
Outline *Outline
// LineHeight overrides the font's default line height. Zero uses Font.LineHeight().
LineHeight float64
// contains filtered or unexported fields
}
TextBlock holds text content, formatting, and cached layout state.
func (*TextBlock) Invalidate ¶ added in v0.1.3
func (tb *TextBlock) Invalidate()
Invalidate invalidates the cached layout and TTF image, forcing recomputation on the next frame. Call this after changing Content, Font, WrapWidth, Align, LineHeight, Color, or Outline at runtime.
type TextureRegion ¶
type TextureRegion struct {
Page uint16 // atlas page index (references Scene.pages)
X, Y uint16 // top-left corner of the sub-image rect within the atlas page
Width uint16 // width of the sub-image rect (may differ from OriginalW if trimmed)
Height uint16 // height of the sub-image rect (may differ from OriginalH if trimmed)
OriginalW uint16 // untrimmed sprite width as authored
OriginalH uint16 // untrimmed sprite height as authored
OffsetX int16 // horizontal trim offset from TexturePacker
OffsetY int16 // vertical trim offset from TexturePacker
Rotated bool // true if the region is stored 90 degrees clockwise in the atlas
}
TextureRegion describes a sub-rectangle within an atlas page. Value type (32 bytes) — stored directly on Node, no pointer.
type TileMapLayer ¶ added in v0.1.3
type TileMapLayer struct {
// contains filtered or unexported fields
}
TileMapLayer is a single layer of tile data. It stores the raw integer grid and owns a geometry buffer that is rebuilt on tile boundary crossings and transformed each frame.
func (*TileMapLayer) InvalidateBuffer ¶ added in v0.1.3
func (l *TileMapLayer) InvalidateBuffer()
InvalidateBuffer forces a full buffer rebuild on the next frame.
func (*TileMapLayer) Node ¶ added in v0.1.3
func (l *TileMapLayer) Node() *Node
Node returns the layer's scene graph node.
func (*TileMapLayer) SetAnimations ¶ added in v0.1.3
func (l *TileMapLayer) SetAnimations(anims map[uint32][]AnimFrame)
SetAnimations sets the animation definitions for this layer. The map is keyed by base GID (no flag bits).
func (*TileMapLayer) SetData ¶ added in v0.1.3
func (l *TileMapLayer) SetData(data []uint32, w, h int)
SetData replaces the entire tile data array and forces a full buffer rebuild.
func (*TileMapLayer) SetTile ¶ added in v0.1.3
func (l *TileMapLayer) SetTile(col, row int, newGID uint32)
SetTile updates a single tile in the given layer. If the tile is currently visible in the buffer, its vertex UVs are updated immediately.
type TileMapViewport ¶ added in v0.1.3
type TileMapViewport struct {
// Tile dimensions in pixels.
TileWidth int
TileHeight int
// MaxZoomOut is the minimum zoom level the developer expects. Controls
// buffer sizing. Default 1.0 (no zoom out). E.g. 0.5 means the
// viewport may show 2x as many tiles.
MaxZoomOut float64
// MarginTiles is the number of extra tiles beyond the viewport edge to
// keep buffered. Prevents pop-in during fast pans. Default 2.
MarginTiles int
// contains filtered or unexported fields
}
TileMapViewport is a scene graph node that manages a viewport into a tilemap. It owns an ordered list of TileMapLayer (tile data) and supports interleaved regular Node containers for entities (sandwich layers).
func NewTileMapViewport ¶ added in v0.1.3
func NewTileMapViewport(name string, tileWidth, tileHeight int) *TileMapViewport
NewTileMapViewport creates a new tilemap viewport node with the given tile dimensions. The viewport is a container node that should be added to the scene graph.
func (*TileMapViewport) AddChild ¶ added in v0.1.3
func (v *TileMapViewport) AddChild(child *Node)
AddChild adds a regular node container as a child of the viewport (for sandwich layers: NPCs, items, effects, etc.).
func (*TileMapViewport) AddTileLayer ¶ added in v0.1.3
func (v *TileMapViewport) AddTileLayer(name string, w, h int, data []uint32, regions []TextureRegion, atlasImage *ebiten.Image) *TileMapLayer
AddTileLayer creates a tile layer with the given map data and adds it as a child of the viewport. All regions must come from the provided atlas image. Returns the layer for further configuration (RenderLayer, animations, etc.).
func (*TileMapViewport) Node ¶ added in v0.1.3
func (v *TileMapViewport) Node() *Node
Node returns the underlying scene graph node for this viewport.
func (*TileMapViewport) SetCamera ¶ added in v0.1.3
func (v *TileMapViewport) SetCamera(cam *Camera)
SetCamera binds this viewport to a specific camera. If nil, defaults to scene.Cameras()[0] during update.
type TweenGroup ¶
type TweenGroup struct {
// Done is true when all tweens in the group have finished or the target
// node has been disposed.
Done bool
// contains filtered or unexported fields
}
TweenGroup animates up to 4 float64 fields on a Node simultaneously. Create one via the convenience constructors (TweenPosition, TweenScale, TweenColor) and call Update(dt) each frame. The group auto-applies values and marks the node dirty. If the target node is disposed, the group stops immediately.
There is no global animation manager — users call Update themselves.
func TweenAlpha ¶
TweenAlpha creates a TweenGroup that animates node.Alpha to the target value over the specified duration using the easing function.
func TweenColor ¶
TweenColor creates a TweenGroup that animates all four components of node.Color (R, G, B, A) to the target color over the specified duration.
func TweenPosition ¶
TweenPosition creates a TweenGroup that animates node.X and node.Y to the given target coordinates over the specified duration using the easing function.
func TweenRotation ¶
TweenRotation creates a TweenGroup that animates node.Rotation to the target value over the specified duration using the easing function.
func TweenScale ¶
TweenScale creates a TweenGroup that animates node.ScaleX and node.ScaleY to the given target values over the specified duration using the easing function.
func (*TweenGroup) Update ¶
func (g *TweenGroup) Update(dt float32)
Update advances all tweens by dt seconds, writes values to the target fields, and marks the node dirty. If the target node has been disposed, Done is set to true and no writes occur.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
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. |
|
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 demonstrates the LightLayer system: a dark dungeon scene lit by five colored torches and a warm lantern that follows the mouse cursor.
|
Lighting demonstrates the LightLayer system: a dark dungeon scene lit by five colored torches and a warm lantern that follows the mouse cursor. |
|
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. |
|
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. |
|
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. |
|
text
command
Text demonstrates bitmap font (BMFont) text rendering with willow.NewText.
|
Text demonstrates bitmap font (BMFont) text rendering with willow.NewText. |
|
texttf
command
Text demonstrates TTF text rendering with willow.NewText and willow.LoadTTFFont.
|
Text demonstrates TTF text rendering with willow.NewText and willow.LoadTTFFont. |
|
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. |
|
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. |
|
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. |