# Ebitengine — A Dead Simple 2D Game Engine for Go > Ebitengine is a simple 2D game library for Go with a tiny API that takes minutes to learn. It compiles to WASM, iOS, Android, Nintendo Switch, and desktop — ideal for game jams and indie titles written in Go. ## Install Save as a script file and run: # Ebitengine — 2D Game Engine for Go ## Quick Use ```bash go mod init mygame go get github.com/hajimehoshi/ebiten/v2 ``` ```go // main.go package main import ( "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" "log" ) type Game struct{} func (g *Game) Update() error { return nil } func (g *Game) Draw(screen *ebiten.Image) { ebitenutil.DebugPrint(screen, "Hello, Ebitengine!") } func (g *Game) Layout(ow, oh int) (int, int) { return 320, 240 } func main() { ebiten.SetWindowSize(640, 480) ebiten.SetWindowTitle("Hello") if err := ebiten.RunGame(&Game{}); err != nil { log.Fatal(err) } } ``` ```bash go run . ``` ## Introduction Ebitengine (formerly Ebiten), by Hajime Hoshi, is the answer to "what would a minimal game engine in Go look like?" The entire public API fits in a handful of functions: an `Update()` and `Draw()` method, sprite drawing, input, audio. That's it. Despite the simplicity, commercial games ship on Steam, Switch, iOS, and Android using Ebitengine. With over 13,000 GitHub stars, Ebitengine is the most popular Go-based game engine. It compiles to native, WASM, iOS, Android, and Nintendo Switch (with the official porting toolkit). The "Odyssey" Switch game and many itch.io hits are made with it. ## What Ebitengine Does Ebitengine gives you a game loop via `ebiten.Game` interface (`Update`, `Draw`, `Layout`), image/sprite rendering, input (keyboard, mouse, gamepad, touch), audio (WAV/OGG/MP3), shaders (Kage shader language), and helpers for tilemaps + text. The engine doesn't impose scene graphs or ECS — you structure your game however you want. ## Architecture Overview ``` Your Go code | [ebiten.Game interface] Update() error — game logic, 60Hz Draw(*Image) — render each frame Layout(ow, oh) — logical vs screen size | [Ebitengine runtime] input subsystem (keyboard, mouse, gamepad, touch) audio player (OggVorbis, MP3, WAV) image API (Image, DrawImage, shader hooks) | [Kage shaders] WGSL-like DSL compiled to GLSL/MSL/WebGPU | [Backends] OpenGL / Metal / DirectX / WebGPU / WebGL Desktop (GLFW), Mobile (NDK / iOS frameworks), WASM (canvas + WebGL) | [Deploy] native binary, WASM bundle, APK/AAB, IPA, Switch (via toolkit) ``` ## Self-Hosting & Configuration ```go // Sprite example type Game struct { img *ebiten.Image x, y float64 } func (g *Game) Update() error { if ebiten.IsKeyPressed(ebiten.KeyArrowRight) { g.x += 2 } if ebiten.IsKeyPressed(ebiten.KeyArrowLeft) { g.x -= 2 } return nil } func (g *Game) Draw(screen *ebiten.Image) { op := &ebiten.DrawImageOptions{} op.GeoM.Translate(g.x, g.y) screen.DrawImage(g.img, op) } func main() { img, _, err := ebitenutil.NewImageFromFile("assets/player.png") if err != nil { log.Fatal(err) } g := &Game{img: img, x: 50, y: 50} ebiten.SetWindowSize(800, 600) ebiten.RunGame(g) } ``` ```bash # WebAssembly build (itch.io, personal site) GOOS=js GOARCH=wasm go build -o game.wasm . # Grab wasm_exec.js from Go toolchain cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" . # Host via any static server # iOS / Android (requires gomobile + native tooling) gomobile bind -target=ios ./... # Switch port via official Ebitengine Switch SDK ``` ## Key Features - **Tiny API** — 3-method game interface, discoverable in minutes - **Cross-platform** — desktop + WASM + iOS + Android + Switch - **Kage shader language** — single shader source, multiple backends - **Input everywhere** — keyboard / mouse / touch / gamepad abstracted uniformly - **Audio support** — WAV, OGG, MP3 via native codec libraries - **Text rendering** — bitmap + vector font via golang.org/x/image/font - **No GC spikes** — sensible Image caching, careful allocations - **Commercial-friendly** — Apache-2.0, no royalties ## Comparison with Similar Tools | Feature | Ebitengine | raylib (Go bindings) | Godot | Bevy | pixel (pure Go) | |---|---|---|---|---|---| | Language | Go (native) | Go via C binding | GDScript / C# | Rust | Go (native) | | Learning curve | Very shallow | Shallow | Moderate | Steeper | Shallow | | Dimensions | 2D | 2D + 3D | 2D + 3D | 2D + 3D | 2D | | WASM | Yes | Yes (via emsdk) | Yes | Yes | Partial | | Switch support | Official toolkit | Via C port | Via 3rd party | Via 3rd party | No | | Best For | Go devs writing 2D games | Go devs wanting raylib API | Full-feature engine | Rust devs | Pure-Go 2D | ## FAQ **Q: Ebitengine vs raylib-go?** A: Both are simple. Ebitengine is pure Go (no CGO, easier cross-compile). raylib-go binds to C raylib. Ebitengine fits idiomatic Go projects better; raylib-go if you want raylib's exact API. **Q: Can I make commercial games?** A: Yes — Apache-2.0 license, no royalties. Examples: Odyssey (Steam + Switch), A Short Hike (partial), various itch.io hits. **Q: Is it fast enough?** A: Yes for most 2D games. Large tilemaps, hundreds of sprites, custom shaders — all run at 60 FPS on modest hardware. For bullet-hell games with 10k particles, use custom draw batching. **Q: Switch support?** A: There's an official Ebitengine Nintendo Switch SDK (requires Nintendo dev agreement). Many commercial Ebitengine games ship on Switch. ## Sources - GitHub: https://github.com/hajimehoshi/ebiten - Website: https://ebitengine.org - Author: Hajime Hoshi - License: Apache-2.0 --- Source: https://tokrepo.com/en/workflows/a9148c68-3862-11f1-9bc6-00163e2b0d79 Author: Script Depot