A turn-based roguelike game built in Godot 4 with procedural dungeon generation and traditional grid-based movement.
The goal with this project was not to ship a complete game, but to explore, learn and practice game developement patterns.
Data-Driven Design: Entity behaviors, stats, and properties are defined in .tres resource files rather than hardcoded. This enables easy content modification and supports future modding.
Component-Based Systems: Uses composition over inheritance. Entities are built from configurable components rather than complex class hierarchies.
Separation of Concerns: Clear boundaries between:
- Game initialization (
scripts/game.gd) - Turn management (
scripts/turn_manager.gd) - Rendering and visual representation (
scripts/dungeon_renderer.gd) - Entity definitions (
definitions/) - Scene composition (
scenes/) - Visual assets and SFX (
assets/)- Assets by Kenney
Dungeon Generation: Dictionary-based procedural generation that creates rooms and corridors. Easily extensible for new tile types and generation algorithms.
Rendering System: DungeonRenderer encapsulates all tilemap interactions and provides a clean interface for coordinate conversions. Game logic interacts with the visual layer through well-defined methods rather than direct tilemap access.
Entity Management: Centralized system where all creatures (player, enemies) use the same base entity class with configurable definitions. Adding new entity types requires only creating new .tres files.
Turn System: Command pattern with centralized batch processing ensures consistent game state and eliminates rendering/data synchronization issues.
graph LR
subgraph "Input Sources"
Player[Player Input]
Entity[Entity AI]
end
subgraph "Core System"
TurnManager[TurnManager<br/>Command Queue & Processing]
DungeonData[DungeonData<br/>Game State]
end
subgraph "Output"
Renderer[DungeonRenderer<br/>Visual Output]
end
%% Main Flow
Player -->|command| TurnManager
Entity -->|command| TurnManager
TurnManager -->|executes| DungeonData
TurnManager -->|renders| Renderer
%% Styling
classDef inputSystem fill:#2e7d32,color:#ffffff
classDef coreSystem fill:#1565c0,color:#ffffff
classDef renderSystem fill:#c2185b,color:#ffffff
class Player,Entity inputSystem
class TurnManager,DungeonData coreSystem
class Renderer renderSystem
Command Pattern: All actions (movement, combat, death) are encapsulated as commands, enabling undo/redo, replay systems, and complex action sequences.
Batch Processing: Commands are queued and executed in batches per turn, eliminating data race conditions and ensuring consistent game state.
Centralized Rendering: All visual updates happen once per turn after command processing, preventing flickering and synchronization issues.
Single Source of Truth: DungeonData maintains authoritative game state. All systems reference this central data source.
Clean Turn Flow:
- Input/AI → Commands created
- Commands → Queued in TurnManager
- TurnManager → Batch executes all commands
- TurnManager → Updates FOV once
- Renderer → Renders all changes once
Separation of Concerns: Clear boundaries between game logic (commands), state management (DungeonData), visibility (FOV), and presentation (DungeonRenderer).
- Use typed GDScript
- Keep entity logic generic and configurable through resource files
- Maintain clear separation between game systems
- Design for extensibility without modifying existing core systems
- Follow traditional roguelike design patterns
- autoexplore should make visible walls explored
- currently only exploring walkable tiles so some visible walls remain unexplored
- spawn enemies in valid locations
- 1 or 2 per room instead of fully random
- add another enemy type
- each enemy should have their own sfx
-
generate different wall tiles based on their orientation- not possible with current tileset