Hello everyone. I hope you’re doing well.
I took a small hiatus due to some things that came up, but I’m back to development. Let’s talk about entities.
Come to think of it, you have never seen anything related to entities except the player placeholder. Let’s start at the beginning.
The Importance System
Most games have some sort of limit to how many objects can exist before things start to break, either explicit or implicit (by hardware availability). I decided to implement an explicit limit in my game. That is – once X objects have spawned, no more can. To do this, I have “tiers” of objects:
- Essential (only the player)
- Important (enemies and interactible objects)
- Not Important (enemy projectiles)
- Decorative (particles with no interaction)
enum EntityImportance {
ImportanceUnknown = 0,
ImportanceDecorative = 1,
ImportanceNotImportant = 2,
ImportanceImportant = 3,
ImportanceEssential = 4
};
If an entity is Unknown or Decorative or NotImportant, it can be deleted to free up spots for more important entities. The order of deletion is as follows:
- Decorative
- NotImportant
- Unknown
An object of any of these tiers spawns while the entity count is at its limit, it instead fails to spawn and immediately deletes itself. Otherwise, the application immediately crashes.
The entity limit is currently 512, which doesn’t allow much room for particle effects, which are also entities (at least, for now).
EntityRegistry and Limits
This is 508 entities, which is almost at the limit of 512. These drops are marked as NotImportant, so they could give up their slot, but it is a lot of usage.
For this situation, I implemented a simple fix:
Allow entities to have their own EntityRegistries.
This comes with two benefits: an entity can keep track of its sub-entities in a registry, and the tick and draw events can be distributed among them.
void Fountain::tick() {
for (int i = 0; i < 1 + ((int) sprayiness / 100); i++) {
if (rand() % 100 < sprayiness)
shootProjectile();
}
particles->tick();
}
particle
s here is simply another EntityRegistry holding the particles that the fountain has created. This has the additional benefit of allowing the fountain to control its own entity count by resizing its registry. This fountain is allowed to use up to 4,096 entities, but if we limit it to 32, we see this behavior:
That’s strange: it shoots in spurts now. Why is that?
Well, if we look back at our entity spawning behavior, we find the answer: entities marked NotImportant fail to spawn if the registry is full (even if those entities are also NotImportant). Thus, the fountain stops spraying until slots free (by the drops hitting entities or the ground).
Another benefit to subregistries is that the global entity count remains super low.
This means we can put a ton of fountains without worrying about game crashes. The only issue is that now we can still place tons of entities, which was the sole reason for enforcing the limit in the first place.
Oh well, it was fun anyway. We’ll fix it if it becomes a problem, but I think this is fine for now. Plus, we can use registries to limit the effect of objects like fountains in case they manage to have drops fall through the floor, for example, by limiting how many can exist (as otherwise they would fall until they exit the map’s bounds).
Bonus
I made a flamethrower. I had to implement the Radial Gradient Brush from Direct2D (doing the blur using successively larger ellipses was really slow) but we got it to work.
Anyway, stay tuned for me yapping about my engine.
See you!
Leave a Reply