new changes
parent
289b635077
commit
e9602140e9
63
README.md
63
README.md
|
|
@ -80,48 +80,72 @@ Werden jetzt wie im vorherigen Beispiel die Lebenspunkte aller Wesen gebraucht,
|
||||||
|
|
||||||
Ein Entity-Component-System besteht aus vier Konzepten:
|
Ein Entity-Component-System besteht aus vier Konzepten:
|
||||||
|
|
||||||
### Entities
|
### Entity
|
||||||
|
|
||||||
Entities sind Spielobjekte, sie sind meist nicht mehr als eine fortlaufende ID.
|
Entities sind Spielobjekte, sie sind meist nicht mehr als eine fortlaufende ID.
|
||||||
|
|
||||||
### Components
|
### Component
|
||||||
|
|
||||||
Components sind die zum Spielobjekt gehörenden Daten. Wie viele Daten jede Art von Component enthält kann verschieden sein.
|
Components sind die zum Spielobjekt gehörenden Daten. Wie viele Daten jede Art von Component enthält kann verschieden sein.
|
||||||
Zum Beispiel kann ein `Lebenspunkte` Component nur die derzeitigen Lebenspunkte enthalten, während ein `Kampfkraft` Component Schaden, Geschwindigkeit und Rüstung enthält.
|
Zum Beispiel kann ein `Lebenspunkte` Component nur die derzeitigen Lebenspunkte enthalten, während ein `Kampfkraft` Component Schaden, Geschwindigkeit und Rüstung enthält.
|
||||||
|
|
||||||
### Registry
|
### Registry
|
||||||
|
|
||||||
Die Registry ist eine Datenbank, die alle Entities ihren Components zuweist und folgende Operationen Erlaubt:
|
Die Registry ist eine Datenbank, die alle Entities ihren Components zuweist und meist folgende Operationen erlaubt:
|
||||||
|
- addComponent(entity, component) -- Füge einen neuen Component in die verwaltung hinzu.
|
||||||
|
- removeComponent(entity, ComponentType) -- Lösche den Component diesen Types für die Entity.
|
||||||
|
- withComponents(ComponentTypes[]) -- erstelle eine Liste aller Entities, die alle angegebenen Component Typen besitzen.
|
||||||
|
|
||||||
|
### Sytem
|
||||||
|
|
||||||
|
Systems bilden die Anwendungslogik ab. Sie können die Registry nach Entities abfragen und neue Entities oder Components hinzufügen.
|
||||||
|
Ein System könnte zum Beispiel die Schadensberechnung für alle Einheiten durchführen und daraus Schadens-Entities erstellen und ein anderes System alle Schadens-Entities abfragen und Lebenspunkte abziehen.
|
||||||
|
|
||||||
|
|
||||||
|
## Aufgabe
|
||||||
|
|
||||||
|
Ihre Aufgabe ist es ein Entity-Component-System zu entwickeln.
|
||||||
|
Das ECS muss mindestens aus folgenden Klassen bestehen:
|
||||||
|
|
||||||
|
- class Entity -- Entities sollten unveränderbar und nach Wert vergleichbar sein.
|
||||||
|
- die folgenden beiden Konstruktoren müssen existieren:
|
||||||
|
- public Entity()
|
||||||
|
- protected Entity(int)
|
||||||
|
|
||||||
|
- interface Component -- Ein interface zur Markierung von Components.
|
||||||
|
- class Registry -- Die Registry soll alle Entities und Components verwalten. Sie soll folgende Operationen unterstuützen:
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────┐
|
||||||
│ │
|
│ │
|
||||||
│ registerComponentType(componentClass) │
|
│ registerComponentType(componentClass) │
|
||||||
│ └─ Registriert eine neue Art von Component zur Verwaltung │
|
│ └─ Registriert eine neue Art von Component zur Verwaltung.
|
||||||
|
| Es dürfen nur Klassen akzeptiert werden, die das Interface Component implementieren │
|
||||||
│ │
|
│ │
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
│ │
|
│ │
|
||||||
│ addComponent(entity, component) │
|
│ addComponent(entity, component) │
|
||||||
│ └─ Fügt der Entity einen neuen Component hinzu │
|
│ └─ Fügt der Entity einen neuen Component hinzu.
|
||||||
|
| Diese Methode akzeptiert alle Components, die das Interface Component implementieren.
|
||||||
|
| Besitzt die Entity bereits einen Component dieser Klasse, wird dieser durch die neue Instanz ersetzt. │
|
||||||
│ │
|
│ │
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
│ │
|
│ │
|
||||||
│ removeComponent(entity, componentType) │
|
│ removeComponent(entity, componentClass) │
|
||||||
│ └─ Löscht den angegebenen Component von der Entity │
|
│ └─ Löscht den Component der angegebenen Klasse von der Entity. │
|
||||||
│ │
|
│ │
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
│ │
|
│ │
|
||||||
│ hasComponent(entity, componentType) → boolean │
|
│ hasComponent(entity, componentClass) → boolean │
|
||||||
│ └─ Prüft, ob die Entity einen Component diesen Types hat │
|
│ └─ Prüft, ob die Entity einen Component dieser Klasse hat. │
|
||||||
│ │
|
│ │
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
│ │
|
│ │
|
||||||
│ getComponent(entity, componentType) → component │
|
│ getComponent(entity, componentClass) → component │
|
||||||
│ └─ Gibt den angegebenen Component für die Entity zurück │
|
│ └─ Gibt den Component der angegebenen Klasse für die Entity zurück. │
|
||||||
│ │
|
│ │
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
│ │
|
│ │
|
||||||
│ withComponents(componentType...) → entity[] │
|
│ withComponents(componentClass...) → entity[] │
|
||||||
│ └─ Gibt alle Entities zurück, die alle angegebenen Components haben │
|
│ └─ Gibt alle Entities zurück, die alle angegebenen Components haben. │
|
||||||
│ │
|
│ │
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
│ │
|
│ │
|
||||||
|
|
@ -131,6 +155,13 @@ Die Registry ist eine Datenbank, die alle Entities ihren Components zuweist und
|
||||||
└─────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
### Sytems
|
Tipp:
|
||||||
|
|
||||||
Systems bilden die Anwendungslogik ab. Sie können die Registry nach Entities abfragen und neue Entities oder Components hinzufügen
|
Sie können die Klasse eines Objektes mit der .class Eigenschaft ermitteln. Das damit erzeugte Class-Token kann wie jeder andere Wert in Datenstruckturen gespeichert werden.
|
||||||
|
|
||||||
|
```
|
||||||
|
class App {}
|
||||||
|
|
||||||
|
App app = new App();
|
||||||
|
Class<App> appClassToken = app.class;
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
public record BattleWin(
|
||||||
|
Entity winningSquad,
|
||||||
|
Entity loosingSquad,
|
||||||
|
boolean draw,
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -7,22 +7,34 @@ import com.example.ecs.Entity;
|
||||||
|
|
||||||
public class Squad implements Component {
|
public class Squad implements Component {
|
||||||
private String name;
|
private String name;
|
||||||
private List<Entity> units;
|
private List<Entity> activeUnits;
|
||||||
|
private List<Entity> deadUnits;
|
||||||
|
|
||||||
public Squad(String name, List<Entity> units) {
|
public Squad(String name, List<Entity> units) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.units = units;
|
this.units = units;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeUnit(Entity entity) {
|
public void killUnit(Entity entity) {
|
||||||
units.remove(entity);
|
if (activeUnits.contains(entity)) {
|
||||||
|
activeUnits.remove(entity);
|
||||||
|
deadUnits.add(unit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String name() {
|
public String name() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Entity> units() {
|
public List<Entity> activeUnits() {
|
||||||
return units;
|
return activeUnits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Entity> deadUnits() {
|
||||||
|
return deadUnits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return !activeUnits.empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.example.systems;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import com.example.components.Attack;
|
||||||
|
import com.example.components.Battle;
|
||||||
|
import com.example.components.Hero;
|
||||||
|
import com.example.components.Squad;
|
||||||
|
import com.example.components.Stats;
|
||||||
|
import com.example.ecs.Entity;
|
||||||
|
import com.example.ecs.Registry;
|
||||||
|
import com.example.ecs.System;
|
||||||
|
|
||||||
|
public class SquadUpdateSystem extends System {
|
||||||
|
|
||||||
|
public UnitKillerSystem(Registry registry) {
|
||||||
|
super(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
for (var battleEntity : registry.getWithComponents(Battle.class)) {
|
||||||
|
var battle = registry.getComponent(battleEntity, Battle.class);
|
||||||
|
|
||||||
|
var squad1 = registry.getComponent(battle.squad1(), Squad.class);
|
||||||
|
var squad2 = registry.getComponent(battle.squad2(), Squad.class);
|
||||||
|
|
||||||
|
Entity battleWinEntity = new Entity();
|
||||||
|
if (squad1.isActive() && squad2.isActive()) {
|
||||||
|
BattleWin battleWin(battle.squad1(), battle.squad2(), true);
|
||||||
|
registry.add(battleWinEntity, battleWin);
|
||||||
|
} else if (squad1.isActive) {
|
||||||
|
BattleWin battleWin(battle.squad2(), battle.squad1(), false);
|
||||||
|
registry.add(battleWinEntity, battleWin);
|
||||||
|
} else if (squad2.isActive()) {
|
||||||
|
BattleWin battleWin(battle.squad1(), battle.squad2(), false);
|
||||||
|
registry.add(battleWinEntity, battleWin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (squad1.isActive() || squad2.isActive()) {
|
||||||
|
registry.remove(battleEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.example.systems;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import com.example.components.Attack;
|
||||||
|
import com.example.components.Battle;
|
||||||
|
import com.example.components.Hero;
|
||||||
|
import com.example.components.Squad;
|
||||||
|
import com.example.components.Stats;
|
||||||
|
import com.example.ecs.Entity;
|
||||||
|
import com.example.ecs.Registry;
|
||||||
|
import com.example.ecs.System;
|
||||||
|
|
||||||
|
public class WinSystem extends System {
|
||||||
|
|
||||||
|
public WinSystem(Registry registry) {
|
||||||
|
super(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
for (var battleEntity : registry.getWithComponents(Battle.class)) {
|
||||||
|
var battle = registry.getComponent(battleEntity, Battle.class);
|
||||||
|
|
||||||
|
var squad1 = registry.getComponent(battle.squad1(), Squad.class);
|
||||||
|
var squad2 = registry.getComponent(battle.squad2(), Squad.class);
|
||||||
|
|
||||||
|
Entity battleWinEntity = new Entity();
|
||||||
|
if (squad1.isActive() && squad2.isActive()) {
|
||||||
|
BattleWin battleWin(battle.squad1(), battle.squad2(), true);
|
||||||
|
registry.add(battleWinEntity, battleWin);
|
||||||
|
} else if (squad1.isActive) {
|
||||||
|
BattleWin battleWin(battle.squad2(), battle.squad1(), false);
|
||||||
|
registry.add(battleWinEntity, battleWin);
|
||||||
|
} else if (squad2.isActive()) {
|
||||||
|
BattleWin battleWin(battle.squad1(), battle.squad2(), false);
|
||||||
|
registry.add(battleWinEntity, battleWin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (squad1.isActive() || squad2.isActive()) {
|
||||||
|
registry.remove(battleEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.example.ecs;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assert;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for simple App.
|
||||||
|
*/
|
||||||
|
public class EntityTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rigorous Test :-)
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void ShouldBeCreatable() {
|
||||||
|
Entity entity = new Entity();
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.example.ecs;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for simple App.
|
||||||
|
*/
|
||||||
|
public class RegistryTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rigorous Test :-)
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void shouldAnswerWithTrue() {
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue