Ebitengine (Ebiten v2)
Go 2D game engine skill - covers the full Ebitengine API and ecosystem. Routes to sub-skills by domain.
Ebitengine is a dead simple 2D game library for Go. Cross-platform: desktop (Windows/macOS/Linux), mobile (iOS/Android), WebAssembly, and Nintendo Switch.
Import: github.com/hajimehoshi/ebiten/v2
When to Use This Skill
You are building a 2D game or interactive graphical application in Go using Ebitengine (Ebiten v2).
Sub-Skill Routing
| If you need... |
Use Sub-Skill |
Game loop, ebiten.Game interface, TPS/FPS, window config |
ebiten/game-loop |
| Keyboard, mouse, gamepad, touch input |
ebiten/input |
| Images, sprites, tiles, camera, shaders, text |
ebiten/rendering |
| Entity Component System (Donburi, Ark, etc.) |
ebiten/ecs |
| Collision detection, physics, pathfinding |
ebiten/physics |
| Sound effects, music, audio playback |
ebiten/audio |
| WASM, mobile, Steam, cross-platform build |
ebiten/deployment |
| Asset loading, tilemaps (LDtk, Tiled), resource management |
ebiten/resources |
Minimal Game Template
package main
import (
"log"
"github.com/hajimehoshi/ebiten/v2"
)
type Game struct{}
func (g *Game) Update() error {
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
return 320, 240
}
func main() {
ebiten.SetWindowSize(640, 480)
ebiten.SetWindowTitle("Title")
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err)
}
}
Ecosystem Libraries
Architecture
| Library |
Purpose |
Stars |
| donburi |
ECS for Ebitengine |
500+ |
| ark |
Archetype-based ECS |
400+ |
| mizu |
ECS framework |
400+ |
| ebiten-extended |
Godot-inspired scene graph, camera, sprites |
100+ |
GUI
| Library |
Purpose |
| ebitenui |
Full widget library (buttons, lists, combo boxes) |
| furex |
Flexbox-based UI framework |
| etk |
Toolkit for graphical interfaces |
Graphics & Animation
| Library |
Purpose |
| ganim8 |
Animation library inspired by anim8 |
| aseprite |
Aseprite file parser (layers, tags, slices) |
| aseplayer |
Aseprite animation player |
| etxt |
Font management and text rendering |
| colorgrad |
Color scales for data viz and games |
| tetra3d |
3D software renderer via Ebitengine |
Physics & Collision
| Library |
Purpose |
| resolv |
2D collision detection and resolution |
| cp |
Chipmunk2D physics port |
| box2d-go |
Box2D v3 physics port |
| coll |
2D collision detection |
World & Maps
| Library |
Purpose |
| ldtkgo |
LDtk level designer loader |
| go-tiled |
Tiled map editor (TMX) parser |
| dngn |
Random map generation |
| paths |
A* pathfinding |
Input
Audio
| Library |
Purpose |
| resound |
Sound effects (delay, low-pass, panning, distortion) |
| xm |
XM music format playback |
Resources & Tools
Networking
| Library |
Purpose |
| necs |
Networking layer for Donburi ECS |
Integration
Key Concepts
TPS vs FPS
- TPS (Ticks Per Second): How often
Update() is called. Default: 60. Set via ebiten.SetTPS().
- FPS (Frames Per Second): How often
Draw() is called. Tied to monitor refresh rate.
ebiten.CurrentTPS() / ebiten.CurrentFPS() for monitoring.
- Use
ebiten.SetTPS(ebiten.SyncWithFPS) to decouple update from render.
Coordinate System
- Origin (0,0) is top-left
- X increases right, Y increases down
Layout() defines logical screen size; engine scales to window
Image Model
ebiten.Image is the core drawing surface
screen parameter in Draw() is the final render target
- Use
SubImage() for sprite sheet regions (zero-copy)
- Use
ebiten.NewImage() for off-screen buffers
Anti-Patterns
| Don't |
Do |
Call ebiten.NewImage() in Update()/Draw() |
Create images once in NewGame() or load phase |
| Use floating-point for pixel positions |
Use float64 with GeoM (engine handles sub-pixel) |
Load assets in Draw() |
Load in init() or dedicated load phase |
Ignore Layout() return values |
Return consistent logical size |
Use ebiten.IsKeyPressed() for single actions |
Use inpututil.IsKeyJustPressed() for one-shot triggers |
Create *ebiten.DrawImageOptions each frame |
Reuse and reset with opts.GeoM.Reset() |
| Mix game state with rendering logic |
Keep Update() pure logic, Draw() pure rendering |
References
Remember: Ebitengine is intentionally simple. Start with the Game interface, add libraries only when needed.
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.