Game
Save the Valley
2D sandbox game built from scratch in C++ with a custom engine architecture. Features infinite procedural world generation, multi-weapon combat system, enemy AI with state machines, and optimized chunk-based rendering — all without a game engine.
The Problem
The goal was never to ship a polished product — it was to understand what a game engine actually abstracts away. Most developers use Unity or Unreal and never touch a render loop, an entity component system, or a collision pipeline directly. I wanted to build those things myself in C++ to develop a real mental model of the lower-level systems I'd otherwise take for granted.
Key Decisions
No game engine — pure C++ with SFML as the only dependency
SFML handles the window, input events, and texture rendering, but nothing else. There is no scene graph, no physics engine, no asset pipeline. Writing the entity update loop, the spatial partitioning, and the camera system by hand forced me to think about performance budgets and memory layout in a way that using an engine would have completely hidden.
Chunk-based world instead of loading the full map
An infinite world can't live in memory at once. The world is divided into fixed-size chunks; only the chunks near the player are active. When the player moves past a threshold, the trailing chunks are serialized and unloaded, and the leading chunks are loaded or generated fresh. This keeps memory usage constant regardless of how far the player travels.
Finite State Machine for enemy AI instead of behavior trees
I started prototyping with a behavior tree library but it was overengineered for three states: Idle, Wandering, and Hunting. An FSM with explicit transitions was readable in a single file, easy to debug by printing the current state, and fast enough that hundreds of enemies ran without impacting frame time. Complexity is only justified when the problem actually requires it.
Simplex noise over Perlin for terrain generation
Perlin noise produces visible axis-aligned artifacts at certain frequencies — the terrain starts to look grid-like. Simplex noise is rotation-invariant and has a more isotropic gradient, which produces more natural-looking terrain contours without post-processing. The computational cost is similar.
Outcome
The project took three months of evenings and weekends. By the end I had a working infinite world, a combat system with three weapons, and enemy AI that chased the player across chunk boundaries. More importantly, I gained a concrete understanding of rendering pipelines, spatial partitioning, and game loop architecture that I carry into every project that involves real-time systems.
Features
Procedural World
- Infinite chunks with dynamic load/unload
- Multiple biomes with unique terrain generation
- Autotiling for smooth transitions between tile types
- Collidable objects: trees, rocks, structures
Combat System
- Sword, axe and hammer with dynamic hitboxes
- Health, damage and temporary invulnerability frames
- Attack, damage and death animations
Enemy AI
- State machine: Idle → Wandering → Hunting
- Player detection by range
- Pursuit with obstacle avoidance
Rendering
- Chunk-based rendering (only visible chunks drawn)
- Layered: terrain / objects / entities
- Smooth camera + collision debug mode
Demo
World Gen
Combat