Implemented component data per Austin Morlan's example

This commit is contained in:
Brychan Dempsey 2021-04-01 16:02:17 +13:00
parent 1e9fc8d180
commit 44412dae46

View File

@ -32,7 +32,71 @@ public class ECS {
// Unfortunately, given Java's constraints on dynamic typing (run-time type determination), the returned data must be // Unfortunately, given Java's constraints on dynamic typing (run-time type determination), the returned data must be
// explicitly cast. Therefore, all components must implement the IComponent interface - which mandates the getType() // explicitly cast. Therefore, all components must implement the IComponent interface - which mandates the getType()
// function // function
List<List<Object>> componentDataArrays = new ArrayList<>();
// As discussed by Austin Morlan, this array must be packed, otherwise we waste time iterating over non-subscribed entities
// This also means we cannot use the location implicitly - we must keep track of exactly which data instance associates with
// which entity.
// Therefore, we need a custom data structure that keeps reversable references to component instances and entities:
interface IComponentArray{
void entityDestroyed(int entity);
}
class ComponentArray<E> implements IComponentArray{
List<E> componentArray = new ArrayList<>();
Map<Integer, Integer> entityComponentDataMap = new HashMap<>();
Map<Integer, Integer> componentDataEntityMap = new HashMap<>();
public void entityDestroyed(int entity){
Optional<Integer> pos = entityComponentDataMap.get(entity);
if (pos.isEmpty()){
removeData(entity);
}
}
void removeData(int entity){
if (!entityComponentDataMap.containsKey(entity)){
System.err.println("Attempted to remove non-existent entity");
return;
}
// 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
int 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);
}
void insertData(int entity, E component){
Optional<Integer> pos = entityComponentDataMap.get(entity);
if (!pos.isEmpty()){
System.err.println("Entity is already subscribed to the component");
return;
}
int index = componentArray.size();
entityComponentDataMap.put(entity, index);
componentDataEntityMap.put(index, entity);
componentArray.add(component);
}
E getData(int entity){
if (!entityComponentDataMap.containsKey(entity)){
System.err.println("Attempted to retrieve non-existent data");
return null;
}
return componentArray.get(entityComponentDataMap.get(entity));
}
}
// The actual list of data arrays
List<IComponentArray> componentDataArrays = new ArrayList<>();
// Components are either primitive types or class/struct definitions, with an additional list associating // Components are either primitive types or class/struct definitions, with an additional list associating
// the entities the component is assigned to // the entities the component is assigned to