Duke vs The Gang
ABOUT THIS PROJECT
A 2D action game shipped on Steam by a 30-person student team.
DGA's flagship project: A 2D action game developed by a 30-person team at Cornell's Development in Games Association and released on Steam. I work on the enemies: the two boss encounters players spend the most time learning, and the minions that fill the space between them.
Granny runs on a six-state machine
Granny.cs is an enum-driven state machine over Idle, Invincible, HoldingContract, ContractDropped, Scavenge and Returning, dispatched from a switch in Update against a single stateTimer that counts down each frame. Every transition method is responsible for setting its own duration and zeroing her velocity before handing control over, so a state can never inherit leftover movement from the one before it. Keeping the timer in one place instead of one per behavior is what made the phase 2 handoff debuggable, because there is exactly one clock to inspect when she gets stuck. Adding a phase means adding a state and its transition rather than threading another boolean through the update loop.
Contracts are the real health bar
She fights while holding contracts that spawn inside a designer-authored list of bounds, and hitting her does nothing: destroying the contracts is what actually removes her health. Drop one and she leaves her attack pattern to go and get it, running a nearest-contract search over the currently dropped ones, walking to it, then returning to her start point before resuming. The double-contract case gets its own lock flag, because two contracts resolving in the same frame was the bug behind most of the fight breaking, either by taking double health or by leaving a phantom contract on the board.
Attacks and timings as data
The coin, contract-coin and double-contract-coin attacks are BulletPattern assets assigned to serialized fields, so a pattern is swapped in the Inspector rather than rewritten in code. Every duration in the fight is a [SerializeField] too: idle, scavenge, out, invincible, dropped and return times, plus collision radius and check distance. That was deliberate, because the designers retuned this fight repeatedly and none of it should have required me to be in the room.
Pig minion AI
The pigs run their own smaller state machine of patrol, charge and return. Patrol moves them across a set distance and elevation on a randomized start delay drawn between a min and max, which stops a group of them from sliding in lockstep and reading as one object. Charging takes a target position and commits to it, and returning uses an arrival threshold rather than an exact position check so a pig never jitters trying to land on a float. They also carry their own stun timing and whip knockback force, and report hits back up to the Drover riding them.