ECS refactoring (breaks game code)
- Remove requirement of an Engine instance in ComponentMapper instances, as the Engine from the entity passed to get() can be used. Allows for static initialization of ComponentMappers. - Store instances of ComponentMapper in a static Map within the ComponentMapper class itself, rather that inside of Engine. - Name bit/bits consistently. Some cases of bits were renamed to bit, such as ComponentType getBits() is now getBit(). Change usage of Mask to just Bits for consistency. - Modify access modifiers and field finality where appropriate - Add comments to public methods in Engine
This commit is contained in:
parent
cc53757a37
commit
6ae11ef2d3
@ -2,7 +2,7 @@ package com.me.common.ecs;
|
|||||||
|
|
||||||
public abstract class BaseSystem {
|
public abstract class BaseSystem {
|
||||||
|
|
||||||
protected Engine engine;
|
protected final Engine engine;
|
||||||
|
|
||||||
public BaseSystem(Engine engine) {
|
public BaseSystem(Engine engine) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
|
@ -1,38 +1,33 @@
|
|||||||
package com.me.common.ecs;
|
package com.me.common.ecs;
|
||||||
|
|
||||||
public class ComponentBag {
|
class ComponentBag {
|
||||||
|
|
||||||
private Component[] items;
|
private Component[] items;
|
||||||
private int size;
|
private int size;
|
||||||
|
|
||||||
public ComponentBag() {
|
ComponentBag() {
|
||||||
this.items = new Component[16];
|
this.items = new Component[16];
|
||||||
this.size = items.length;
|
this.size = items.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component get(int index) {
|
Component get(int index) {
|
||||||
if (index >= size) {
|
if (index >= size) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return items[index];
|
return items[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(int index) {
|
void insert(int index, Component item) {
|
||||||
return index < size && items[index] != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insert(int index, Component item) {
|
|
||||||
if (index >= size) {
|
if (index >= size) {
|
||||||
grow((int) (index * 1.5f));
|
grow((int) (index * 1.5f));
|
||||||
}
|
}
|
||||||
items[index] = item;
|
items[index] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(int index) {
|
void remove(int index) {
|
||||||
if (index >= size) {
|
if (index < size) {
|
||||||
throw new IndexOutOfBoundsException("index must be < size");
|
items[index] = null;
|
||||||
}
|
}
|
||||||
items[index] = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grow(int newSize) {
|
private void grow(int newSize) {
|
||||||
|
@ -1,23 +1,36 @@
|
|||||||
package com.me.common.ecs;
|
package com.me.common.ecs;
|
||||||
|
|
||||||
public class ComponentMapper<T extends Component> {
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
private Engine engine;
|
public final class ComponentMapper<T extends Component> {
|
||||||
private ComponentType type;
|
|
||||||
private Class<T> typeClass;
|
|
||||||
|
|
||||||
public ComponentMapper(Engine engine, Class<T> typeClass) {
|
private static final Map<Class<? extends Component>, ComponentMapper> mappers = new HashMap<>();
|
||||||
this.engine = engine;
|
|
||||||
|
private final ComponentType type;
|
||||||
|
private final Class<T> typeClass;
|
||||||
|
|
||||||
|
private ComponentMapper(Class<T> typeClass) {
|
||||||
this.type = ComponentType.getComponentType(typeClass);
|
this.type = ComponentType.getComponentType(typeClass);
|
||||||
this.typeClass = typeClass;
|
this.typeClass = typeClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T get(Entity entity) {
|
public T get(Entity entity) {
|
||||||
return typeClass.cast(engine.getEntityComponent(entity, type));
|
return typeClass.cast(entity.getComponent(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean has(Entity entity) {
|
public boolean has(Entity entity) {
|
||||||
return type.isTypeInMask(entity.componentBits);
|
return type.isInBits(entity.componentBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T extends Component> ComponentMapper<T> getFor(Class<T> typeClass) {
|
||||||
|
ComponentMapper<T> mapper = mappers.get(typeClass);
|
||||||
|
if (mapper == null) {
|
||||||
|
mapper = new ComponentMapper<>(typeClass);
|
||||||
|
mappers.put(typeClass, mapper);
|
||||||
|
}
|
||||||
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,64 +6,44 @@ import java.util.Map;
|
|||||||
final class ComponentType {
|
final class ComponentType {
|
||||||
|
|
||||||
private static final Map<Class<? extends Component>, ComponentType> types = new HashMap<>();
|
private static final Map<Class<? extends Component>, ComponentType> types = new HashMap<>();
|
||||||
private static final ComponentType[] typeById = new ComponentType[Long.SIZE];
|
|
||||||
|
|
||||||
private static long nextBit = 1l;
|
private static long nextBit = 1l;
|
||||||
private static int nextId = 0;
|
private static int nextId = 0;
|
||||||
|
|
||||||
protected long bits;
|
final long bit;
|
||||||
protected int id;
|
final int id;
|
||||||
|
|
||||||
private ComponentType() {
|
private ComponentType() {
|
||||||
this.bits = nextBit;
|
this.bit = nextBit;
|
||||||
this.id = nextId++;
|
this.id = nextId++;
|
||||||
|
|
||||||
this.nextBit <<= 1;
|
nextBit <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long getBits() {
|
boolean isInBits(long bits) {
|
||||||
|
return (bits & bit) == bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
static long getBitsFor(Class<? extends Component>... components) {
|
||||||
|
long bits = 0l;
|
||||||
|
for (Class<? extends Component> clazz : components) {
|
||||||
|
bits |= getComponentType(clazz).bit;
|
||||||
|
}
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getId() {
|
static ComponentType registerComponentType(Class<? extends Component> component) {
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static long getMaskBits(Class<? extends Component>... components) {
|
|
||||||
long mask = 0l;
|
|
||||||
for (Class<? extends Component> clazz : components) {
|
|
||||||
mask |= getTypeBits(clazz);
|
|
||||||
}
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static long getTypeBits(Class<? extends Component> component) {
|
|
||||||
return getComponentType(component).bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static int getTypeId(Class<? extends Component> component) {
|
|
||||||
return getComponentType(component).id;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static ComponentType getById(int id) {
|
|
||||||
return typeById[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isTypeInMask(long mask) {
|
|
||||||
return (bits & mask) == bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void registerComponentType(Class<? extends Component> component) {
|
|
||||||
ComponentType type = types.get(component);
|
ComponentType type = types.get(component);
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
throw new IllegalArgumentException(component.getName() + " has already been registered.");
|
throw new IllegalArgumentException(component.getName() + " has already been registered.");
|
||||||
}
|
}
|
||||||
type = new ComponentType();
|
type = new ComponentType();
|
||||||
types.put(component, type);
|
types.put(component, type);
|
||||||
typeById[type.id] = type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ComponentType getComponentType(Class<? extends Component> component) {
|
static ComponentType getComponentType(Class<? extends Component> component) {
|
||||||
ComponentType type = types.get(component);
|
ComponentType type = types.get(component);
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
throw new IllegalArgumentException(component.getName() + " has not been registered.");
|
throw new IllegalArgumentException(component.getName() + " has not been registered.");
|
||||||
@ -71,8 +51,4 @@ final class ComponentType {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int getRegisteredComponentTypeCount() {
|
|
||||||
return types.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,46 +4,51 @@ import com.badlogic.gdx.utils.Array;
|
|||||||
import com.me.common.ecs.event.Event;
|
import com.me.common.ecs.event.Event;
|
||||||
import com.me.common.ecs.event.Listener;
|
import com.me.common.ecs.event.Listener;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class Engine {
|
public class Engine {
|
||||||
|
|
||||||
private ComponentBag[] components;
|
private final EntityManager entityManager;
|
||||||
protected Array<BaseSystem> systems;
|
private final ComponentBag[] components;
|
||||||
|
private final Array<BaseSystem> systems;
|
||||||
|
|
||||||
private EntityManager entityManager;
|
private final ListenerRegistry listenerRegistry;
|
||||||
private ListenerRegistry listenerRegistry;
|
|
||||||
|
|
||||||
private Map<Class<? extends Component>, ComponentMapper> componentMappers;
|
|
||||||
|
|
||||||
public Engine() {
|
public Engine() {
|
||||||
this.entityManager = new EntityManager(this);
|
this.entityManager = new EntityManager(this);
|
||||||
|
this.components = new ComponentBag[Long.SIZE];
|
||||||
this.systems = new Array<>();
|
this.systems = new Array<>();
|
||||||
|
|
||||||
this.listenerRegistry = new ListenerRegistry();
|
this.listenerRegistry = new ListenerRegistry();
|
||||||
this.componentMappers = new HashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a Component class.
|
||||||
|
* @param clazz
|
||||||
|
*/
|
||||||
public void registerComponentClass(Class<? extends Component> clazz) {
|
public void registerComponentClass(Class<? extends Component> clazz) {
|
||||||
ComponentType.registerComponentType(clazz);
|
ComponentType type = ComponentType.registerComponentType(clazz);
|
||||||
|
components[type.id] = new ComponentBag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a BaseSystem.
|
||||||
|
* @param system
|
||||||
|
*/
|
||||||
public void registerSystem(BaseSystem system) {
|
public void registerSystem(BaseSystem system) {
|
||||||
this.systems.add(system);
|
systems.add(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an event Listener.
|
||||||
|
* @param listener
|
||||||
|
*/
|
||||||
public void registerListener(Listener listener) {
|
public void registerListener(Listener listener) {
|
||||||
listenerRegistry.registerListener(listener);
|
listenerRegistry.registerListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ready() {
|
/**
|
||||||
this.components = new ComponentBag[ComponentType.getRegisteredComponentTypeCount()];
|
* Process all systems
|
||||||
for (int i = 0; i < components.length; i++) {
|
* @param dt the time (in seconds) passed since the last update
|
||||||
components[i] = new ComponentBag();
|
*/
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(float dt) {
|
public void update(float dt) {
|
||||||
entityManager.update();
|
entityManager.update();
|
||||||
|
|
||||||
@ -54,61 +59,70 @@ public class Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return all entities known by the engine - both those active and inactive.
|
||||||
|
*/
|
||||||
public Array<Entity> getEntities() {
|
public Array<Entity> getEntities() {
|
||||||
return entityManager.entities;
|
return entityManager.getEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEntityCount() {
|
/**
|
||||||
return entityManager.entities.size;
|
* @return all currently registered systems.
|
||||||
|
*/
|
||||||
|
public Array<BaseSystem> getSystems() {
|
||||||
|
return systems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a new Entity object which can have fresh components added to it
|
||||||
|
*/
|
||||||
public Entity createEntity() {
|
public Entity createEntity() {
|
||||||
return entityManager.create();
|
return entityManager.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the given event, dispatching it to all registered Listeners that have an EventHandler
|
||||||
|
* for this particular event.
|
||||||
|
* @param event the event to call
|
||||||
|
*/
|
||||||
public void callEvent(Event event) {
|
public void callEvent(Event event) {
|
||||||
listenerRegistry.callEvent(event);
|
listenerRegistry.callEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void refreshEntity(Entity entity) {
|
void refreshEntity(Entity entity) {
|
||||||
entityManager.queueRefresh(entity);
|
entityManager.queueRefresh(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void removeAllEntityComponents(int entityId) {
|
void removeAllEntityComponents(int entityId) {
|
||||||
for (int i = 0; i < components.length; i++) {
|
for (ComponentBag bag : components) {
|
||||||
components[i].insert(entityId, null);
|
if (bag == null) {
|
||||||
|
// The rest of the array should also be null given that we never nullify
|
||||||
|
// an index after it has been set, and they are set sequentially. So, break.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bag.remove(entityId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addEntityComponent(Entity entity, Component component) {
|
void addEntityComponent(Entity entity, Component component) {
|
||||||
ComponentType type = ComponentType.getComponentType(component.getClass());
|
ComponentType type = ComponentType.getComponentType(component.getClass());
|
||||||
components[type.id].insert(entity.id, component);
|
components[type.id].insert(entity.id, component);
|
||||||
entity.addComponentType(type);
|
entity.addComponentType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void removeEntityComponent(Entity entity, Component component) {
|
void removeEntityComponent(Entity entity, Component component) {
|
||||||
ComponentType type = ComponentType.getComponentType(component.getClass());
|
ComponentType type = ComponentType.getComponentType(component.getClass());
|
||||||
components[type.id].remove(entity.id);
|
components[type.id].remove(entity.id);
|
||||||
entity.removeComponentType(type);
|
entity.removeComponentType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T extends Component> T getEntityComponent(Entity entity, Class<T> clazz) {
|
<T extends Component> T getEntityComponent(Entity entity, Class<T> clazz) {
|
||||||
return clazz.cast(components[ComponentType.getTypeId(clazz)].get(entity.id));
|
return clazz.cast(getEntityComponent(entity, ComponentType.getComponentType(clazz)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Component getEntityComponent(Entity entity, ComponentType type) {
|
Component getEntityComponent(Entity entity, ComponentType type) {
|
||||||
return components[type.id].get(entity.id);
|
return components[type.id].get(entity.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Component> ComponentMapper<T> getComponentMapper(Class<T> typeClass) {
|
|
||||||
ComponentMapper<T> mapper = componentMappers.get(typeClass);
|
|
||||||
if (mapper == null) {
|
|
||||||
mapper = new ComponentMapper<>(this, typeClass);
|
|
||||||
componentMappers.put(typeClass, mapper);
|
|
||||||
}
|
|
||||||
return mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,15 @@ public final class Entity {
|
|||||||
private static int nextId = 0;
|
private static int nextId = 0;
|
||||||
private static long nextUniqueId = 0;
|
private static long nextUniqueId = 0;
|
||||||
|
|
||||||
private Engine engine;
|
private final Engine engine;
|
||||||
protected final int id;
|
final int id;
|
||||||
|
|
||||||
protected long componentBits;
|
long componentBits;
|
||||||
protected long systemEnabledBits;
|
long systemEnabledBits;
|
||||||
|
boolean pendingRefresh;
|
||||||
|
|
||||||
protected boolean active;
|
boolean active;
|
||||||
protected boolean removed;
|
boolean removed;
|
||||||
protected boolean pendingRefresh;
|
|
||||||
|
|
||||||
private long uniqueId;
|
private long uniqueId;
|
||||||
|
|
||||||
@ -30,6 +30,10 @@ public final class Entity {
|
|||||||
return uniqueId;
|
return uniqueId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Engine getEngine() {
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
@ -60,18 +64,6 @@ public final class Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Engine getEngine() {
|
|
||||||
return this.engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasComponent(Class<? extends Component> clazz) {
|
|
||||||
return ComponentType.getComponentType(clazz).isTypeInMask(componentBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends Component> T getComponent(Class<T> clazz) {
|
|
||||||
return engine.getEntityComponent(this, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addComponent(Component component) {
|
public void addComponent(Component component) {
|
||||||
engine.addEntityComponent(this, component);
|
engine.addEntityComponent(this, component);
|
||||||
refresh();
|
refresh();
|
||||||
@ -82,39 +74,49 @@ public final class Entity {
|
|||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addComponentType(ComponentType type) {
|
private void refresh() {
|
||||||
componentBits |= type.bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removeComponentType(ComponentType type) {
|
|
||||||
componentBits &= ~type.bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addSystemEnabledBit(long bit) {
|
|
||||||
systemEnabledBits |= bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removeSystemEnabledBit(long bit) {
|
|
||||||
systemEnabledBits &= ~bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refresh() {
|
|
||||||
if (!pendingRefresh) {
|
if (!pendingRefresh) {
|
||||||
engine.refreshEntity(this);
|
engine.refreshEntity(this);
|
||||||
pendingRefresh = true;
|
pendingRefresh = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void reset() {
|
public boolean hasComponent(Class<? extends Component> clazz) {
|
||||||
|
return ComponentType.getComponentType(clazz).isInBits(componentBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Component> T getComponent(Class<T> clazz) {
|
||||||
|
return engine.getEntityComponent(this, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal getComponent method accessed only by ComponentMapper
|
||||||
|
Component getComponent(ComponentType type) {
|
||||||
|
return engine.getEntityComponent(this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addComponentType(ComponentType type) {
|
||||||
|
componentBits |= type.bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeComponentType(ComponentType type) {
|
||||||
|
componentBits &= ~type.bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSystemEnabledBit(long systemBit) {
|
||||||
|
systemEnabledBits |= systemBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeSystemEnabledBit(long systemBit) {
|
||||||
|
systemEnabledBits &= ~systemBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
componentBits = 0;
|
componentBits = 0;
|
||||||
systemEnabledBits = 0;
|
systemEnabledBits = 0;
|
||||||
active = false;
|
active = false;
|
||||||
removed = false;
|
removed = false;
|
||||||
pendingRefresh = false;
|
pendingRefresh = false;
|
||||||
}
|
uniqueId = nextUniqueId++;
|
||||||
|
|
||||||
protected void updateUniqueId() {
|
|
||||||
this.uniqueId = nextUniqueId++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -4,11 +4,11 @@ import com.badlogic.gdx.utils.Array;
|
|||||||
|
|
||||||
final class EntityManager {
|
final class EntityManager {
|
||||||
|
|
||||||
private Engine engine;
|
private final Engine engine;
|
||||||
|
|
||||||
protected Array<Entity> entities;
|
private final Array<Entity> entities;
|
||||||
protected Array<Entity> removedEntities;
|
private final Array<Entity> removedEntities;
|
||||||
protected Array<Entity> toRefresh;
|
private final Array<Entity> toRefresh;
|
||||||
|
|
||||||
EntityManager(Engine engine) {
|
EntityManager(Engine engine) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
@ -18,7 +18,11 @@ final class EntityManager {
|
|||||||
this.toRefresh = new Array<>(false, 16);
|
this.toRefresh = new Array<>(false, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity create() {
|
Array<Entity> getEntities() {
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity create() {
|
||||||
Entity entity;
|
Entity entity;
|
||||||
if (!removedEntities.isEmpty()) {
|
if (!removedEntities.isEmpty()) {
|
||||||
entity = removedEntities.removeIndex(0);
|
entity = removedEntities.removeIndex(0);
|
||||||
@ -26,12 +30,11 @@ final class EntityManager {
|
|||||||
entity = new Entity(engine);
|
entity = new Entity(engine);
|
||||||
}
|
}
|
||||||
entity.reset();
|
entity.reset();
|
||||||
entity.updateUniqueId();
|
|
||||||
entities.add(entity);
|
entities.add(entity);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
void update() {
|
||||||
if (toRefresh.isEmpty()) {
|
if (toRefresh.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -44,12 +47,12 @@ final class EntityManager {
|
|||||||
toRefresh.clear();
|
toRefresh.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void queueRefresh(Entity entity) {
|
void queueRefresh(Entity entity) {
|
||||||
toRefresh.add(entity);
|
toRefresh.add(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshEntity(Entity entity) {
|
private void refreshEntity(Entity entity) {
|
||||||
for (BaseSystem system : engine.systems) {
|
for (BaseSystem system : engine.getSystems()) {
|
||||||
if (!(system instanceof EntitySystem)) {
|
if (!(system instanceof EntitySystem)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -57,7 +60,7 @@ final class EntityManager {
|
|||||||
((EntitySystem) system).refresh(entity);
|
((EntitySystem) system).refresh(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.removed) {
|
if (entity.isRemoved()) {
|
||||||
engine.removeAllEntityComponents(entity.id);
|
engine.removeAllEntityComponents(entity.id);
|
||||||
entities.removeValue(entity, true);
|
entities.removeValue(entity, true);
|
||||||
removedEntities.add(entity);
|
removedEntities.add(entity);
|
||||||
|
@ -10,15 +10,16 @@ public abstract class EntitySystem extends BaseSystem {
|
|||||||
private static final Map<Class<? extends EntitySystem>, Long> systemBits = new HashMap<>();
|
private static final Map<Class<? extends EntitySystem>, Long> systemBits = new HashMap<>();
|
||||||
private static long nextBit = 1l;
|
private static long nextBit = 1l;
|
||||||
|
|
||||||
private long systemBit;
|
private final long systemBit;
|
||||||
private long typeBits;
|
private final long componentBits;
|
||||||
|
|
||||||
protected Array<Entity> entities;
|
private final Array<Entity> entities;
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
public EntitySystem(Engine engine, Class<? extends Component>... components) {
|
public EntitySystem(Engine engine, Class<? extends Component>... components) {
|
||||||
super(engine);
|
super(engine);
|
||||||
this.systemBit = getBitFor(getClass());
|
this.systemBit = getBitFor(getClass());
|
||||||
this.typeBits = ComponentType.getMaskBits(components);
|
this.componentBits = ComponentType.getBitsFor(components);
|
||||||
this.entities = new Array<>(true, 16, Entity.class);
|
this.entities = new Array<>(true, 16, Entity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,13 +38,13 @@ public abstract class EntitySystem extends BaseSystem {
|
|||||||
|
|
||||||
public abstract void processEntity(Entity entity, float dt);
|
public abstract void processEntity(Entity entity, float dt);
|
||||||
|
|
||||||
protected void refresh(Entity entity) {
|
void refresh(Entity entity) {
|
||||||
boolean enabled = (entity.systemEnabledBits & systemBit) == systemBit;
|
boolean enabled = (entity.systemEnabledBits & systemBit) == systemBit;
|
||||||
boolean interested = (entity.componentBits & typeBits) == typeBits;
|
boolean interested = (entity.componentBits & componentBits) == componentBits;
|
||||||
|
|
||||||
if (interested && !enabled && entity.active && !entity.removed) {
|
if (interested && !enabled && entity.active && !entity.removed) {
|
||||||
add(entity);
|
add(entity);
|
||||||
} else if (enabled && (!interested || !entity.active || entity.removed)) {
|
} else if (enabled && (!interested || !entity.active) || entity.removed) {
|
||||||
remove(entity);
|
remove(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,7 +60,7 @@ public abstract class EntitySystem extends BaseSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static long getBitFor(Class<? extends EntitySystem> es) {
|
private static long getBitFor(Class<? extends EntitySystem> es) {
|
||||||
Long bits = systemBits.get(es);
|
Long bits = systemBits.get(es);
|
||||||
if (bits == null) {
|
if (bits == null) {
|
||||||
bits = nextBit;
|
bits = nextBit;
|
||||||
|
@ -11,15 +11,15 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ListenerRegistry {
|
class ListenerRegistry {
|
||||||
|
|
||||||
private final Map<Class<? extends Event>, List<RegisteredListener>> registeredListeners;
|
private final Map<Class<? extends Event>, List<RegisteredListener>> registeredListeners;
|
||||||
|
|
||||||
protected ListenerRegistry() {
|
ListenerRegistry() {
|
||||||
this.registeredListeners = new HashMap<>();
|
this.registeredListeners = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void registerListener(Listener listener) {
|
void registerListener(Listener listener) {
|
||||||
for (Method method : listener.getClass().getMethods()) {
|
for (Method method : listener.getClass().getMethods()) {
|
||||||
EventHandler eh = method.getAnnotation(EventHandler.class);
|
EventHandler eh = method.getAnnotation(EventHandler.class);
|
||||||
if (eh == null) {
|
if (eh == null) {
|
||||||
@ -37,10 +37,9 @@ public class ListenerRegistry {
|
|||||||
List<RegisteredListener> executors = getRegisteredListeners(eventClass);
|
List<RegisteredListener> executors = getRegisteredListeners(eventClass);
|
||||||
executors.add(new RegisteredListener(listener, method, eventClass, eh));
|
executors.add(new RegisteredListener(listener, method, eventClass, eh));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void callEvent(Event event) {
|
void callEvent(Event event) {
|
||||||
List<RegisteredListener> listeners = getRegisteredListeners(event.getClass());
|
List<RegisteredListener> listeners = getRegisteredListeners(event.getClass());
|
||||||
if (listeners.isEmpty()) {
|
if (listeners.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -4,11 +4,10 @@ import java.lang.reflect.Method;
|
|||||||
|
|
||||||
public class RegisteredListener {
|
public class RegisteredListener {
|
||||||
|
|
||||||
private Listener listener;
|
private final Listener listener;
|
||||||
private Method method;
|
private final Method method;
|
||||||
private Class<? extends Event> eventType;
|
private final Class<? extends Event> eventType;
|
||||||
|
private final EventHandler eh;
|
||||||
public EventHandler eh;
|
|
||||||
|
|
||||||
public RegisteredListener(Listener listener, Method method, Class<? extends Event> eventType, EventHandler eh) {
|
public RegisteredListener(Listener listener, Method method, Class<? extends Event> eventType, EventHandler eh) {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
|
Loading…
Reference in New Issue
Block a user