Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

So far the entity component systems I've used have worked mostly like Java's artemis:

  • All data in components
  • Stateless independent systems (at least to the degree that they don't require input on initialization) iterating over each entity that contains only the components that particular system is interested in
  • All systems process their entities one tick, then the whole thing starts over.

Now I'm trying to apply this to a turn based game for the first time, with tons of events and responses that must occur in a set order relative to eachother, before the game can move on. An example:

Player A receives damage from a sword. In response to this, A's armor kicks in and lowers the damage taken. A's movement speed is also lowered as a result of getting weaker.

  • The damage taken is what sets off the whole interaction
  • Armor must be computed and applied to the incoming damage before the damage is applied to the player
  • Movement speed reduction cannot be applied to a unit until after the damage has actually been dealt, since it is dependent on the final damage amount.

Events can also trigger other events. Reducing sword damage using armor can cause the sword to shatter (this must take place before the damage reduction is completed), which in turn can cause additional events in response to it, essentially a recursive evaluation of events.

All in all, this seem to lead to a few problems:

  1. Lots of wasted processing cycles: Most systems (save for things that always run, like rendering) simply doesn't have anything worthwile to do when it's not "their turn" to work, and spend most of the time waiting for the game to enter a valid work-state. This litters every such system with checks that keep growing in size the more states are added to the game.
  2. To find out if a system can process entities that is present in the game, they need some way to monitor other unrelated entity/system states (the systaem responsible for dealing damage needs to know if armor has been applied or not). This either muddles the systems with multiple responsibilities, or creates the need for additional systems with no other purpose but to scan the entity collection after each processing cycle and communicate with a set of listeners by telling them when it's okay to do something.

The above two points assume that the systems work on the same set of entities, that end up changing state using flags in their components.

Another way to solve it would be to add/remove components (or create entirely new entities) as a result of a single systems work to progress the games state. This means that whenever a system actually have a matching entity, it knows that it is allowed to process it.

This however make systems responsible for triggering subsequent systems, making it difficult to reason about the programs behaviour since bugs won't show up as the result of a single system interaction. Adding new systems also gets harder since they can't be implemented without knowing exactly how they affect other systems (and previous systems might have to be modified to trigger the states the new system is interested in), kinda defeating the purpose of having separate systems with a single task.

Is this something I'll have to live with? Every single ECS example I've seen have been real time, and it's really easy to see how this one-iteration-per-game-loop works in such cases. And I still need it for rendering, it just seems really unfit for systems that pause most aspects of itself every time something happens.

Is there some design pattern for moving the game state forward that is suitable for this, or should I just move all logic out of the loop and instead trigger it only when needed?

share|improve this question
    
You don't really want to poll for an event to happen. An event only happens when it occurs. Doesn't Artemis allow for systems to communicate with each other? –  Sidar May 4 '13 at 5:10
    
It does, but only by coupling them using methods. –  Aeris130 May 7 '13 at 11:12
add comment

1 Answer

My advice here is coming from past experience on an RPG project where we used a component system. I will say that I hated working in that gameside code because it was spaghetti code. So I'm not offering much of an answer here, just a perspective:

The logic you describe for handling sword damage to a player... it seems one system should be in charge of all of that.

Somewhere, there's a HandleWeaponHit() function. It would access the player entity's ArmorComponent to get the relevant armor. It would access the attacking weapon entity's WeaponComponent to perhaps shatter the weapon. After computing final damage, it would touch the MovementComponent for the player to achieve the speed reduction.

As for wasted processing cycles... HandleWeaponHit() should only be triggered when needed (upon detecting the sword hit).

Maybe the point I'm trying to make is: surely you want a place in code where you can put a breakpoint, hit it, and then proceed to step through all the logic that is supposed to run when a sword hit occurs. In other words, the logic shouldn't be scattered throughout the tick() functions of multiple systems.

share|improve this answer
    
Doing it this way would make the hit() function baloon as more behavior are added. Let's say there's an enemy that falls down laughing every time a sword hits a target (any target) within its line of sight. Should HandleWeaponHit really be responsible for triggering that? –  Aeris130 May 7 '13 at 11:14
1  
You have a tightly enmeshed combat sequence so yes, hit is responsible for triggering effects. Not everything has to be broken out into little systems, let this one system handle this because it really is your "Combat System" and it handles... Combat... –  Patrick Hughes Jun 2 '13 at 19:42
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.