tnk9x

August 4, 2026 · View on GitHub

A modern remake and tribute to the classic arcade game Battle City (NES, 1985), built with Go and Ebiten. This project combines a passion for the original game with learning Go, Clean Architecture principles, and game development.

Play online: https://shpaker.github.io/tnk9x/

tnk9x running in a mobile browser

WebAssembly build in a mobile browser — touch controls are auto-detected.

Development Status

Playable now:

  • Full game loop with HQ and victory/defeat overlays
  • Two-player keyboard controls
  • Touch controls for mobile browsers: auto-detected virtual D-pad, fire and pause in the letterbox area, tappable menu
  • Tank movement with braking and grid snap
  • Bullets and destructible terrain with incremental brick chipping: each hit shaves a half-tile slab, reinforced bullets break tiles whole
  • All five surface types (brick, steel, forest, water, ice) with ice sliding and water blocking
  • Lua-scripted enemies of four types with probability-based levels
  • Player lives, levels and damage
  • All six bonuses: grenade, tank, star, helmet shield, enemy-freezing timer, HQ-fortifying shovel
  • Level selection with a desktop quit item
  • Pause menu on Esc/P/touch (continue, exit to level select)
  • Sound effects and music
  • NES-style sidebar HUD (enemy reserve, player lives, stage flag) on an authentic 256x224 screen
  • Runs natively and in the browser (WebAssembly, deployed to GitHub Pages on release tags)

Under the hood:

  • Clean Architecture with depguard-enforced layer boundaries
  • Constructor-only DI from a composition root, repository pattern
  • Scripting behind a domain-typed engine interface
  • App-lifetime GPU sprite cache with startup preload, fail-fast sprite/animation validation on startup
  • Unit tests with a >=70% use-cases coverage gate
  • CI/CD (fmt, lint, test, build, release)

Roadmap

  • Enemy AI difficulty scaling
  • HQ: defeat screen, protection mechanics
  • UI: score, main menu, game over screen, settings
  • Test coverage >80% total, performance profiling

Installation and Running

Requirements: Go 1.24+, optionally — Just.

git clone https://github.com/shpaker/tnk9x.git
cd tnk9x
just deps         # Install dependencies (or go mod download)

# Run the game
just run          # or go run cmd/main.go

# Build binary
just build        # binary will be in ./tnk9x

# Checks
just fmt
just lint
just test

Architecture

The project follows Clean Architecture principles with clear separation of concerns. Dependencies point inward: outer layers depend on inner layers through interfaces. The composition root (internal/app) is the only place that assembles the object graph — all dependencies are injected via constructors, layer boundaries are enforced by depguard.

Dependency Flow

┌─────────────────────────────────────────────────────────┐
│  Composition Root (internal/app)                        │
│  game loop · state transitions · object graph assembly  │
└───────────────────┬─────────────────────────────────────┘
                    │ (builds & wires)
┌───────────────────▼─────────────────────────────────────┐
│  Presentation Layer                                     │
│  ┌──────────────┐  ┌──────────────────────┐             │
│  │   States     │  │      Adapters        │             │
│  │              │  │                      │             │
│  │ StageState   │  │ Renderer             │             │
│  │ StageSelect  │  │ Input                │             │
│  │              │  │ Sound                │             │
│  │              │  │ Scripting (Lua)      │             │
│  └──────┬───────┘  └───────┬──────────────┘             │
│         └─────────┬────────┘                            │
│                   │ (depends on)                        │
└───────────────────▼─────────────────────────────────────┘

┌───────────────────▼─────────────────────────────────────┐
│  Application Layer                                      │
│  ┌──────────────┐  ┌──────────────┐                     │
│  │  Use Cases   │  │   Services   │                     │
│  │              │  │              │                     │
│  │ TankActions  │  │ Collision    │                     │
│  │ Collision    │  │ Animation    │                     │
│  │ Sound        │  │ Braking      │                     │
│  └──────┬───────┘  └──────┬───────┘                     │
│         └─────────┬───────┘                             │
│                   │ (manipulates)                       │
└───────────────────▼─────────────────────────────────────┘

┌───────────────────▼─────────────────────────────────────┐
│  Domain Layer                                           │
│  ┌───────────────────────────────────────────────────┐  │
│  │  Entities (Tank, Bullet, Block, HQ, etc.)         │  │
│  │  Value Objects (Position, Size, Direction)        │  │
│  │  Session Entities (GameSession, StageSession)     │  │
│  └───────────────────────────────────────────────────┘  │
│                   ▲                                     │
└───────────────────┼─────────────────────────────────────┘
                    │ (reads/writes)
┌───────────────────▼─────────────────────────────────────┐
│  Infrastructure Layer                                   │
│  ┌──────────────┐  ┌──────────────┐                     │
│  │ Repositories │  │   Raw Files  │                     │
│  │              │  │              │                     │
│  │ Game         │  │ FileSystem   │                     │
│  │ Processed    │  │              │                     │
│  └──────────────┘  └──────────────┘                     │
└─────────────────────────────────────────────────────────┘

License

This project is licensed under the MIT License - see the LICENSE file for details.