The game
Izumi and Master WooGuay explore a dark dungeon in search of treasure. Players navigate tile-based levels, avoid spikes and patrolling hazards, push pots, collect gold and replenish their light at torches. Created by our five-person Black Tortoise Sect team for DigiPen’s first-year game project, the game combines deliberate grid movement with time pressure.
My role and the team boundary
I decided the ECS architecture and implemented its generic system interface, component-mask definitions and entity factories. I also built the player, grid, turn, trap and patrol systems, with teammates contributing features and integration work. Ryan handled component memory management and the entity ID system. My architectural responsibility was defining how systems fit together and how gameplay could be built on that foundation.
Polymorphic behaviour in C
Coming from C++, the hardest part was working out how to reproduce polymorphic behaviour in C. I used a shared system struct containing a component mask, an opaque pointer to system-specific data and a function-pointer table. Each concrete system supplies callbacks for adding entities, updating and removing entities. The world can then dispatch through the common interface while each system works with its own data.
One turn, two ways to advance
The hybrid turn/timer mechanic was my idea. A successful player move triggers a new turn immediately; if the player waits, a timer advances the turn after 2.5 seconds. Registered callbacks update traps, light depletion and patrols. This lets players plan around discrete world steps while preventing the dungeon from remaining still indefinitely. Shops, dialogue and tutorials suspend the turn timer.
Keeping the grid and gameplay together
The grid holds separate layers for static and dynamic tiles. Movement checks those layers for collision and interactions, including pushable pots, enemies, projectiles and collapsing floors. My work included connecting grid state to entity creation and level loading, along with player damage, pickups and movement completion. Logical tile positions and continuous movement animation need to stay consistent as a turn changes the world.
Traps, patrols and reusable behaviour
The trap system activates hazards according to their starting turn and repeat interval, with timing data loaded from level files. Spike states update the grid and their animation, while painting traps spawn projectiles. The patrol system supports both enemies and projectiles: blocked enemies reverse direction, while blocked projectiles are removed. Sharing the movement path kept related behaviours within the same system.
Introducing a shared development workflow
Alongside the architecture and gameplay work, I introduced code reviews, pull requests and a development workflow using forked repositories to the team. This gave us a process for proposing changes and reviewing one another’s code before integration. My contribution extended beyond individual systems to helping establish how we worked together on the codebase.
What I took forward
The main lesson was learning to express architectural ideas without relying on C++ language features. Structs, function pointers and explicit data boundaries were enough to build a common system interface in C. Applying that interface to the actual turn, grid and hazard mechanics made the architectural decisions part of the team’s working game.

