Spell Forge

Spell Forge is a fantasy top-down multiplayer game where up to 4 players explore a two mystical maps, collecting spells in order to take down other players in high action magical combat. This Game Supports up to 4 Players Locally or Online. Create a lobby, share the name and code, choose a map, and then jump in!

December 9, 2025

Spell Forge is a top-down multiplayer fantasy game where up to four players explore magical maps, collect spells, and battle in fast-paced combat both locally and online. I focused on building the core enemies, creating the new projectile system, and implementing the Reaper miniboss with full phase transitions. I also improved performance by redesigning enemy detection and made the miniboss fully deterministic to ensure synced behavior across all clients.

Major Contributions

  • Enemy System: Built three unique enemies (slime, walker, projectile enemy), added enemy variants, and placed enemy spawners throughout the map.
  • Reaper Miniboss: Implemented teleport, projectile, and spread-shot attacks, added a full Phase Two, integrated the new projectile system, and ensured deterministic attack ordering.
  • Performance & Networking: Replaced enemy-driven detection with player-driven scanning to eliminate physics spikes, and centralized miniboss decision logic to prevent desyncs.

Miniboss Logic

While working on the Reaper miniboss AI in Photon Quantum, I discovered a recurring issue where multiple abilities were being scheduled as separate FrameEvents, but Quantum’s deterministic frame queue would occasionally execute them out of order. Because each attack—teleport, shoot, and shockwave—was triggered from different parts of the codebase, the miniboss could end up with overlapping states or back-to-back actions that ignored intended cooldowns. This resulted in desynced client simulations, unpredictable attack patterns, and cases where the miniboss entered conflicting animation states. To solve this, I decided the entire attack-selection process needed to be centralized into a single, deterministic decision step.

I created a contained function that gathers all relevant state from the miniboss, its health, its phase, and its internal counters, then resolves the next action in one pass. This function ensures that only one FrameEvent is ever queued per decision cycle, and that the event is correctly associated with the miniboss's state machine. By consolidating the logic, I was able to enforce strict ordering, preserve deterministic behavior across clients, and make the boss’s attack loop maintainable and fully predictable. The final system not only fixed the desync issues, but also allowed me to implement more advanced phase behavior, looping attack sequences, and clean transitions between abilities—all controlled through a single, reliable decision-making function.

Enemy Detection

Originally, every enemy in the game performed its own circular Shape2D detection scan each frame to search for nearby players. While this approach was simple, it did not scale—large groups of enemies would each run multiple physics queries every few frames, overwhelming the deterministic physics system and causing noticeable spikes and frame hitches. Because all detection happened on the enemy side, the cost increased linearly with enemy count, and arenas that can contain 100+ active enemies at once suffered from significant performance degradation. It became clear that enemy-driven detection had to be replaced with a more efficient system.

The fix was to invert the process: instead of every enemy searching for the player, the player searches for nearby enemies. Once an enemy is found within a player’s detection radius, the enemy is assigned an Aggressive component, which immediately hands control over to the enemy’s state and pathing logic. From that point on, the enemy no longer performs heavy detection queries—it simply reacts and pathfinds toward its assigned target. This player-driven approach reduced the number of physics queries from “potentially hundreds per frame” down to a predictable “once per player per interval,” eliminating lag while maintaining identical gameplay behavior.

Game Programmer

Joseph Pacentine

Hi! I’m Joseph Pacentine, a senior Game Development and Software Engineering student at Michigan State University with a passion for building fun, polished, and technically interesting gameplay systems. I’ve spent the past several years developing my skills in C#, C++, Java, and Python, and applying them to real game projects ranging from AI systems to gameplay tools and enemy behavior logic. I’ve loved games for as long as I can remember, and turning that childhood excitement into actual development work has been one of the most rewarding experiences of my life.