Timeline - First commit Oct 3, 2024 → Steam Demo Release Oct 2025
5,982
Total Commits
178/460
Active Days
104,126
Lines of C#
295
YAML Configs
Daily Code Commits: 14 Months of Development
Peak Development Days
#1
223
Oct 11, 2025
#2
171
Oct 7, 2025
#3
167
Oct 5, 2025
#4
165
Oct 13, 2025
#5
122
Oct 6, 2025
System Architecture & Design Decisions
Epic Survivors follows a "convention over configuration" pattern inspired by Ruby on Rails. The entire 104,000 lines of C# are organized in a layered architecture: Framework Layer (MonoGame), Engine Layer (custom game engine for survivor roguelikes), and Game Layer (weapons, enemies, levels, characters, abilities, pickups, meta progression, and assets like sprites, sounds, music).
Why MonoGame? Transparency. Unity's metadata files and prefab instances were opaque to AI. MonoGame meant plain C# code, YAML configs, and visible content files - everything the AI could read and modify directly.
Complete Engine Overview
All core systems interconnected across 104K lines. Scene management, entity system, collision detection, multiplayer state sync.
Click any diagram to view full-screen
Layered Architecture
Engine Layer (Custom Game Engine) → Framework Layer (MonoGame) → Game Layer (Weapons, Enemies, Levels)
Pure Enemy Anatomy
260 lines of YAML connecting to 50+ files. Zero enemy-specific C# code. 7 animations, 10 effects, 4 states, 4 behaviors.
Agent Orchestrator
Multi-agent Claude coordination system. Session startup flow, workspace hierarchy, data flow architecture, and config management.
Development Story
February 2024: The Copy-Paste Era
Started building a SaaS website - Ruby on Rails, PostgreSQL, Python. Worked with another guy. We used ChatGPT and copy-pasted entire files back and forth between the IDE and the chat. Started in Replit to share with each other. GitHub, but no easy way to see diffs. ChatGPT would cut stuff out, say "rest of code here" - standard limitations.
We went hard for two weeks, then kept going every Sunday for 6+ hours. Never wrote a single line of code ourselves. Ruby on Rails, Postgres database, Python data pipeline, connecting to APIs, transforms, loading into databases.
I designed the database myself in some software. I brain dumped it to AI and got it to generate the format for relational databases, so it was AI-assisted, but I did the data modeling. The AI could write SQL beautifully - we could give it the schema.rb (which it actually generated based on my plan) with minimal issues.
Full data pipeline: Python scripts extracting data from 5 different APIs. Transformation logic - cleaning data, normalizing formats, matching records across sources. Import into SQL database. Rails front-end with user authentication, settings, filters to slice data different ways. Mailing system for notifications. Automated tests. All of this in early/mid 2024 - months before ChatGPT officially supported structured JSON outputs. Everyone said "AI can't do complex coding." We figured it out through prompt engineering.
That website got to 99% complete. Some icons weren't loading. I delayed sending it out to fix them. Never sent it. A year later it's still sitting there. Perfectionism and ADHD killed it.
March/April 2024: Cursor Changes Everything
Around April 4, 2024: Found out about Cursor. Chat window directly in the IDE with visible diffs significantly improved workflow. Still had to accept every diff individually, but far more efficient than copy-paste.
Not sure what model we were using then. Might have been Sonnet 3, might have been ChatGPT. It worked. We kept making progress.
Late September 2024: Planning Epic Survivors
I originally wanted to enter a two-week game jam. Wanted to do a Survivors-like. The game jam theme didn't line up. I had two weeks off work. I kept the deadline, dropped the jam. Two weeks to make a game.
Did some brainstorming with ChatGPT. Read game design books - Game Design Patterns, all that. Played Survivors-likes and broke them down. Features. Functions. Data structures. How they work.
Took inspiration from Ruby on Rails. Convention over configuration. If you follow certain naming conventions and folder structures, meta-programming beneath the hood makes it work. I wanted that for a game.
Did deep research. Decided on MonoGame so I could publish to Steam. I'd worked on a Unity game a few months earlier, fully coded by AI, but hit walls. Unity's metadata files - I forget what they're called - you couldn't really generate them fully through AI. Prefabs, scene instances - the AI didn't have visibility. Or I didn't know how to give it that visibility.
MonoGame was different. Stardew Valley was built on it. You don't get an engine out of the box, but you get transparency. Everything's plain C# code, YAML configs, visible content files. The AI can read and modify everything directly.
The plan: separate game engine from game logic. Framework layer (MonoGame), engine layer (custom game engine for survivor roguelikes), game layer. Clean architecture.
Reality check: It didn't stay that clean. Over time the separation blurred. GameEngineFramework folder vs Scripts folder - they merged. The folders are still there, but the hierarchy should've been flatter. That said, there are systems that could be extracted into a pure engine.
What it became: an engine for Survivors-likes. You can change the entire game without touching C# code. Swap YAML files and content (sprites, sounds). If you want advanced custom behavior, drop in a .cs file following naming conventions. The system discovers it automatically.
The Two-Week Sprint: 457 Commits
Started with Cursor 3.5 (or whatever was available then). I'd done a lot of research and planning with ChatGPT. Created folder structures. Stubs of files. Placeholders. Over time it grew organically.
Day 1 (October 3, 2024) - 4 hours, 8 commits:
12:40 PM: First commit. Empty repository.
3:17 PM: Complete folder structure. All directories created, .gitkeeps for empty folders.
3:29 PM: Core architecture established. SceneManager, Scene base class, GameWorld. The entire engine skeleton existed.
3:34 PM: Entity system complete. Base Entity class, PlayerCharacter inheritance, InputManager, Game1 main loop.
In 4 hours: complete game engine architecture with scene management, entity system, input handling, content pipeline. All AI-generated from architecture prompts.
Day 2 (October 4) - 56 commits:
Complete menu system - main menu, pause menu, options. Audio system with volume sliders. Multi-platform save system (Steam Cloud + local fallback). Settings persistence. Character selection screen.
Day 3 (October 5) - 7 commits:
Testing & polish day. Unit testing infrastructure established. Tests passing. Menu refinements. Day of consolidation.
Day 4 (October 6) - 13 commits:
11:57 AM: Fixed timestep, variable rendering - the performance foundation that would matter later.
10:12 AM: "added player damage" - Player can take damage!
11:31 AM: Game over screen when player dies.
Afternoon: Weapon system foundation. Experience/leveling system. Massive refactoring spree - 13 commits in 28 minutes fixing interconnected systems.
End of day: HUD with health bars, player damage/death, weapon architecture. Game systems interconnecting. Enemies still weren't dying.
Day 8 (October 10) - 31 commits: THE BREAKTHROUGH
8:35 AM: "projectiles and stuff working, but camera and everything still broken"
1:55 PM: "enemy may be taking damage"
1:57 PM: "enemy taking damage!"
2:03 PM:"FIRST ENEMIES KILLED!"
Combat loop working end-to-end. Player shoots, projectiles fly, enemies take damage, enemies die. The game existed.
Day 8: Projectiles working, particle effects, health and gem pickups
Day 9-13: More weapons. More enemies. Wave spawning. Difficulty progression. Economy. Shop. Permanent upgrades. Upgrade tree. Character unlocks. The game was playable.
Day 14 (October 16) - 35 commits:
Tilemap system
Procedural terrain generation with Simplex noise
Terrain collision
Infinite world generation
Players could now dash through forests, trees blocking movement, terrain stretching infinitely
By Day 14:
Shop
Economy
Permanent upgrades
Multiple characters
Multiple weapons
Multiple enemies
Wave spawning
Leveling
Item pickups
Menus
Settings
Save/load
Character selection
Terrain system
457 commits in 14 days. Average: 32.6 commits/day. Peak: 56 commits in one day.
End of two-week sprint: Performance testing with frame analysis
A friend joined partway through. Working ~1 day/week, maybe some nights. They made significant code contributions. Set up asset packs from purchased bundles. Gave us a library of sprites. When we wanted a new enemy, we had art ready instead of placeholder boxes. They set up content so we could iterate fast.
The system has fallbacks everywhere. If certain files aren't there, it won't crash. You can test a new enemy YAML without having sprites yet.
After Two Weeks: What Actually Existed
Over 400 commits. 10,049 lines of C# code. 1,656 lines of config. 100-120 hours estimated. First and last commits were 2 weeks (minus 3 minutes) apart.
UI System: All custom. Buttons, sliders, checkboxes.
Options: Rebind keys/alt keys, different setups (keyboard/controller), volume (master/SFX/music), resolution swapper, default settings, saving to file.
Scene Manager. Menu manager/flow. Enemy list scene (like Bestiary in Vampire Survivors). Character select scene - dynamically load new characters. Level select scene - dynamically load new levels.
Audio Manager: For calling audio, including SFX/sounds/volume settings.
Input Manager: Creating own engine - must handle every single user input manually. Implemented through high-level class.
Content Loader: Loading of content assets.
Sounds: Menu music, game music, button select/click/confirm, enemy death sound, gem pickup sound, level up sound.
Characters: Starting weapon, base stat modifiers. 4 starting characters, each with unique weapon that's aim-able with cursor.
Enemies: 5 enemies. Base state modifiers, auto sprite loading, scaling config, sprite size and frame speed.
Levels: Background tile settings, terrain object config (hooks into algorithm to place objects around level), wave config. Tested ability to run custom code for a level (could be rain effect on one).
Waves: Spawns enemies based on algorithm and config.
Weapons: 4 aim-able weapons, 5 auto-shooting weapons. Inheritance from base types (ranged, melee, AOE, random spawn). Level up stats built into config.
Passive Upgrades: 2 passive upgrades.
Pickups: Gem/health potion.
Level up: On level up, ability to select from random upgrades - new weapon, upgrade to current weapon, new passive, or upgrade to existing passive.
Movement: Dash (blur on dash), walk, blocking by terrain objects (if tagged as Blocking), aim cursor to shoot primary weapons.
Physics engine/Collision detection: Enemies collide with other enemies and push back. Enemies collide with player. Projectiles collide with enemies and knock back. Implemented highly efficient spatial partitioning algorithms.
Particle System: Enemies explode on death into particles of their sprite.
Damage Numbers: Varies color, movement, length of visibility based on damage number. Batching/spacing for clarity.
Damage numbers, leveling up, visual effects
HUD: Weapon/passive icon, health bar, dash icons with cooldown (if you have 3 dashes, you have 3 icons), health count, enemies killed, damage done, FPS, UPS (updates per second), frames dropped count, XP bar.
Performance: 60 FPS. Game does not slow down when lagging. 1 minute = 1 minute. Ever played a game where when it lags, the actual game time goes slo-mo? Not here.
HUGE mob counts: Thousands have been tested. Huge amount without dropping frames. Even if pushed too far, the game does not slow down.
Fast forward mode: Can fast forward the game on toggle (1x, 2x, 3x, 5x, 1x speed).
System Design: Object-oriented, config-driven, modular, expandable.
I am under no delusions - the current state was not polished, or even a fun game yet. But the amount achieved in two weeks? I was very proud of that. I'd become disillusioned in my work and investments. Everywhere I went, I was hitting blockers. Sometimes told things I knew were wrong, other times I suspected but had no evidence. I'd never built a game before. This was my first serious attempt at seeing what was possible.
After the Sprint: Back to Reality
Went back to work. Continued weekends and occasional nights for a week or two while the project was fresh. After that, mostly weekends.
January 5, 2025 - Three months into development
One of the main issues: hallucinations. Function names, classes, variables that didn't exist. I created compressed versions of the codebase to reduce this. Scripts that boiled code down to file names, class names, function names, connections between them. Codes and abbreviations to minimize characters without losing accuracy. You could reconstruct it perfectly. That worked. I didn't have an automated way to keep it up to date besides just running the scripts, but it was a technique I kept using in other projects.
December 7, 2024: The README Hack
Got annoyed tagging files with @ symbols every single time in Cursor. Had an idea: create a README.md with system documentation. Tag the README once, and the AI could reference everything.
Started documenting all the systems, architecture summaries, code patterns. Every chat session: "Please read the README before implementing this feature."
This was a precursor to what would later become the claude.md or cursor rules file.
January 23, 2025: Cursor Rules file launched (version 0.45.x). That's the first time cursor rules came out. I'd been doing it manually for almost 2 months already.
Late 2024/Early 2025: Cursor Gets Nerfed
I think there were two different times Cursor got nerfed. One in late 2024, one in early 2025. Got really slow. Could feel it was worse, and it was. It wasn't reading stuff properly. Totally messed up.
That's when I switched to Claude Code full-time.
January 2025: Remote Coding with Voice
I went on a 1.5-hour road trip as a passenger. Before leaving, I set up Parsec for remote desktop access, text-to-speech on my computer, and routed my phone's microphone to my PC so I could speak commands remotely.
I also had auto-commit and push enabled, and the game was set to auto-play. The AI knew how to run the game automatically and select specific weapons for testing.
While driving through the countryside, I was actually prompting with my voice, creating weapons, viewing them in real-time on my phone screen via Parsec, and giving feedback - all remotely. Voice to code to game to visual feedback, from the passenger seat of a moving car.
January/February 2025: The 99% Lesson
Went back to that SaaS website. Got it to 99% complete. Ready to send it out. But those icons weren't loading. I decided to delay sending it out.
Never sent it. A year later, it's still there.
Then I posted about the game on Twitter. The reactions were... interesting.
ThePrimeagen challenged me to send the code. I did. He confirmed he had access to the code, but didn't follow up.
Jonathan Blow (who I have great respect for) didn't believe it was 100% AI-coded. He pointed out some cosmetic issues - white text on white background, things that didn't look polished.
And I realized: my SaaS project died because of perfectionism. I'm a perfectionist. But as Steven Pressfield says, perfectionism is one of the resistances. Seth Godin: you can ship, get feedback, iterate.
That ugly text? It has no effect on gameplay. It's probably not the best first impression, but if you click through and play, it doesn't matter. It's on the Trello, but I never had time to fix it before launch.
So I shipped it anyway. Ignore the haters. Ship.
Side Projects: Proving the Speed Was Real
10-day multiplayer game jam (Astro Breaker): Full game. 5-10 players simultaneously. Automated testing. Launched and worked. Built with another guy who hadn't made a game before. Proved the speed was real.
Astro Breaker - 10-day multiplayer game jam
24-48 hour Pixelmon prototype: Built enough to get a trailer out. Data adapters, databases, automated testing. Never finished, but good test.
Topiamon prototype - 48-hour build
March 2025: 6 Parallel Agents & GitHub
Before going away in March 2025, I tested Claude Code with multiple agents. Managed to spawn six agents at once. Six agents working simultaneously on the codebase.
Hooked it up to GitHub through the API. Connected to GitHub, pulled down bugs, created issues. They went through fixing bugs autonomously.
At that time I didn't have git worktrees set up, so when sessions closed there wasn't an easy way to cd into the branches - it was tedious. But it worked.
The Tactical FPS Game: Brutal Lessons
Got frustrated with Cursor getting nerfed - could feel it was worse, not reading stuff properly. So I switched to Claude Code full-time.
Thought: let's make a game quickly to test it. Figured I should be able to do it pretty fast.
Day 1: Core logic of the game done. Core game loop. Shooting, planting bomb, defusing, rounds, games, win conditions. Mostly there. No level - random piece of ground in the sky. Placeholder guns or maybe no guns yet. The structure was there.
VoxFire early development
Early VoxFire gameplay
Then it grew. The other guy found a free Minecraft-style tactical map someone created. We retextured it, remodeled various areas for competitive angles.
VoxFire - Tactical FPS built on Hytopia
We were building on the Hytopia platform, and problems emerged. Cold start problem - no players. So we decided to make AI bots. Old-school bots, not LLMs. State machines. Over half the codebase is dedicated to these bots - at least 60,000 lines of code in a 100,000+ line codebase. Teamwork and coordination, different difficulty settings, the works. Over 400,000 plays across both modes.
I thought about how I play tactical FPS games. What decisions do I make? What are the discrete states in terms of inputs and outputs? What makes me do certain things, go certain places? Attackers can be more random, but defenders are regimented. Translated that into bot logic.
The other guy created groundwork while I was away. When I came back, I worked on bots for weeks. Added more and more logic.
SDK issues. They kept changing the SDK. Either the client or the website, things broke. We lost hours. Days. Sometimes a week on critical issues we couldn't debug. Unknown dependencies we couldn't see into.
Got it live, then hit performance issues. Local servers were far better than production. Don't know if we didn't test enough or if they downgraded servers. Massive performance issues.
We had to spend huge amounts of time trying to improve performance. Performance is one of the hardest things. Huge codebase, lots of situations, bots doing things. You can have baseline performance, then things that happen on certain ticks causing spikes. How do you detect them? How do you measure, aggregate data, replicate issues, pull them apart?
We made good tools. Made progress. Kept fixing. Eventually got to a point where it was pretty good.
Then we found out most players were mobile. And not just mobile - low-end mobile.
We'd added mobile controls in the last 24-36 hours before launch. They sucked. Could barely play, barely shoot. Once we realized this, we tested other games, learned, improved controls.
Then: client-side optimizations. Much was on the engine, so there's only so much we could do. We did what we could. Made it responsive. Added view models - which was a limitation of the engine, but we found a workaround.
We created a separate instance of 3JS on top of the game. A state machine that hooks into messages from the game about what state it's in. Based on your inputs - swapping weapons, shooting - it has the data (bullets in gun, fire rate, which gun). It replicates the weapon locally on your client. Client-side prediction.
When you click shoot, it shoots. It's fake, but that's what most games do. We couldn't simulate particles hitting walls perfectly, but we did add trails off the gun.
Then we realized: people don't like to wait. If you join, you might be waiting a minute or two for the round to start. So we made a deathmatch mode. That's our most popular mode now.
Retention still wasn't amazing. We tried increasing it - performance, tutorials, better controls. Got to a certain point and stopped there.
The Arcade: Moving Off The Platform
After the tactical FPS game, we thought: we can do overlays with 3JS for view models. Why not make an arcade with 2D/3D games using Phaser or 3JS?
Because they're not linked to the actual SDK, they wouldn't break when they update it. And technically there's the ability to move them off onto another site - they're mostly raw HTML, JS, CSS. There's some Hytopia-specific code, but it wouldn't be too hard to rip out.
Vibe coded up some basic games for an MVP. People liked it. Recently we resumed it - have 12 unique arcade games in the works. Planning to launch with 5 soon.
The Arcade - 12 games in development (with sound)
AI Co-Op in One Day
The AI co-op thing: done in one day. The player was hard-coded as a single player. AI was able to separate that out enough that there'd be more than one player. Created a player manager or something. Could have multiple players - one human, others AI co-ops.
They're good at the game. Advanced stuff - they protect the player when you're surrounded or getting injured. Come back and help you. Effective.
5 AI co-op players - they protect you when surrounded
That facilitated the autoplay later on. That facilitated automated testing. It's building up tools. Seeing your game being played automatically like that - crazy.
Steam Next Fest: The 10-Day Sprint
In September 2025, I applied to Steam Next Fest and got in just in time. Suddenly I had a deadline - maybe two or three weeks until Next Fest.
After a couple days I realized: I need to get onto this. You need to submit multiple stages. I submitted my Steam front page, then got to work.
Went hard for about 10 days. Got my Trello going. Assigned all eight agents to the project. Worked intensively. 1,600 commits in 10 days.
Daily Commits - 10-Day Sprint
72
75
58
48
167
122
171
111
118
199
1
2
3
4
5
6
7
8
9
10
October 2025 · ~1,600 commits in 10 days
24-Hour Commit Heatmap
Each cell = commits that hour. Sleep gap clearly visible 2-6am. Peak: 35 commits (Oct 5, 5pm)
● commit (1,323)● PR merged (94)● branch switch (587)Click type to filter · X = timestamp · Y = worktree
Commit Flow - Guitar Hero Style
Commits spawn on right, flow left · Each row = one git worktree
● commit● PR merged● branch switchClick type to filter · ~1 sec to cross
Automated testing breakthrough. I figured out how to launch the game in a headless window with CLI parameter flags. Different scenarios: select a certain level, character, spawn enemies, force level up a weapon.
Let's say there's a bug in a weapon. Agent can fix it, start the game, run that weapon. Check for fatal errors. There's huge amounts of logs - it can add more if needed. Run the game for a certain number of seconds. The game plays through AI (old-school AI code, not LLM). Then look at logs, debug any fatal errors, commit and push, or fix more.
This codified testing workflow was effectively a precursor to what would later become Claude Skills - teaching the AI reusable patterns for specific tasks.
This enabled performance testing too. Automated performance benchmarks. Look for performance issues, attempt to fix them, benchmark, run it without the fix, try to fix it, rerun under similar situation, confirm if it fixed the error. Verifiable way to confirm fixes.
Performance is tough. You can have baseline performance, then things that happen on certain ticks causing spikes. How do you detect them? Things might only happen occasionally. Things might be correlated, adding up. How do you measure? How do you aggregate data? How do you replicate? How do you test it? Pull it apart?
We had to wrap different functions with performance monitoring. As it goes down into functions (like a flame chart), you might have to wrap more and more code further down. I had a standard way to do that. Find exactly where the performance issue was, then verify and test. Otherwise you might know "the performance issue is in this area" but that code could have heaps of functions calling heaps of functions.
You can use Visual Studio profiler and get the flame chart. I also built in an F1 menu earlier that let you pause the game, give yourself items, spawn enemies, fast forward time, rewind time, create snapshots, load snapshots. The game saves snapshots periodically so you can roll back. It doesn't save everything, but it's good enough for testing.
I also created an entity inspector. You can click any entity and use reflection to drill down into all the attributes and nested objects. Enemy has stats, state, behavior - drill down into all of them. Live updates too.
Entity inspector - real-time attribute drilling
Later on I created a Windows app to view and edit YAML files. Not fully finished, but it was working. Nice way to view them instead of having AI do it. If I needed someone to balance the game, I'd either give them AI or have a YAML config viewer. It can get complex - especially if an enemy is in a level, that's harder to do. Not finished.
There was a huge rush. I submitted. Really hoping it would get approved in time.
Friday came. Next Fest starting Monday. I thought: might be game over.
Luckily Valve was working over the weekend. They approved it. It got in.
The other thing: I'd had it working on Steam Deck at some point. As I made changes, I tried again and it hit a fatal crash. Never had enough time to reestablish it on Linux/Steam Deck. Locally it was working on Linux though. It was comfortable on Steam Deck with controller support.
I did considerable work around controllers, input management. Used the command pattern so I didn't hard-code buttons. Made sure it was compatible with controllers, touchpads, and similar inputs. MonoGame provided heavy lifting, but I still had to set it up properly.
Did considerable work around settings too. Not perfect, but you can rebind controls, change resolution, change sound and music levels.
Created a UI system with standard elements - buttons, scroll bars, all that.
Technical Deep Dives
Performance optimizations:
Started with a quad tree for broad-phase collision detection. Did a lot of early work with performance. Then later switched to a spatial hash grid (uniform grid cells). Benchmarked it. Definitely faster, no bugs.
Implemented object pooling for most things - enemies, projectiles. Maybe not pickups. Created pre-warming cache. There were issues where some enemies spawn at the tick of the minute and it'd stutter. So I created a system in the loading screen that pre-warms the cache.
Did fair bit around batch rendering. Various performance techniques - you can see them in the git logs.
Thousands of enemies - no performance degradation
Build process: Created a compile/build step that creates texture atlases. Obfuscation step. Encrypted player save data. Encrypted and packed YAML configs and files into .pak files using encryption. All bundled up as part of build process.
Created full process: do the build, compile assets, create atlases, obfuscate code, encrypt and pack YAMLs, create different builds, upload them to Steam automatically based on my request (deploy to demo build or whatever). It would switch all these different flags based on build type - couldn't use dev tools or cheat tools in release builds. Turn off most logging and performance tools.
Separated update loop and draw loop: Enables continuing to run update logic even if it lags. Separated game logic from rendering. Game won't slow down if it's lagging. Won't get slower or faster based on FPS. Drops frames if it can't render them.
Prevents exploits. Prevents slowdowns. If there's a lag spike during a dash, you still land where you expected. Even if during that dash there is a lag spike, you'll still land where you expected.
This enabled pausing and speed ups. I can press hotkeys and speed up the game. Some issues over time, but mostly fixed. Maybe a handful of issues at 5x or 10x speed, but it's effective for playing at 2x or 3x speed to get through stuff faster.
Fast speed gameplay - 2x/3x acceleration
Automated tests: I tried at the start but couldn't get them working. A few dry runs, but no automated tests initially. Later did deep research on ChatGPT. It went away, looked into obscure MonoGame forums, people talking about how they did automated testing, headless tests, normal tests. Came back with a solution.
Claude implemented it. Still some issues. Went back and forth with ChatGPT and Claude, more deep research. Eventually got it working.
Problem was the game had progressed so far it was hard to create full tests. I did add regression tests. And the best thing: the game can play with AI autoplay. Not automated testing of code, but testing the game itself. Opens up performance testing, balance testing, regression testing.
Nested CLAUDE.md files: Created them into the repo. Like the enemy config folder has a separate CLAUDE.md there. Really good.
Later on I started using Codex somewhere around the final 10-day sprint before Next Fest. Much slower. Only used it for two out of eight agents. For larger features.
Some worked perfectly. Some didn't. I tried to refactor the entire codebase to make it more of an engine. Couldn't get there. It likely could now.
Local Co-Op in One Day
Made local co-op. Working. Then made online co-op. In one day. It's getting close - not 100%, haven't fully tested, but almost working. Effective.
Local co-op - two players on one machine
Convention Over Configuration: The System
The entire system follows Rails-inspired patterns. Drop a Weapon.yaml in Config/Weapons/ with the right name. Add sprites to Content/Weapons/WeaponName/. System auto-discovers it. No manual registration. Meta-programming handles everything.
You can technically, with some work, separate the code entirely to the point where you had the engine separate and the game code as its own module. You could swap in and out different game modules. You could allow modding - let people know the schema and expected things, let them drop in new YAMLs and content files. New levels, characters, weapons, enemies.
Depending on how it works, you could allow people to insert new .cs files as long as they meet the interface and right folders and file names. Drop in new C# files for new weapons, abilities, states, behaviors, events.
Adding a new thing usually requires: a YAML file, or a .cs file, or a combination of YAMLs, content (sound, sprites), and .cs files. Depending on what you're adding.
Right now it's fully open. The system is set up to allow that. With some rework, it could be blocked off at different levels depending on what I want to do.
If I wanted a more general engine (not only Survivors-likes), I could keep modularizing. Input system separate. Content loader separate. Asset system. General method for loading YAMLs. Could all be separated. There'd be a decent chunk of refactoring, but it's set up in a decent spot.
The folders - if you merge the folder structure from GameEngineFramework and Scripts, it'd probably be better.
You could swap out the entire game's content - weapons, enemies, levels, characters - without touching C# code. YAML files and assets. Want custom behavior? Add a .cs file following naming conventions. Factory system finds it automatically.
Debug tools: game speed, camera zoom, level controls, performance monitoring
There's States and Behaviors for enemies. Weapons and Abilities for the player. Status effects. Events. You can add new ones with single new files.
Character abilities: Q and R skills for different characters
There's even one called AOEAttack State or something. Used for both ranged attacks (enemy gets within distance, triggers attack - could be shooting projectiles or meteor falling) and melee attacks (enemy gets really close, triggers animation, circle forms, shockwave). By changing YAML parameter values, we have separate types of attacks.
Enemy AI in action: states, formations, slime trails, charge attacks
Everything is convention over configuration. Character has a name. You'd have Config/Characters/CharacterName.yaml. Under Content/Sprites/Characters/CharacterName/ you'd have sprites in certain format (idle_01.png or whatever). System expects certain format. Can be multiple formats - asset content loader handles different things for enemies and players, four-directional sprites or left and right.
As long as you put it in the right format and drop it in, someone without coding experience (as long as they know how it works) can add new content and change the game.
Asked Cursor to create a "crazy complex weapon" - one-shot it
Demo Trailer
Loading trailer...
Play Epic Survivors
Try the free demo or add to your wishlist on Steam (Demo button is bottom-right on the Steam page)