Feel free to join the next Helmholtz Hacky Hour #26 on Wednesday, April 21, 2021 from 2PM to 3PM!

Commit 8bd7c702 authored by Martin Lange's avatar Martin Lange

rewrite of the general ECS section

parent 552d1b82
Pipeline #12188 passed with stage
in 34 seconds
# ECS Tutorial with Java and Artemis-odb
This projects demonstrates the use of an Entity-Component-System (ECS) for the implementation of an individual-based model (IBM). We use Java and the ECS library [Artemis-odb](https://github.com/junkdog/artemis-odb) to build a simple grassing model.
This projects demonstrates the use of an Entity-Component-System (ECS) for the implementation of an individual-based model (IBM). We use Java and the ECS library [Artemis-odb](<https://github.com/junkdog/artemis-odb>) to build a simple grassing model.
The model description is structured following the ODD protocol (Grimm et al. 2006, 2010) to demonstrate the good fit of ECS and ODD. The complete model code is presented along with the descriptions. ECS-specific remarks are shown as indented notes:
The complete model code is presented along with the descriptions. ECS-specific remarks are shown as indented notes:
> ECS-remarks look like this.
......@@ -25,31 +25,32 @@ The model description is structured following the ODD protocol (Grimm et al. 200
## How to use this project?
The main purpose of this project is for you to read this page.
This document contains the most important information explaining the basics of an ECS. It is recommended that you read this document from top to bottom, as this is probably the most effective way to absorb the content.
See the **[How to](md/howto.md)** for details on further usage, from simply running downloaded binaries to cloning and building it on your machine.
The model description is structured following the ODD protocol (Grimm et al. 2006, 2010) to demonstrate the good fit of ECS and ODD.
See the **[How to](md/howto.md)** for details on further usage, from simply running downloaded binaries to cloning and building it on your machine.
## What is an Entity-Component-System?
Entity鈥揅omponent鈥揝ystem (ECS) is an architectural pattern originating from game design, but also useful for the development of (individual-based) models (IBMs).
Model development is an iterative process. For example, submodels are frequently changed or fully replaced by new or alternative versions.
A design approach that facilitates this style of work is the Entity鈥揅omponent鈥揝ystem (ECS) pattern, by decoupling the state of the model from the logic. While it is rooted in game design, it has proven to be useful for IBMs.
Entities of a model are just that in an ECS, generic "somethings", or merely just an ID. Each entity has one or more components, which can contain state variables or simply serve as labels. What an entity is results from the composition of it's components, and this composition can even change at runtime.
In ECS terms, *entities* are an abstract handle to refer to what we usually consider entities in the IBM world. For example in a predator-prey-model, each predator and each prey is represented by an entity. In a livestock model, each individual animal, each herd, and each market is represented by an entity.
Systems are where the logic of the model sits, and represent (in most cases) what is called a submodel in modelling terms. Each system operates on all entities with a certain combination of components. Examples of this kind of logic could be:
Each entity has one or more *components* which contain the entity's state variables. What can happen with an entity in the model results from the composition of its components. To resume the livestock example, all three types of entities could have a location component, but only animals would have an age. The herds could e.g. have a component holding their trade partners.
* If it has a position and a velocity, it moves (i.e. changes position).
* If it has a velocity and a mass, is falls due to gravity (i.e. changes velocity).
What is called a submodel in modelling terms are *systems* in ECS. Systems contain the logic of a model and operate on a certain combination of components. Examples of this kind of logic could be:
The respective systems do not care what the entity really "is", nor are they interested in any further potential components.
* If something has a position and a velocity, it moves (i.e. changes position).
* If something has a velocity and a mass, is falls due to gravity (i.e. changes velocity).
Besides benefits for performance and maintainability, ECS offers great flexibility to create many different kinds of entities. This is mainly an advantage in the field of game design, were ECS was invented. However, in individual-based models, there are rarely more than a few "types" of entities, so how can IBM design benefit from ECS? Here are some thoughts:
Because systems are only concerned with certain components relevant to their logic, while further components are ignored, the ECS approach enables independent development of different aspects of a model.
* Flexibility: ECS is perfectly suited for iterative development of, or experimentation with a model. Submodels can be easily swapped out. Entities can get new or different state variables easily, if a new or alternative submodel requires it.
* Maintainability: Data (components) and logic (systems) are well separated, and the structure of the code follows well-known principles.
* ...
* With an ECS-thinking about "types" of entities, much more types can arise in the model. E.g. from the view of a birth submodel, a pregnant animal is a different type than a non-pregnant animal (which is not of interest for the system)
Component composition can also change over time. Composition changes are often performed by systems, and effect which systems process an entity.
...
A hurdle to overcome when starting to use ECS is to replace thinking about the type of an entity by considering which components/state variables are affected by which systems/processes. The model dynamics then emerge from the interaction of systems via overlapping components.
## Model purpose
......@@ -61,7 +62,7 @@ The purpose of this model is to demonstrate the use of the ECS approach for indi
**Components**
In this grassing model, the only entities are grassers. All grassers possess the components `Position`, `Heading` and `Energy`. Behaviour of grassers is governed by the components `IsGrassing` or `IsSearching`, which each grasser possess one of.
In this grassing model, the only entities are grassers. All grassers possess the components `Position`, and `Energy`. An optional component `Heading` determines the current activity of each grasser.
> Components must extend `com.artemis.Component`.
......@@ -166,6 +167,8 @@ Spatial and temporal scales of the model are arbitrary. The duration of a model
Processes in the model are grass growth, grasser metabolism, grasser reproduction and the two grasser behaviours grassing and searching. Processes are executed in that order.
> During initialization, systems are added to the world in a certain order, which defines the order of their execution. As systems interact indirectly via components, it is important to understand how the order of execution shapes the resulting dynamics.
>
> In the ECS, processes (or submodels, or systems) are added during world construction via `with(...)`. Resources are added via `register(...)`.
```java
......@@ -369,12 +372,14 @@ public class Reproduction extends IteratingSystem {
if(random.rng.nextFloat() < reproductionProb) {
var pos = position.get(id);
var e = energy.get(id);
e.value /= 2;
int entity = world.create();
world.edit(entity)
.add(new Position(pos.x, pos.y))
.add(new Heading(random.rng.nextFloat() * 2 * (float) Math.PI))
.add(new Energy(e.value / 2));
e.value /= 2;
.add(new Energy(e.value));
}
}
}
......@@ -388,7 +393,7 @@ If the grasser's energy is 1.0 or above, it does nothing. Otherwise, the grasser
> The behaviour is switched by adding component `Heading`.
>
> We extend `IteratingSystem` again, and use `@All(...)` as before, but with an additional `@Exclude(...)`. This time, we want only entities that have no `Heading`, which is optional according to our model logic. Thus, grassers that are searching instead of grassing will not be processed by this system. In the `else` branch at the end of the code, we add a component `Heading`, which means that the respective entity will not be processed by this system in the next step.
> We extend `IteratingSystem` again, and use `@All(...)` as before, but with an additional `@Exclude(...)`. This time, we want only entities that have no `Heading`, which is optional according to our model logic. Thus, grassers that are searching instead of grassing will not be processed by this system. In the `else` branch at the end of the code, we add a component `Heading`, which means that the respective entity will not be processed by this system in the next step, but by the `SearchBehaviour`.
```java
/// file:src/main/java/grassing/sys/GrassingBehaviour.java
......@@ -426,6 +431,7 @@ public class GrassingBehaviour extends IteratingSystem {
if(e.value >= 1) {
return;
}
Position pos = position.get(id);
float g = grass.grass.get((int) pos.x, (int) pos.y);
if( g - consumption > minGrass ) {
......@@ -439,7 +445,7 @@ public class GrassingBehaviour extends IteratingSystem {
}
```
### Searching
### Search
The grassing behaviour system works on all entities that have the components `Position` and `Heading`. Thus, it ignores grassers that are currently grassing (and thus have no `Heading`).
......@@ -482,6 +488,7 @@ public class SearchBehaviour extends IteratingSystem {
@Override
protected void process(int id) {
Position pos = position.get(id);
float g = grass.grass.get((int) pos.x, (int) pos.y);
if( g >= minGrass ) {
heading.remove(id);
......@@ -493,6 +500,7 @@ public class SearchBehaviour extends IteratingSystem {
private void randomWalk(int id) {
var pos = position.get(id);
var head = heading.get(id);
head.angle += (float) random.rng.nextGaussian() * maxAngle;
var h = MathUtil.heading(head.angle);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment