Compare commits
8
Commits
051836852c
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
244bb38e43 | ||
|
|
4731981977 | ||
|
|
fc480cfe2e | ||
|
|
2c96e92a6a | ||
|
|
ccabef5226 | ||
|
|
6d8574b951 | ||
|
|
e578e72b46 | ||
|
|
84d71c0df7 |
@@ -1,4 +1,28 @@
|
||||
# JavaECS
|
||||
An implementation of an Entity-Component-System in Java. Based on the C++ implementation by [Austin Morlan](https://code.austinmorlan.com/austin/ecs).
|
||||
An implementation of an Entity-Component-System written in Java.
|
||||
|
||||
See the [documentation](https://git.software.kauripeak.co.nz/BrychanD/JavaECS-Docs/wiki) for implmentation details
|
||||
## Introduction to ECS
|
||||
The primary goal of an ECS is to provide fast access to many entities; especially where those entities share many of the same properties. It also solves issues regarding adaptability in an inheritance-based engine.
|
||||
ECS is more of a conceptual idea rather than an actual engine structure. There exists many variations of the concept, each adding in different features and models as required.
|
||||
|
||||
The primary example of an ECS is [EnTT](https://github.com/skypjack/entt), which is used in Mojang's Minecraft.
|
||||
|
||||
There are four key elements to an ECS:
|
||||
1. The **entity**, which is a simple ID, usually an index.
|
||||
2. The **component**, which is a struct or class that stores data
|
||||
3. The **system**, which is a functionality that is executed regularly by the engine.
|
||||
4. The **engine** (*sometimes split into parts called 'managers'*), which controls the interaction between these components, and provides access to the external program.
|
||||
|
||||
## About JavaECS
|
||||
The focus of JavaECS is more about the structure rather than raw performance. It remains performant, but there may be multiple areas where improvements can be made.
|
||||
|
||||
In a quick port of Alex Beimler's [ECS Benchmark](https://github.com/abeimler/ecs_benchmark), JavaECS performs at about the same speed as [ECS](https://github.com/redxdev/ECS) (~90 ms). The results aren't normalised between test environments, so take them with a grain of salt; but it tends to suggest that the project has decent performance.
|
||||
|
||||
This project is inspired by:
|
||||
* [C++ implementation](https://austinmorlan.com/posts/entity_component_system/) by Austin Morlan.
|
||||
* [Nomad Game Engine](https://medium.com/@savas/nomad-game-engine-part-2-ecs-9132829188e5) by Niko Savas
|
||||
* [EntityX](https://github.com/alecthomas/entityx) by Alec Thomas.
|
||||
|
||||
|
||||
## Implementation
|
||||
See the [documentation](https://git.software.kauripeak.co.nz/BrychanD/JavaECS-Docs/wiki) for implementation details
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nz.ac.massey.javaecs</groupId>
|
||||
<artifactId>javaecs</artifactId>
|
||||
<version>0.9.9-RELEASE_CANDIDATE</version>
|
||||
<version>1.0.1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
package nz.ac.massey.javaecs;
|
||||
/**
|
||||
* Component Array
|
||||
* Defines the data structure that component data is stored under.
|
||||
* Has a list of defined objects, and two associative maps that link
|
||||
* the position of the data with the entity number.
|
||||
*
|
||||
* Therefore, every entity in entityComponentDataMap is valid, so
|
||||
* no additional sorting is required
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Brychan Dempsey - brychand@hotmail.com
|
||||
*
|
||||
*/
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Stores component data in a packed interal list, and provides methods for accessing this data
|
||||
*/
|
||||
class ComponentArray{
|
||||
// The object data array
|
||||
private List<Object> componentArray;
|
||||
// The mappings between data and entity
|
||||
private Map<Entity, Integer> entityComponentDataMap;
|
||||
private Map<Integer, Entity> componentDataEntityMap;
|
||||
|
||||
public ComponentArray(int initialSize){
|
||||
componentArray = new ArrayList<>(initialSize);
|
||||
entityComponentDataMap = new HashMap<>(initialSize);
|
||||
componentDataEntityMap = new HashMap<>(initialSize);
|
||||
}
|
||||
/**
|
||||
* Gets the data Object associated with the entity.
|
||||
* @param entity the entity to find data for
|
||||
* @return the Object if the data exists, else null
|
||||
*/
|
||||
protected Object getData(Entity entity){
|
||||
try{
|
||||
return componentArray.get(entityComponentDataMap.get(entity));
|
||||
}
|
||||
catch (NullPointerException ex){
|
||||
Engine.writeErr("Attempted to retrieve non-existent data for unassigned entity: " + entity.getValue());
|
||||
return null;
|
||||
}
|
||||
catch (IndexOutOfBoundsException e){
|
||||
Engine.writeErr("Index out-of-bounds for entity: " + entity.getValue());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the provided component and associates it with the entity.
|
||||
* @param entity the entity to associate data to
|
||||
* @param component the component data
|
||||
* @return true if successful, false if the entity is already subscribed to the component
|
||||
*/
|
||||
protected boolean insertData(Entity entity, Object component){
|
||||
if (entityComponentDataMap.containsKey(entity)){
|
||||
Engine.writeErr("Entity is already subscribed to the component");
|
||||
return false;
|
||||
}
|
||||
// Put data at the end of the componentArray
|
||||
int index = componentArray.size();
|
||||
entityComponentDataMap.put(entity, index);
|
||||
componentDataEntityMap.put(index, entity);
|
||||
componentArray.add(component);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves component data to another entity. (Copies, deletes and inserts data)
|
||||
* @param sourceEntity
|
||||
* @param destinationEntity
|
||||
* @return 0 if successful, -1 if the object is null, -2 if a NullPointerException occurred, and -3 if inserting data failed
|
||||
*/
|
||||
protected int moveData(Entity sourceEntity, Entity destinationEntity){
|
||||
try{
|
||||
Object data = entityComponentDataMap.get(sourceEntity);
|
||||
if (data == null) return -1;
|
||||
else if (insertData(destinationEntity, data))
|
||||
{
|
||||
removeData(sourceEntity);
|
||||
return 0;
|
||||
}
|
||||
else return -3;
|
||||
}
|
||||
catch (NullPointerException e){
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the data associated with the entity.
|
||||
* @param entity the entity to remove the data from
|
||||
* @return true if the data was removed. If the data isn't found then returns false
|
||||
*/
|
||||
protected boolean removeData(Entity entity){
|
||||
if (!entityComponentDataMap.containsKey(entity)){
|
||||
Engine.writeErr("Attempted to remove non-existent entity: " + entity.getValue());
|
||||
return false;
|
||||
}
|
||||
// Get the componentData index of the entity
|
||||
int removedComponentDataIndex = entityComponentDataMap.get(entity);
|
||||
// Replace the removed component with the last component in the array
|
||||
componentArray.set(removedComponentDataIndex, componentArray.get(componentArray.size() -1));
|
||||
// update the data positions in the map
|
||||
Entity lastEntity = componentDataEntityMap.get(componentArray.size()-1);
|
||||
entityComponentDataMap.replace(lastEntity, removedComponentDataIndex);
|
||||
componentDataEntityMap.replace(removedComponentDataIndex, lastEntity);
|
||||
// Finally, remomve the last elements
|
||||
entityComponentDataMap.remove(entity);
|
||||
componentDataEntityMap.remove(componentArray.size() -1);
|
||||
componentArray.remove(componentArray.size() -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -16,21 +16,23 @@ import java.util.HashMap;
|
||||
/**
|
||||
* Manages the addition, sorting and retrieving of components and component data
|
||||
*/
|
||||
class ComponentManager{
|
||||
private Map<Type, ComponentArray> componentArrays = new HashMap<>();
|
||||
private Map<Type, Integer> componentPosIndex = new HashMap<>();
|
||||
private Map<Integer, Type> indexComponentType = new HashMap<>();
|
||||
public class ComponentManager{
|
||||
public Map<Type, Map<Entity, Object>> componentArrays = new HashMap<>();
|
||||
// Need to be able to map bit indices and component types
|
||||
public Map<Integer, Type> indexComponentType = new HashMap<>();
|
||||
public Map<Type, Integer> componentTypeIndex = new HashMap<>();
|
||||
//
|
||||
|
||||
/**
|
||||
* Adds the specified component to the provided entity.
|
||||
* <p>
|
||||
* Providing a null Object defaults the value to boolean false
|
||||
* Does not ensure synchronisation with the other managers; ensure this is done!
|
||||
* @param componentType the class type of the component to add
|
||||
* @param componentData the component data to associate
|
||||
* @param entity the entity to associate data to
|
||||
*/
|
||||
protected boolean addComponentToEntity(Type componentType, Object componentData, Entity entity){
|
||||
return componentArrays.get(componentType).insertData(entity, componentData);
|
||||
public boolean addComponentToEntity(Type componentType, Object componentData, Entity entity){
|
||||
componentArrays.get(componentType).put(entity, componentData);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,9 +43,7 @@ class ComponentManager{
|
||||
// HashMap lookups take time, use the known bitstates to avoid
|
||||
int index = entityRegistrations.nextSetBit(0);
|
||||
while(index != -1){
|
||||
if (!componentArrays.get(indexComponentType.get(index)).removeData(entity)){
|
||||
Engine.writeErr(indexComponentType.get(index).getTypeName());
|
||||
}
|
||||
componentArrays.get(indexComponentType.get(index)).remove(entity);
|
||||
index = entityRegistrations.nextSetBit(index+1);
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ class ComponentManager{
|
||||
* @return the Object data found, or null if it was not found
|
||||
*/
|
||||
public Object getComponent(Type componentType, Entity entity){
|
||||
return componentArrays.get(componentType).getData(entity);
|
||||
return componentArrays.get(componentType).get(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ class ComponentManager{
|
||||
*/
|
||||
public Integer getComponentIndex(Type type){
|
||||
try{
|
||||
return componentPosIndex.get(type);
|
||||
return componentTypeIndex.get(type);
|
||||
}
|
||||
catch (NullPointerException e){
|
||||
return -1;
|
||||
@@ -94,11 +94,11 @@ class ComponentManager{
|
||||
* @return true if the component was moved successfully, else false
|
||||
*/
|
||||
public boolean moveComponentData(Entity sourceEntity, Entity destinationEntity, Type component){
|
||||
if (componentArrays.get(component).moveData(sourceEntity, destinationEntity) == 0){
|
||||
Object data = componentArrays.get(component).get(sourceEntity);
|
||||
componentArrays.get(component).put(destinationEntity, data);
|
||||
componentArrays.get(component).remove(sourceEntity);
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves all component data from one entity to another
|
||||
@@ -109,8 +109,7 @@ class ComponentManager{
|
||||
public void moveAllComponentData(Entity sourceEntity, Entity destinationEntity, BitSet sourceRegistrations){
|
||||
int result = sourceRegistrations.nextSetBit(0);
|
||||
while (result != -1){
|
||||
Type key = indexComponentType.get(result);
|
||||
componentArrays.get(key).moveData(sourceEntity, destinationEntity);
|
||||
moveComponentData(sourceEntity, destinationEntity, indexComponentType.get(result));
|
||||
result = sourceRegistrations.nextSetBit(result +1);
|
||||
}
|
||||
}
|
||||
@@ -135,9 +134,9 @@ class ComponentManager{
|
||||
Engine.writeErr("Component " + type.getTypeName() + " is already registered");
|
||||
return false;
|
||||
}
|
||||
componentArrays.put(type, new ComponentArray(arraySize));
|
||||
indexComponentType.put(componentPosIndex.size(), type);
|
||||
componentPosIndex.put(type, componentPosIndex.size());
|
||||
componentArrays.put(type, new HashMap<>());
|
||||
indexComponentType.put(componentTypeIndex.size(), type);
|
||||
componentTypeIndex.put(type, componentTypeIndex.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -149,6 +148,18 @@ class ComponentManager{
|
||||
* @param entity the entity to remove the component from
|
||||
*/
|
||||
public boolean removeComponentFromEntity(Type componentType, Entity entity){
|
||||
return componentArrays.get(componentType).removeData(entity);
|
||||
componentArrays.get(componentType).remove(entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity contains data for the provided component
|
||||
* @param entity the entity to check
|
||||
* @param componentType the component class type
|
||||
* @return true if the entity has component data
|
||||
*/
|
||||
public boolean entityHasComponentData(Entity entity, Type componentType){
|
||||
if (componentArrays.get(componentType).containsKey(entity)) return true;
|
||||
else return false;
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,25 @@ import java.util.Set;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* Abstract class that all systems should inherit from<p>
|
||||
* Defines four required components:
|
||||
* <ol>
|
||||
* <li>The list of <b>entities</b> that have all the components required for this system</li>
|
||||
* <li>The <b>BitSet</b> of component registrations required for this system</li>
|
||||
* <li>The <b>init()</b> function, where logic that needs to be run once is performed</li>
|
||||
* <li>The <b>update(dt)</b> function, where logic that needs to be run regularly is performed. <i>dt is the delta time in millseconds</i></li>
|
||||
* </ol>
|
||||
* Additionally, the object constructor should define the actual values of the BitSet.<p>
|
||||
* Additional functions can be implemented as required.
|
||||
*/
|
||||
public abstract class ECSSystem{
|
||||
protected Set<Entity> entities = new HashSet<>();
|
||||
protected BitSet registrationSet;
|
||||
public Set<Entity> entities = new HashSet<>();
|
||||
public BitSet registrationSet;
|
||||
|
||||
public ECSSystem(){
|
||||
registrationSet = new BitSet();
|
||||
}
|
||||
|
||||
public BitSet getRegistrationSet(){
|
||||
return registrationSet;
|
||||
@@ -26,14 +42,19 @@ public abstract class ECSSystem{
|
||||
|
||||
/**
|
||||
* Functionality that should be run only once.
|
||||
* Implement additional parameterised init() functions as required.
|
||||
* Implement additional parameterised <b>init()</b> functions as required.
|
||||
* <p>
|
||||
* This is distinct from the constructor as this may be run as required any time between
|
||||
* the construction and <b>update(dt)</b>. It is not intended to set the actual bits of <b>registrationSet</b>
|
||||
* in this function; that should be performed in the constructor.
|
||||
* @throws Exception can return exceptions to the main program if an issue occurred.
|
||||
*/
|
||||
public abstract void init();
|
||||
public abstract void init() throws Exception;
|
||||
|
||||
/**
|
||||
* Functionality that is expected to be called regularly
|
||||
* Intended as a template only; may be superficially implemented.
|
||||
* Implement additional parameterised update() functions as required.
|
||||
* Implement additional parameterised <b>update()</b> functions as required.
|
||||
* @param dt delta-time; the change in time in milliseconds since this function was last run
|
||||
*/
|
||||
public abstract void update(double dt);
|
||||
|
||||
@@ -116,6 +116,16 @@ public class Engine {
|
||||
return entityManager.getNumEntities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity is subscribed to the provided type
|
||||
* @param entity the entity to search
|
||||
* @param componentType the class type of the component to search
|
||||
* @return true if the entity is subscribed
|
||||
*/
|
||||
public boolean entityHasComponent(Entity entity, Type componentType){
|
||||
return entityManager.getRegistrations(entity).get(componentManager.getComponentIndex(componentType));
|
||||
}
|
||||
|
||||
/***************************************
|
||||
** Manage Components **
|
||||
***************************************/
|
||||
@@ -141,7 +151,6 @@ public class Engine {
|
||||
int componentIndex = componentManager.getComponentIndex(componentType);
|
||||
if (entityManager.registerComponent(componentIndex, entity))
|
||||
{
|
||||
//systemManager.entityRegistrationAdded(entity, componentIndex);
|
||||
systemManager.entityRegistrationsChanged(entity, entityManager.getRegistrations(entity));
|
||||
componentManager.addComponentToEntity(componentType, component, entity);
|
||||
return true;
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.lang.reflect.Type;
|
||||
/**
|
||||
* Entity class.
|
||||
* Whilst an entity is just an Integer, and using Integer values
|
||||
* would be more performant (no function call, primitive arrays & etc.), it is encapsulated to help
|
||||
* would be more performant (no function call, primitive arrays and etc.), it is encapsulated to help
|
||||
* distinguish between entities and Integers. Also, in this form it may be extended to also include things
|
||||
* like names, grouping, specific ordering etc
|
||||
*/
|
||||
@@ -56,12 +56,11 @@ public class Entity {
|
||||
/**
|
||||
* Adds the provided component to this entity.
|
||||
* <p>
|
||||
* <b>This function calls addComponent() in the engine,</b> so
|
||||
* <b>This function calls <i>Engine.addComponent(Entity, Type, Object)</i></b>, so
|
||||
* that should be used instead.
|
||||
* @deprecated This function is not ECS-like.
|
||||
* It is provided as an auxilliary method, that will be more
|
||||
* intuitive to those familiar with OO design
|
||||
* @see Engine.addComponent() - which this function makes a call to
|
||||
* @param componentType the class type of the component to add
|
||||
* @param componentData the component data
|
||||
* @return true if successful
|
||||
@@ -74,12 +73,11 @@ public class Entity {
|
||||
/**
|
||||
* Removes the provided component from this entity.
|
||||
* <p>
|
||||
* <b>This function calls removeComponent() in the engine,</b> so
|
||||
* <b>This function calls <i>Engine.removeComponent(Entity, Type)</i></b>, so
|
||||
* that should be used instead.
|
||||
* @deprecated This function is not ECS-like.
|
||||
* It is provided as an auxilliary method, that will be more
|
||||
* intuitive to those familiar with OO design
|
||||
* @see Engine.removeComponent() - which this function makes a call to
|
||||
* @param componentType the class type of the component to remove
|
||||
* @return true if successful
|
||||
*/
|
||||
@@ -91,12 +89,11 @@ public class Entity {
|
||||
/**
|
||||
* Gets the component data associated to this entity.
|
||||
* <p>
|
||||
* <b>This function calls getComponentData() in the engine,</b> so
|
||||
* <b>This function calls <i>Engine.getComponentData()</i></b>, so
|
||||
* that should be used instead.
|
||||
* @deprecated This function is not ECS-like.
|
||||
* It is provided as an auxilliary method, that will be more
|
||||
* intuitive to those familiar with OO design
|
||||
* @see Engine.getComponentData() - which this function makes a call to
|
||||
* @param componentType the class type of the component to fetch data from
|
||||
* @return the data Object, which requires casting
|
||||
*/
|
||||
|
||||
@@ -19,15 +19,17 @@ import java.util.ArrayList;
|
||||
* Manages data from the perspective of the entity.
|
||||
* <p>
|
||||
* I.e. Controls adding and removing entities, and registration and deregistration of components.
|
||||
* <p>
|
||||
* Do not update values in this class unless you have reviewed the JavaECS source!
|
||||
*/
|
||||
class EntityManager{
|
||||
public class EntityManager{
|
||||
// According to https://stackoverflow.com/questions/12524826/why-should-i-use-deque-over-stack
|
||||
// ArrayDeque is likely faster than a LinkedList, when used in place of one.
|
||||
// We can also supply a size to the constructor of ArrayDeque, which avoids resizing the collection
|
||||
// at initialisation time (took 1.4s vs 1.8s for 1M)
|
||||
private Deque<Entity> unusedEntities;
|
||||
private List<BitSet> entityRegistrations;
|
||||
private int maxSize = 1024;
|
||||
public Deque<Entity> unusedEntities;
|
||||
public List<BitSet> entityRegistrations;
|
||||
public int maxSize = 1024;
|
||||
|
||||
/**
|
||||
* Initialise the EntityManager with the default max size of 1024
|
||||
@@ -63,7 +65,7 @@ class EntityManager{
|
||||
* @return the index of the new entity
|
||||
* @throws NoSuchElementException an exception if there are no more unused entities
|
||||
*/
|
||||
protected Entity addEntity() throws NoSuchElementException{
|
||||
public Entity addEntity() throws NoSuchElementException{
|
||||
Entity result = unusedEntities.remove();
|
||||
entityRegistrations.set(result.getValue(), new BitSet());
|
||||
return result;
|
||||
@@ -105,7 +107,7 @@ class EntityManager{
|
||||
* @param entity the entity to register
|
||||
* @return true if the operation was successful
|
||||
*/
|
||||
protected boolean registerComponent(int component, Entity entity){
|
||||
public boolean registerComponent(int component, Entity entity){
|
||||
if (entity.getValue() >= maxSize){
|
||||
Engine.writeErr("Attempted to assign a component to non-existent entity: " + entity.getValue());
|
||||
return false;
|
||||
@@ -124,32 +126,36 @@ class EntityManager{
|
||||
/**
|
||||
* Adds the entity index back into unusedEntities, and sets the registrations to null
|
||||
* <p>
|
||||
* <b>Does not handle associated data</b> Use the method in ECS to remove entities cleanly
|
||||
* <b>Does not handle associated data</b> Use the method in ECS to remove entities cleanly,
|
||||
* or otherwise ensure the component data and systems are updated!
|
||||
* @param entity the entity to remove
|
||||
*/
|
||||
protected void removeEntity(Entity entity){
|
||||
public void removeEntity(Entity entity){
|
||||
unusedEntities.add(entity);
|
||||
entityRegistrations.set(entity.getValue(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entity's registrations to the provided BitSet
|
||||
* Sets the entity's registrations to the provided BitSet.
|
||||
* <p>
|
||||
* Does <b>not</b> ensure the systems registrations are updated.
|
||||
* @param entity the entity to set
|
||||
* @param registrations the preset registrations
|
||||
*/
|
||||
protected void setRegistrations(Entity entity, BitSet registrations){
|
||||
public void setRegistrations(Entity entity, BitSet registrations){
|
||||
entityRegistrations.set(entity.getValue(), registrations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the specified component from the entity
|
||||
* <p>
|
||||
* <b>Does not handle component data</b> Use the method in ECS to remove components cleanly
|
||||
* <b>Does not handle component data</b> Use the method in ECS to remove components cleanly,
|
||||
* or otherwise ensure the component data and systems are updated!
|
||||
* @param component the component index to remove
|
||||
* @param entity the entity to remove
|
||||
* @return true if successful
|
||||
*/
|
||||
protected boolean unregisterComponent(int component, Entity entity){
|
||||
public boolean unregisterComponent(int component, Entity entity){
|
||||
try{
|
||||
entityRegistrations.get(entity.getValue()).clear(component);
|
||||
return true;
|
||||
|
||||
@@ -17,16 +17,18 @@ import java.util.HashMap;
|
||||
/**
|
||||
* Manages system-focused aspects, such as ensuring a system has the correct list of current entities.
|
||||
* Manages registration of new systems
|
||||
* <p>
|
||||
* Do not update data in this class unless you have reviewed the JavaECS source.
|
||||
*/
|
||||
class SystemManager{
|
||||
private Map<Type, ECSSystem> systems = new HashMap<>();
|
||||
public class SystemManager{
|
||||
public Map<Type, ECSSystem> systems = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Signals the SystemManager that an entity was destroyed.
|
||||
* Removes the entity from each system's tracked entities
|
||||
* @param entity the destroyed entity
|
||||
*/
|
||||
protected void entityDestroyed(Entity entity){
|
||||
public void entityDestroyed(Entity entity){
|
||||
// Unlike components, this isn't simply indexed.
|
||||
for (Type key : systems.keySet()) {
|
||||
systems.get(key).entities.remove(entity);
|
||||
|
||||
Reference in New Issue
Block a user