Fixed javadocs, cleaned many lines
Prepped for release at v0.9.9 Breaking changes for all implementations
This commit is contained in:
parent
999ffa41dd
commit
051836852c
@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nz.ac.massey.javaecs</groupId>
|
||||
<artifactId>javaecs</artifactId>
|
||||
<version>0.9.2-PRERELEASE</version>
|
||||
<version>0.9.9-RELEASE_CANDIDATE</version>
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
|
@ -19,7 +19,9 @@ 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;
|
||||
|
@ -13,6 +13,9 @@ import java.lang.reflect.Type;
|
||||
import java.util.BitSet;
|
||||
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<>();
|
||||
@ -27,9 +30,6 @@ class ComponentManager{
|
||||
* @param entity the entity to associate data to
|
||||
*/
|
||||
protected boolean addComponentToEntity(Type componentType, Object componentData, Entity entity){
|
||||
/*if (componentData == null){
|
||||
return componentArrays.get(componentType).insertData(entity, false);
|
||||
} */
|
||||
return componentArrays.get(componentType).insertData(entity, componentData);
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ class ComponentManager{
|
||||
* @param component the component class type to consider
|
||||
* @return true if the component was moved successfully, else false
|
||||
*/
|
||||
protected boolean moveComponentData(Entity sourceEntity, Entity destinationEntity, Type component){
|
||||
public boolean moveComponentData(Entity sourceEntity, Entity destinationEntity, Type component){
|
||||
if (componentArrays.get(component).moveData(sourceEntity, destinationEntity) == 0){
|
||||
return true;
|
||||
}
|
||||
@ -106,7 +106,7 @@ class ComponentManager{
|
||||
* @param destinationEntity the entity to move data to
|
||||
* @param sourceRegistrations the component registrations of the source entity
|
||||
*/
|
||||
protected void moveAllComponentData(Entity sourceEntity, Entity destinationEntity, BitSet sourceRegistrations){
|
||||
public void moveAllComponentData(Entity sourceEntity, Entity destinationEntity, BitSet sourceRegistrations){
|
||||
int result = sourceRegistrations.nextSetBit(0);
|
||||
while (result != -1){
|
||||
Type key = indexComponentType.get(result);
|
||||
@ -120,7 +120,7 @@ class ComponentManager{
|
||||
* @param type the class type to register
|
||||
* @return true if the component was registered successfully, else false
|
||||
*/
|
||||
protected boolean registerComponent(Type type){
|
||||
public boolean registerComponent(Type type){
|
||||
return registerComponent(type, 16);
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ class ComponentManager{
|
||||
* @param arraySize the number of elements to prereserve space for.
|
||||
* @return true if the component was registered successfully, else false
|
||||
*/
|
||||
protected boolean registerComponent(Type type, int arraySize){
|
||||
public boolean registerComponent(Type type, int arraySize){
|
||||
if (componentArrays.containsKey(type)){
|
||||
Engine.writeErr("Component " + type.getTypeName() + " is already registered");
|
||||
return false;
|
||||
|
@ -20,17 +20,21 @@ public abstract class ECSSystem{
|
||||
protected Set<Entity> entities = new HashSet<>();
|
||||
protected BitSet registrationSet;
|
||||
|
||||
public BitSet getRegistrationSet;
|
||||
public BitSet getRegistrationSet(){
|
||||
return registrationSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Functionality that should be run only once.
|
||||
* Implement additional parameterised init() functions as required.
|
||||
* These should run once, when the system is first initialised.
|
||||
*/
|
||||
public abstract void init();
|
||||
|
||||
/**
|
||||
* Functionality that is expected to be called regularly
|
||||
* Intended as a template only; may be superficially implemented.
|
||||
* Implement additional parameterised update() functions as required.
|
||||
* These should be run each game loop or otherwise sensible regular interval
|
||||
* @param dt delta-time; the change in time in milliseconds since this function was last run
|
||||
*/
|
||||
public abstract void update();
|
||||
public abstract void update(double dt);
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
package nz.ac.massey.javaecs;
|
||||
/**
|
||||
* ECS manager class.
|
||||
* ECS engine class.
|
||||
* Call this class and its functions to interact correctly with the ECS system.
|
||||
* This is the entry-point to the library
|
||||
*
|
||||
* Contributors:
|
||||
* Brychan Dempsey - brychand@hotmail.com
|
||||
@ -18,7 +19,8 @@ import java.util.BitSet;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* The ECS manager.
|
||||
* The ECS management engine. Supplemented by the EntityManager, ComponentManager, and System Manager
|
||||
* These four classes provide the actual functionality of the ecs
|
||||
* <p>
|
||||
* See https://git.software.kauripeak.co.nz/BrychanD/JavaECS
|
||||
* for documentation and more information.
|
||||
@ -39,6 +41,9 @@ public class Engine {
|
||||
entityManager = new EntityManager();
|
||||
componentManager = new ComponentManager();
|
||||
systemManager = new SystemManager();
|
||||
// In a non-ECS type manner (instead OO-like), provide an additional method to
|
||||
// add components to an entity: entity.addComponent().
|
||||
Entity.engineRef = this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,6 +54,7 @@ public class Engine {
|
||||
entityManager = new EntityManager(maxEntities);
|
||||
componentManager = new ComponentManager();
|
||||
systemManager = new SystemManager();
|
||||
Entity.engineRef = this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -156,7 +162,7 @@ public class Engine {
|
||||
if (entityManager.unregisterComponent(componentManager.getComponentIndex(componentType), entity))
|
||||
{
|
||||
componentManager.removeComponentFromEntity(componentType, entity);
|
||||
systemManager.entityRegistrationsChanged(entity, entityManager.getRegistrations(entity)); // entityRegistrationRemoved(entity, componentManager.getComponentIndex(componentType));
|
||||
systemManager.entityRegistrationsChanged(entity, entityManager.getRegistrations(entity));
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
@ -191,6 +197,7 @@ public class Engine {
|
||||
* Registers the system to the SystemManager
|
||||
* @param systemType the type of the system
|
||||
* @param instance the instance of the system
|
||||
* @return true if successful
|
||||
*/
|
||||
public boolean registerSystem(Type systemType, ECSSystem instance){
|
||||
return systemManager.registerSystem(systemType, instance);
|
||||
@ -202,7 +209,7 @@ public class Engine {
|
||||
* @param signature the new signature data
|
||||
*/
|
||||
public void setSystemSignature(Type system, BitSet signature){
|
||||
systemManager.setRegistrationSignature(system, signature);
|
||||
systemManager.setSystemRegistraions(system, signature);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,11 +1,17 @@
|
||||
package nz.ac.massey.javaecs;
|
||||
|
||||
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), it is encapsulated to help
|
||||
* distinguish between entities and Integers.
|
||||
* would be more performant (no function call, primitive arrays & 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
|
||||
*/
|
||||
public class Entity {
|
||||
protected static Engine engineRef;
|
||||
|
||||
private int value;
|
||||
|
||||
public Entity(int value){
|
||||
@ -20,11 +26,11 @@ public class Entity {
|
||||
* Returns the int value wrapped as an entity.
|
||||
* Used to provide a distinction between creating a new entity, and
|
||||
* using an int value we assume is a valid entity.
|
||||
*
|
||||
* <p>
|
||||
* Functionally, this is no different to creating a new entity.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
* @param value the integer value to read as an Entity
|
||||
* @return an Entity object representing the ID value
|
||||
*/
|
||||
public static Entity asEntity(int value){
|
||||
return new Entity(value);
|
||||
@ -44,6 +50,58 @@ public class Entity {
|
||||
|
||||
@Override
|
||||
public int hashCode(){
|
||||
return value;
|
||||
return value; // each entity is an id; the value is implicitly unique, so use it as the hash code
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the provided component to this entity.
|
||||
* <p>
|
||||
* <b>This function calls addComponent() in the engine,</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
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean addComponent(Type componentType, Object componentData){
|
||||
return engineRef.addComponent(this, componentType, componentData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the provided component from this entity.
|
||||
* <p>
|
||||
* <b>This function calls removeComponent() in the engine,</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
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean removeComponent(Type componentType){
|
||||
return engineRef.removeComponent(this, componentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the component data associated to this entity.
|
||||
* <p>
|
||||
* <b>This function calls getComponentData() in the engine,</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
|
||||
*/
|
||||
@Deprecated
|
||||
public Object getComponent(Type componentType){
|
||||
return engineRef.getComponentData(this, componentType);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import java.util.NoSuchElementException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
|
||||
// Define the manager classes internally - should be moved to seperate source files as appropriate
|
||||
/**
|
||||
* Manages data from the perspective of the entity.
|
||||
* <p>
|
||||
@ -23,7 +22,7 @@ import java.util.ArrayList;
|
||||
*/
|
||||
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 as one.
|
||||
// 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;
|
||||
@ -39,7 +38,8 @@ class EntityManager{
|
||||
|
||||
for (int i = 0; i < maxSize; i++) {
|
||||
unusedEntities.add(new Entity(i));
|
||||
entityRegistrations.add(null); // Leave bitsets out as if they are null the entity isn't initialised properly
|
||||
entityRegistrations.add(null); // Annul the entries, to set list size, but keep the unused
|
||||
// entities in an invalid state
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ class EntityManager{
|
||||
* Gets the current maximum size
|
||||
* @return the value of currentSize
|
||||
*/
|
||||
protected Integer getMaxSize(){
|
||||
public Integer getMaxSize(){
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ class EntityManager{
|
||||
* @param entity the entity whose BitSet to retrieve
|
||||
* @return the BitSet of the provided entity, or a new, empty BitSet if the result was null or out of bounds
|
||||
*/
|
||||
protected BitSet getRegistrations(Entity entity){
|
||||
public BitSet getRegistrations(Entity entity){
|
||||
try{
|
||||
BitSet registrations = entityRegistrations.get(entity.getValue());
|
||||
if (registrations != null){
|
||||
@ -171,7 +171,7 @@ class EntityManager{
|
||||
* @param componentManager reference to the insanced ComponentManager
|
||||
* @return true if the operation succeeded, otherwise false
|
||||
*/
|
||||
protected boolean resize(int newSize, SystemManager systemManager, ComponentManager componentManager){
|
||||
public boolean resize(int newSize, SystemManager systemManager, ComponentManager componentManager){
|
||||
if (newSize < maxSize - unusedEntities.size()){
|
||||
Engine.writeErr("Attempted to resize the maximum entity count to a number smaller than the current assigned entity count.");
|
||||
return false;
|
||||
@ -181,9 +181,12 @@ class EntityManager{
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
// Consistency should be maintained.
|
||||
// This is computationally expensive; we must re-order every assigned entity above newSize, if the newSize is smaller
|
||||
// Every element above the index must be reordered
|
||||
if (newSize < maxSize){
|
||||
// Loop through every entity value above our desired index
|
||||
// and attempt to remove it from the unused entity queue
|
||||
// If that fails, the entity is in use, and must have its
|
||||
// data copied to a lower index
|
||||
Deque<Entity> outOfBounds = new ArrayDeque<>(maxSize - newSize);
|
||||
for (int i = newSize; i < maxSize; i++) {
|
||||
Entity entityI = Entity.asEntity(i);
|
||||
@ -193,6 +196,7 @@ class EntityManager{
|
||||
outOfBounds.add(entityI);
|
||||
}
|
||||
}
|
||||
// Process all out-of-bounds entities, and destroy them as we go
|
||||
while(outOfBounds.size() > 0){
|
||||
Entity old = outOfBounds.remove();
|
||||
Entity newPos = addEntity();
|
||||
@ -204,7 +208,7 @@ class EntityManager{
|
||||
componentManager.moveAllComponentData(old, newPos, getRegistrations(old));
|
||||
}
|
||||
for (int i = newSize; i < maxSize; i++) {
|
||||
// Remove out-of-bounds data
|
||||
// Remove out-of-bounds registration data
|
||||
entityRegistrations.remove(newSize);
|
||||
}
|
||||
}
|
||||
@ -221,7 +225,7 @@ class EntityManager{
|
||||
}
|
||||
}
|
||||
|
||||
protected int getNumEntities(){
|
||||
public int getNumEntities(){
|
||||
return maxSize - unusedEntities.size();
|
||||
}
|
||||
}
|
@ -14,8 +14,11 @@ import java.util.BitSet;
|
||||
import java.util.Map;
|
||||
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
|
||||
*/
|
||||
class SystemManager{
|
||||
//private Map<Type, BitSet> registrationSignatures = new HashMap<>();
|
||||
private Map<Type, ECSSystem> systems = new HashMap<>();
|
||||
|
||||
/**
|
||||
@ -32,9 +35,7 @@ class SystemManager{
|
||||
|
||||
/**
|
||||
* Signals the SystemManager that an entity had its registrations changed, so
|
||||
* evaluate if the entity is still relevant to each system. This is not lightweight,
|
||||
* use entityRegistrationAdded and entityRegistrationRemoved if adding/removing a
|
||||
* single component
|
||||
* evaluate if the entity is still relevant to each system.
|
||||
* @param entity the entity that was modified
|
||||
* @param entityRegistrations the new registrations of the entity
|
||||
*/
|
||||
@ -61,7 +62,7 @@ class SystemManager{
|
||||
* @param system the instance of the system
|
||||
* @return true if the system was added successfully. False if it was already registered; with an error message written to the log
|
||||
*/
|
||||
protected boolean registerSystem(Type systemType, ECSSystem system){
|
||||
public boolean registerSystem(Type systemType, ECSSystem system){
|
||||
if (systems.containsKey(systemType)){
|
||||
Engine.writeErr("System \'" + systemType.getTypeName() + "\' already registered");
|
||||
return false;
|
||||
@ -75,7 +76,7 @@ class SystemManager{
|
||||
* @param systemType the class type of the system
|
||||
* @param registrations the BitSet containing the required registrations set to true
|
||||
*/
|
||||
protected void setRegistrationSignature(Type systemType, BitSet registrations){
|
||||
public void setSystemRegistraions(Type systemType, BitSet registrations){
|
||||
systems.get(systemType).registrationSet = registrations;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ class AppTest {
|
||||
|
||||
class TestSystem extends ECSSystem{
|
||||
public void init(){}
|
||||
public void update() {
|
||||
public void update(double dt) {
|
||||
for (Entity entity : entities) {
|
||||
TestObject entityComponent = (TestObject)gameEngine.getComponentData(entity, TestObject.class);
|
||||
entityComponent.i++;
|
||||
@ -99,7 +99,7 @@ class AppTest {
|
||||
gameEngine.addComponent(entity, TestObject.class, new TestObject());
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
system.update();
|
||||
system.update(0.1);
|
||||
}
|
||||
|
||||
assertEquals(6, ((TestObject)gameEngine.getComponentData(entity, TestObject.class)).i);
|
||||
@ -132,7 +132,6 @@ class AppTest {
|
||||
for (int i = 256; i < 512; i++) {
|
||||
gameEngine.destroyEntity(Entity.asEntity(i));
|
||||
}
|
||||
int k = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user