The numbers that matter.

All data captured using Visual Studio CPU profiler and memory diagnostics over a 27 second gameplay session. Generation timing measured using std::chrono with console output.

7.7x Generation speedup

Switching from rejection sampling to Poisson disk + spatial hash grid. 84ms -> 11ms on an 80x80 tile map. Direct result of the Spatial Partition pattern.

54 MB Peak memory

Flat across the 27 second session. No observed growth, confirming no memory leaks during normal gameplay. The Flyweight pattern keeping shared collision data to one allocation per type helps here.

91.34% Render cost

Of total CPU time in the profiled session, rendering accounts for 91.34%. Game logic and AI: 8.66%.

Where the time goes.

Function % CPU Note
Game::render (total)91.34%
Map::render50.17%terrain tiles
VoronoiDiagram::renderDebug28.93%dev only
Other render calls12.24%
Game logic and AI8.66%small
The 28.93% from VoronoiDiagram::renderDebug is a development-only renderer that draws boundary lines between every Voronoi region. It's on in debug builds to check region assignment. Disabling it in a release build removes that overhead entirely. This was found by profiling - it wasn't obvious before running the tool.
Map::render50.17%
Voronoi renderDebug28.93%
Other render12.24%
Game logic and AI8.66%
Algorithm Time Complexity
Rejection Sampling84 msO(n²)
Poisson + Spatial Grid11 msO(k) per tile
Runtime regeneration10 msIn-place reset

Flyweight impact on memory.

The Flyweight pattern's memory benefit is in the collision system. Without it, each world object placed by Perlin noise would own its own copy of the collision shape data. With a 128x128 map and Perlin noise placing objects at density, that's potentially thousands of copies.

Without Flyweight

Each world object owns its collision shapes. 1,000 tree stumps = 1,000 separate vector<CollisionShape> allocations, each containing the same polygon data.

O(n) memory per object type

With Flyweight

WorldObjectTemplateManager stores one list per type. Each instance stores a non owning pointer and an offset. 1,000 tree stumps = 1 shared list + 1,000 sf::Vector2f offsets.

O(1) memory per object type

Atlas Sharing

All world objects share a single sf::Texture atlas via setSharedTexture(). One GPU texture for all forest objects. Same pattern used for item world sprites and inventory sprites.

1 texture for all object types