ObzLib container
obz::ring_buffer
A runtime-capacity circular buffer for fast FIFO storage.
Bounded Churn
Some game systems create lots of short-lived work. Floating combat text is a good example: enemies take damage, numbers pop out of the hit location, and the UI system turns those events into little animated labels.
You want the system to accept bursts, but you do not want an unlimited number of text events building up if the player hits a crowd of enemies at once. A ring buffer gives the queue a clear maximum size.
struct combat_text {
float x;
float y;
int damage;
};
obz::ring_buffer<combat_text> events(64);
events.push_back({enemy.x, enemy.y, 12});
events.push_back({boss.x, boss.y, 42});
A Queue That Walks Around Its Own Memory
The interesting trick is that the buffer moves through fixed storage instead of moving the storage around. New values enter at the tail. Old values leave from the head. When either end reaches the physical end of the allocation, it wraps back to the beginning.
std::size_t next_index(std::size_t index) const {
return (index + 1) % capacity_;
}
That is why the container can keep FIFO order without resizing. The oldest event is still the next one out, even when the physical slot numbers have wrapped around.
Oldest First, With A Limit
A frame can drain pending events in order and decide what to do when the queue is full. That decision stays visible in the game code instead of becoming accidental memory growth.
combat_text event;
while (events.pop_front(event)) {
spawn_floating_text(event);
}
The clean-code point is the boundary: ring_buffer owns the circular indexing and storage
lifetime, while the game owns the policy. If 64 pending events is enough, the system stays predictable.
If it is not enough, the caller has to make that design decision deliberately.