BTA-RRR is a turn-based tactical grid combat game built in LรVE2D (Lua framework). Originally a monolithic CS final project, it's been completely refactored into a modular, well-documented codebase following clean architecture principles.
The game features:
- 16x16 grid-based tactical combat with 30+ character classes
- Vim-style navigation (hjkl + arrows) โ a dual-purpose system for practicing vim while playing
- Turn-based initiative system with action points and resource management
- State machine architecture separating game logic from presentation
- Professional Lua patterns โ metatables, dependency injection, data-driven design
The codebase is designed to be readable and maintainable, with clear separation of concerns and every design decision documented.
- LรVE2D (0.10.2 or later) โ Download from love2d.org
- Git โ For cloning the repo
- Lua 5.1+ โ Usually bundled with LรVE2D
# Clone the repository
git clone https://github.com/TheOnliestMattastic/BTA-RRR.git
cd BTA-RRR
# Run with LรVE2D
love .That's it. The game boots directly from main.lua.
- hjkl โ Vim-style movement (h=left, j=down, k=up, l=right)
- Arrow Keys / WASD โ Alternative directional input
- Tab โ Toggle focus between map and action menu
- j/k โ Navigate menu up/down (when menu has focus)
- Space โ End turn
- Return โ Confirm action (move, attack, etc.)
- Escape โ Quit game
- Move โ Hover over tiles for visual feedback
- Left Click โ Select tiles, characters, or activate menu buttons
- Release โ Confirm action (buttons activate on release)
main.lua # Entry point, state machine, window setup
โโโ states/ # Game states (menu, game loop)
โ โโโ menu.lua # Main menu state
โ โโโ game.lua # Main gameplay loop and orchestration
โโโ core/ # Game logic and systems
โ โโโ character.lua # Character entity, stats, animations
โ โโโ gameState.lua # Turn order, win conditions, AP management
โ โโโ turnManager.lua # Initiative rolls, turn progression
โ โโโ inputHandler.lua # Keyboard/mouse/vim input routing
โ โโโ gameUI.lua # HUD rendering (stats, menu, turn order)
โ โโโ map.lua # Tile grid, collision, rendering
โ โโโ gameLogic.lua # Combat calculations, damage, range checks
โ โโโ assetRegistry.lua # Centralized asset loading
โ โโโ gameInit.lua # Setup and dependency injection
โโโ config/ # Data (not logic)
โ โโโ characters.lua # Character class definitions (30+)
โ โโโ tilesets.lua # Tileset/map configurations
โ โโโ ui.lua # UI layout constants
โ โโโ fx.lua # Visual effects (damage numbers, etc.)
โโโ lib/ # Third-party libraries
โ โโโ anim8.lua # Animation library (vendored)
โโโ assets/ # Sprites, fonts, tilesets
โโโ sprites/chars/ # Character spritesheets
โโโ fonts/ # Game fonts
Key Architectural Principle: Data lives in config/, logic lives in core/, presentation lives in states/. No circular dependencies.
Every function follows a structured comment pattern:
-- =============================================================================
-- MODULE_NAME
-- =============================================================================
-- WHAT: One sentence describing what this does
-- WHY: One sentence explaining why it's needed
-- HOW: One sentence explaining the implementation approach
-- NOTE: [Optional] Gotchas, alternatives, or reminders
-- =============================================================================This isn't busy-workโit makes code self-documenting and intentional. You know exactly why something exists.
- Keep It Stupidly Simple โ Code clarity over cleverness. If it's complex, break it smaller.
- Modularize Everything โ Each module has one job. Find what you need fast.
- Data-Driven โ Configuration lives in tables; logic stays in functions.
- Object-Oriented โ Lua metatables for clean entity management (Character, GameState, Map, etc.)
No over-engineering. No premature optimization. Just clean, readable, maintainable code.
- Initiative: D&D-style
d20 + SPDroll (seeturnManager.lua) - Action Points (AP): Gained at turn start (usually +2, capped at 4)
- Movement: Manhattan distance calculation, validates range before execution
- Combat: Range check + damage formula:
damage = attacker.pwr - defender.def(with minimum 1)
30+ distinct classes with unique stat profiles:
| Stat | Range | Purpose |
|---|---|---|
| HP | 12-32 | Health pool |
| PWR | 4-8 | Damage output |
| DEF | 1-8 | Damage reduction |
| DEX | 2-6 | Hit accuracy/evasion |
| SPD | 2-5 | Movement range + initiative modifier |
| RNG | 1-4 | Attack range |
See config/characters.lua for the full roster (Ninjas, Samurai, Mages, Brawlers, Knights, etc.).
- 16x16 tile grid, 32px per tile
- Randomized tileset selection (procedural variety)
- Character collision detection
- Range highlighting for movement/attacks
- Add entry to
config/characters.luawith stats, sprite path, animation definitions - Add sprite sheets to
assets/sprites/chars/<className>/- SpriteSheet.png (16x16 frames, 4 directions, 3-5 animation states)
- Faceset.png (portrait for UI)
- Register in
states/game.luaby instantiating withCharacter.new(className, x, y, stats) - Test locally with
love .
All balance lives in config/characters.lua (stats) or core/character.lua (AP gain):
function Character:gainAP(amount)
self.ap = math.min(self.ap + (amount or 2), self.maxAP) -- Change "2" to adjust
endinputHandler:getFocus()returns "map" or "menu"inputHandler.uiFocusshows which UI element has focus- Print input in
states/game.luakeypressed/mousepressed handlers
- Action menu buttons are placeholders โ Not all actions are implemented yet
- No persistent saves โ Game state doesn't persist between sessions
- No AI opponents โ Multiplayer/AI would be next-level features
- No ability system โ Tags exist in character data but aren't used yet
- No diagonal movement โ Animations locked to cardinal directions
- Implement Ability System โ Registry with cost/range/effects (shows system design)
- Event Bus Architecture โ Replace direct function calls with event system (loose coupling)
- Data Serialization โ Save/load with proper schema (production readiness)
- Unit Tests โ Test game logic: damage calculations, range checks (quality assurance)
- Performance Profiling โ Document optimization decisions (engineering rigor)
# Run game
love .
# Check code syntax
lua -c core/character.lua
# View recent commits
git log --oneline -10
# Find all TODOs
grep -r "TODO" core/If you're curious about game architecture, check these out:
- LรVE2D Manual: https://love2d.org/wiki/Main_Page
- Game Programming Patterns: https://gameprogrammingpatterns.com/ (state machine, entity systems, etc.)
- Lua Best Practices: https://www.lua.org/pil/ (metatables, module design)
- This Project's AGENTS.md: Architecture guidelines, comment standards, design philosophy
This project is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
Curious about my approach to architecture, code design, or game development? Want to discuss refactoring strategies or hire for a role where clean code matters?
"The only way to do great work is to love what you hate." โ Deliberately Inverted
