@@ -19,7 +19,7 @@ The complete model code is presented along with the descriptions. ECS-specific r
*[References](#references)
*[Appendix](#appendix)
<imgtitle="Screenshot of the model"src="https://git.ufz.de/oesa/ecs-tutorial/uploads/aca134ea4e37bada52effa167172d51a/image.png"alt="Screenshot of the model"width="400">
<imgtitle="Screenshot of the model"src="https://git.ufz.de/oesa/ecs-tutorial/uploads/78a0b08e3e5d4f64383337735f133b43/image.png"alt="Screenshot of the model"width="400">
*Screenshot of the model*
...
...
@@ -62,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`, and `Energy`. An optional component `Heading` determines the current activity of each grasser.
In this grassing model, the only entities are grassers. All grassers possess the components `Position`, and `Energy`. An optional component `Movement` determines the current activity of each grasser.
> Components must extend `com.artemis.Component`.
...
...
@@ -84,36 +84,36 @@ public class Position extends com.artemis.Component {
}
```
Component `Heading` contains the angle the entity is heading towards, in radians.
Entities have components `Heading` only when searching, while there is no defined heading when they are grassing. The presence or absence of the component thus defines an entity's behaviour.
Component `Energy` contains the entity's current energy budget.
```java
/// file:src/main/java/grassing/comp/Heading.java
/// file:src/main/java/grassing/comp/Energy.java
packagegrassing.comp;
publicclassHeadingextendscom.artemis.Component{
publicfloatangle;
publicclassEnergyextendscom.artemis.Component{
publicfloatvalue;
publicHeading(){}
publicHeading(floatangle){
this.angle=angle;
publicEnergy(){}
publicEnergy(floatvalue){
this.value=value;
}
}
```
Component `Energy` contains the entity's current energy budget.
Component `Movement` contains the direction the entity is moving, in radians.
Entities have components `Movement` only when searching, but not when grassing. The presence or absence of the component thus defines an entity's behaviour.
@@ -222,9 +222,9 @@ Grassers have two different behaviours: grassing and searching. Behaviour change
## Initialization
The model is initialized with `NUM_GRASSERS` grassers. All grassers start with components `Position`, `Heading` and `Energy`.
The model is initialized with `NUM_GRASSERS` grassers. All grassers start with components `Position` and `Energy`. They start with the grassing behaviour, as they initially have no component `Movement`.
Position and heading are initialized randomly. Energy is initialized with 1.0.
Position is initialized randomly. Energy is initialized with 1.0.
@@ -336,7 +335,7 @@ The grasser reproduction works on all entities that have the components `Positio
In each iteration, each grasser reproduces with a fixed probability.
When reproducing, energy is split in half between the grasser and it's offspring. The offspring starts with the grassing behaviour (i.e. with a `Heading`).
When reproducing, energy is split in half between the grasser and it's offspring. The offspring starts with the grassing behaviour (i.e. without `Movement`).
> We extend `IteratingSystem` again. This time we wrote `@All({Position.class, Energy.class})`, which means that we are interested only in entities that have all listed components.
>
...
...
@@ -377,7 +376,6 @@ public class Reproduction extends IteratingSystem {
@@ -387,13 +385,13 @@ public class Reproduction extends IteratingSystem {
### Grassing
The grassing behaviour works on all entities that have the components `Position`, `Energy` but no `Heading`. Thus, it ignores grassers that are currently searching (and thus have a `Heading`).
The grassing behaviour works on all entities that have the components `Position`, `Energy` but no `Movement`. Thus, it ignores grassers that are currently searching (and thus have `Movement`).
If the grasser's energy is 1.0 or above, it does nothing. Otherwise, the grasser decides if there is enough grass in it's grid cell. If this is the case, the grasser consumes grass and converts it to energy. Otherwise, the grasser switches to the searching behaviour.
> The behaviour is switched by adding component `Heading`.
> The behaviour is switched by adding component `Movement`.
>
> 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`.
> We extend `IteratingSystem` again, and use `@All(...)` as before, but with an additional `@Exclude(...)`. This time, we want only entities that have no `Movement`, 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 `Movement`, which means that the respective entity will not be processed by this system in the next step, but by the `SearchBehaviour`.
@@ -447,11 +445,11 @@ public class GrassingBehaviour extends IteratingSystem {
### 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`).
The grassing behaviour system works on all entities that have the components `Position` and `Movement`. Thus, it ignores grassers that are currently grassing (and thus have no `Movement`).
The grasser decides if there is enough grass in it's grid cell. If this is the case, the grasser switches to the searching behaviour. Otherwise, it continues searching by a random walk. When reaching a world borders, the grasser is turned by 180°.
> The behaviour is switched by removing component `Heading`.
> The behaviour is switched by removing component `Movement`.