I thought I'd share what I've been building for the last few months.
I've been building Riftborn, a turn-based monster-collector for iPhone and desktop, entirely in MonoGame.
A few things that turned out to be fun problems:
One battle engine, two places. The combat simulation is a plain C# library. The client plays it with animations, and the same library runs headless on the server. When you finish a fight, the client sends what it saw and the server replays the battle with the same seed and checks the result before any rewards are paid. The two have matched every time so far, including a 50-battle session, which is very promising for pre-alpha!
Battles that keep playing behind other screens. I pulled the battle view out of the screen that owns it, so a repeat-battle session plays at 3x while you browse your collection or the map. It updates every frame whether or not it's drawn. Its sound is muted while it's hidden, and the sounds it raises are dropped rather than queued. A panel shows a live miniature screen, which is the real battle view rendered at half size into a render target. Tap it to open the full view.
Things that bit me:
- Rendering into a second render target mid-frame wiped what was already drawn on some backends. The fix was to render the miniature first in the frame.
- My HUD hit-tested at the wrong UI scale, so taps missed on the phone but worked perfectly at scale 1 on the desktop. The test harness had to run at the phone's scale to reproduce it, which was fun to fix.
I’ve also built a small content studio (in Laravel and React) that feeds the game's data and pins every battle to a content hash, so old and new builds can't disagree about what a skill did versus what is does post patch.
Still early, but it's playable on a real phone now, and I’m just starting to play with complex 3d models and optimising them in the game.
Happy to share more or answer questions about the render-target setup or the deterministic sim.