SortedSubIteratingSystem - GameDevWeek/CodeBase GitHub Wiki
If you have to iterate over sorted entities in a big system with different subtasks you might want to consider implementing sub systems to divide the work and keep your code readable and maintainable. The SortedSubIteratingSystem will make your life easier by providing the required infrastructure.
The SubSystem is a part of a bigger system to provide related functionality. It is responsible to process a user defined family of entities.
Requirements:
- Extend the SubSystem class
- Entity family
- Definition of a processEntity() function
The SortedSubIteratingSystem is a subclass of the SortedIteratingSystem and encapsulates a collection of SubSystems. It iterates over a sorted user defined family of entities and delegates to the SubSystem with a matching family.
Note: The SortedSubIteratingSystem can also perform pre- and/or postprocessing before delegation but make sure to call its super functions (super.update() and super.processEntity()).
Note: The family of the SortedSubIteratingSystem is "global" and affects all SubSystems. The family of a SubSystem is a closer definition of its area of responsibility.
Requirements:
- Extend the SortedSubIteratingSystem
- Entity family
- Provide a comparator to define the order of the entity collection
- Use addSubSystem() to add SubSystems
Note: The order of addSubSystem() calls defines the order of delegation. If SubSystem A and B are responsible for family F and A was added before B then A processes the entity first.
Let’s say we want to create a RenderSystem in a 2D sidescroller.
To support multiple layers (background, foreground…) we create a LayerComponent:
public class LayerComponent extends Component implements Pool.Poolable {
public int layer = 0;
@Override
public void reset() {
layer = 0;
}
}
To render our entities in the correct order we use this component in our comparator:
private static final class RenderComparator implements Comparator<Entity> {
@Override
public int compare(Entity e1, Entity e2) {
LayerComponent l1 = ComponentMappers.layer.get(e1);
LayerComponent l2 = ComponentMappers.layer.get(e2);
return l1.layer - l2.layer;
}
}
Our RenderSystem has multiple sub systems like TextureRenderer, ParticleRenderer and LightRenderer. The TextureRenderer could look like this:
public class TextureRenderer extends SortedSubIteratingSystem.SubSystem {
public TextureRenderer() {
super(Family.all(TextureComponent.class).get());
}
@Override
public void processEntity(Entity entity, float deltaTime) {
render(entity);
}
}
And finally in the RenderSystem we have to add our sub systems (renderer classes) and let them do the magic in the update function:
public class RenderSystem extends SortedSubIteratingSystem {
private final static RenderComparator renderComparator = new RenderComparator();
public RenderSystem(int priority) {
super(Family.all(PositionComponent.class, LayerComponent.class).get(),
renderComparator, priority);
addSubSystem(new TextureRenderer());
addSubSystem(new ParticleRenderer());
addSubSystem(new LightRenderer());
}
@Override
public void processEntity(Entity entity, float deltaTime) {
// Some preprocessing
super.processEntity(entity, deltaTime);
// Some postprocessing
}
@Override
public void update(float deltaTime) {
// Some preprocessing
super.update(deltaTime); // SubSystems will take care of things
// Some postprocessing
}
}
The family of the SortedSubIteratingSystem imposes a restriction on all of its SubSystems to only allow entities of that family. In this case the RenderSystem only accepts entities which have a PositionComponent and a LayerComponent.