๐น๏ธ tgames
A terminal-based mini-games emulator.
๐ฎ List of games
- Snake
- Tetris
- 2048
- Minesweeper
- Flappy Bird
๐ ๏ธ Technical Highlights
tgames is built with scalability in mind. It uses a Trait-based abstraction to handle game logic, allowing for easy expansion.
- State Machine Architecture: Uses a centralized game loop and state machine to handle transitions between different game logics seamlessly.
- High-Performance Rendering: Leverages Ratatui for optimized terminal drawing and immediate-mode UI rendering, allowing for smooth, high-frequency updates with minimal CPU overhead
- Non-Blocking Input: Implemented a multi-threaded event loop using MPSC channels to decouple input polling from game logic, ensuring a fluid, non-blocking frame rate regardless of user activity.
- Easy Extension: Adding a new game is as simple as adding a variant to the
Gamesenum and implementing theGameManagertrait for a new struct. No changes to the core engine are required
๐ Adding a New Game
The engine uses the Strategy Pattern to remain decoupled from game logic. To add a new game, simply implement the GameManager trait and register it in the central dispatcher.
Implement the Trait
Register the game
Add the variant to the Games enum. The engine handles the lifecycle and state transitions automatically. New games are registered within the run_game dispatcher:
๐ฆ Installation
The installation can be done via cargo, just use:
๐ฆ Why Rust?
I chose Rust for this project not just for its modern syntax, but for the specific guarantees it provides for systems-level development:
-
Fearless Concurrency: Rustโs ownership model ensured that my multi-threaded input handling remained data-race free, allowing for a stable, non-blocking game loop.
-
Deterministic Resource Management: Rust allows for precise control over heap allocations. This ensures that the runtime execution and memory footprint of the program to remain highly predictable.
-
Zero-Cost Abstractions: The Trait-based architecture used in tgames allows for high-level modularity without sacrificing the performance of the underlying machine code.
-
Learning: Beyond the technical requirements, I chose Rust out of curiosity and desire to master a modern approach to systems design. I wanted to move away from manual memory management and learn the Borrow Checker to improve my ability to write memory-safe software.