com.artemis.World Maven / Gradle / Ivy
package com.artemis;
import com.artemis.managers.ComponentManager;
import com.artemis.managers.EntityManager;
import com.artemis.managers.Manager;
import com.artemis.systems.EntitySystem;
import com.artemis.systems.event.EventDeliverySystem;
import com.artemis.systems.event.SystemEvent;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.ObjectSet;
/**
* The primary instance for the framework. It contains all the managers.
*
* You must use this to create, delete and retrieve entities.
*
* It is also important to set the delta each game loop iteration, and initialize before game loop.
*
* @author Arni Arent
*
*/
public class World implements Disposable {
/**
* Only used internally to maintain clean code.
*/
protected static interface Performer {
void perform(EntityObserver observer, Entity e);
}
protected EntityManager em;
protected ComponentManager cm;
protected float delta;
protected ObjectSet added;
protected ObjectSet changed;
protected ObjectSet deleted;
protected ObjectSet enable;
protected ObjectSet disable;
protected Performer addedPerformer;
protected Performer changedPerformer;
protected Performer deletedPerformer;
protected Performer enablePerformer;
protected Performer disablePerformer;
protected Array managers;
protected EventDeliverySystem eventSystem;
protected Array systems;
public World() {
this(new ComponentManager(), new EntityManager());
}
/**
* Create a world with a specified component and entity
* manager.
*
* @param cm ComponentManager to use.
* @param em EntityManager to use.
*/
public World(ComponentManager cm, EntityManager em) {
managers = new Array();
systems = new Array();
added = new ObjectSet();
changed = new ObjectSet();
deleted = new ObjectSet();
enable = new ObjectSet();
disable = new ObjectSet();
addedPerformer = new Performer() {
@Override
public void perform(EntityObserver observer, Entity e) {
observer.added(e);
}
};
changedPerformer = new Performer() {
@Override
public void perform(EntityObserver observer, Entity e) {
observer.changed(e);
}
};
deletedPerformer = new Performer() {
@Override
public void perform(EntityObserver observer, Entity e) {
observer.deleted(e);
}
};
enablePerformer = new Performer() {
@Override
public void perform(EntityObserver observer, Entity e) {
observer.enabled(e);
}
};
disablePerformer = new Performer() {
@Override
public void perform(EntityObserver observer, Entity e) {
observer.disabled(e);
}
};
this.cm = cm;
setManager(cm);
this.em = em;
setManager(em);
}
/**
* Makes sure all managers systems are initialized
* in the order they were added.
*/
public void initialize() {
// Can't use iterators here because initialize often calls
// getSystem or getManager
for (int i = 0; i < managers.size; i++) {
managers.get(i).initialize();
}
if (eventSystem != null) {
eventSystem.initialize();
}
for (int i = 0; i < systems.size; i++) {
systems.get(i).initialize();
}
}
/**
* Returns a manager that takes care of all the entities in the world.
*
* @return entity manager.
*/
public EntityManager getEntityManager() {
return em;
}
/**
* Returns a manager that takes care of all the components in the world.
*
* @return component manager.
*/
public ComponentManager getComponentManager() {
return cm;
}
/**
* Add a manager into this world. It can be retrieved later.
* World will notify this manager of changes to entity.
*
* @param Manager type
* @param manager to be added
* @return the manager that was added
*/
public T setManager(T manager) {
managers.add(manager);
manager.setWorld(this);
return manager;
}
/**
* Returns a manager of the specified type.
*
* @param Manager type
* @param managerType class type of the manager
* @return the manager
*/
@SuppressWarnings("unchecked")
public T getManager(Class managerType) {
for (Manager manager : managers) {
if (manager.getClass().equals(managerType)) {
return (T) manager;
}
}
return null;
}
/**
* Deletes the manager from this world.
* @param manager to delete.
*/
public void deleteManager(Manager manager) {
managers.removeValue(manager, true);
}
/**
* Time since last game loop.
*
* @return delta time since last game loop.
*/
public float getDelta() {
return delta;
}
/**
* You must specify the delta for the game here.
*
* @param delta time since last game loop.
*/
public void setDelta(float delta) {
this.delta = delta;
}
/**
* Adds a entity to this world.
*
* @param e entity
*/
public void addEntity(Entity e) {
added.add(e);
}
/**
* Ensure all systems are notified of changes to this entity.
* If you're adding a component to an entity after it's been
* added to the world, then you need to invoke this method.
*
* @param e entity
*/
public void changedEntity(Entity e) {
changed.add(e);
}
/**
* Delete the entity from the world.
*
* @param e Entity to remove
*/
public void deleteEntity(Entity e) {
if (!deleted.contains(e)) {
deleted.add(e);
}
if (added.contains(e)) {
added.remove(e);
}
}
/**
* (Re)enable the entity in the world, after it having being disabled.
* Won't do anything unless it was already disabled.
*
* @param e entity to enable
*/
public void enable(Entity e) {
enable.add(e);
}
/**
* Disable the entity from being processed. Won't delete it, it will
* continue to exist but won't get processed.
*
* @param e entity to disable
*/
public void disable(Entity e) {
disable.add(e);
}
/**
* Create and return a new or reused entity instance.
* Will NOT add the entity to the world, use World.addEntity(Entity)
* for that.
*
* @return created entity
*/
public Entity createEntity() {
return em.createEntityInstance();
}
/**
* Create and return a new or reused component instance of specified type.
*
* @param Type of component
* @param type Type of component to return
* @return Created component
*/
public T createComponent(Class type) {
return cm.createComponent(type);
}
/**
* Creates an instance of an event of a specified type. The event
* needs to be posted to the world in order to be propagated to listeners.
*
* @param Type of event
* @param type Type of event to create.
* @return Event of specified type.
*/
public T createEvent(Class type) {
return SystemEvent.createEvent(type);
}
/**
* Get a entity having the specified id.
*
* @param entityId id of the entity to retrieve.
* @return entity Entity or null.
*/
public Entity getEntity(int entityId) {
return em.getEntity(entityId);
}
/**
* Post event to all event systems.
*
* @param sendingSystem System that is sending the event.
* @param event Event being sent
*/
public void postEvent(EntitySystem sendingSystem, SystemEvent event) {
if (eventSystem != null) {
eventSystem.postEvent(sendingSystem, event);
}
}
/**
* Retrieve events from all systems. The set ensures that events are not repeated.
*
* @param Type of event
* @param pollingSystem System that is requesting the events.
* @param type Type of events requested.
* @param events Event set to populate with events
*/
public void getEvents(EntitySystem pollingSystem, Class type, Array events) {
events.clear();
if (eventSystem != null) {
eventSystem.getEvents(pollingSystem, type, events);
}
}
/**
* Gives you all the systems in this world for possible iteration.
*
* @return all entity systems in world.
*/
public Array getSystems() {
return systems;
}
/**
* Returns the event system, or null if not set.
*
* @return Event System for the world.
*/
public EventDeliverySystem getEventDeliverySystem() {
return eventSystem;
}
/**
* Set the system for event delivery.
*
* @param eventSystem Event delivery system
*/
public void setEventDeliverySystem(EventDeliverySystem eventSystem) {
this.eventSystem = eventSystem;
}
/**
* Adds a system to this world that will be processed by World.process()
*
* @param Type of entity system
* @param system the system to add.
* @return the added system.
*/
public T setSystem(T system) {
system.setWorld(this);
if (system instanceof EventDeliverySystem) {
eventSystem = (EventDeliverySystem) system;
} else {
systems.add(system);
}
return system;
}
/**
* Will add a system to this world.
*
* @param Type of entity system
* @param system the system to add.
* @param passive wether or not this system will be processed by World.process()
* @return the added system.
*/
public T setSystem(T system, boolean passive) {
setSystem(system);
system.setPassive(passive);
return system;
}
/**
* Removed the specified system from the world.
* @param system to be deleted from world.
*/
public void deleteSystem(EntitySystem system) {
if (system instanceof EventDeliverySystem) {
eventSystem = null;
} else {
systems.removeValue(system, true);
}
}
/**
* Notify systems of changes to the specified entity.
*
* @param performer The performer that notifies the systems.
* @param e Entity that has been affected.
*/
protected void notifySystems(Performer performer, Entity e) {
for(int i = 0; i < systems.size; i++) {
performer.perform(systems.get(i), e);
}
}
/**
* Notify managers of changes to the specified entity.
*
* @param performer The performer that notifies the managers.
* @param e Entity that has been affected.
*/
protected void notifyManagers(Performer performer, Entity e) {
for(Manager manager : managers) {
performer.perform(manager, e);
}
}
/**
* Retrieve a system for specified system type.
*
* @param Type of entity system
* @param type type of system.
* @return instance of the system in this world.
*/
@SuppressWarnings("unchecked")
public T getSystem(Class type) {
for (int i = 0; i < systems.size; i++) {
EntitySystem system = systems.get(i);
if (system.getClass().equals(type)) {
return (T) system;
}
}
return null;
}
/**
* Performs an action on each entity.
*
* @param entities
* @param performer
*/
protected void check(ObjectSet entities, Performer performer) {
if (entities.size > 0) {
for (Entity e : entities) {
notifyManagers(performer, e);
notifySystems(performer, e);
}
entities.clear();
}
}
/**
* Process all non-passive systems.
*/
public void process() {
check(added, addedPerformer);
check(changed, changedPerformer);
check(disable, disablePerformer);
check(enable, enablePerformer);
check(deleted, deletedPerformer);
cm.clean();
em.clean();
if (eventSystem != null) {
eventSystem.update();
}
for(int i = 0; i < systems.size; i++) {
EntitySystem system = systems.get(i);
if(!system.isPassive()) {
system.process();
}
}
}
/**
* Retrieves a ComponentMapper instance for fast retrieval of
* components from entities.
*
* @param Type of component
* @param type of component to get mapper for.
* @return mapper for specified component type.
*/
public ComponentMapper getMapper(Class type) {
return cm.getMapper(type);
}
@Override
public void dispose() {
em.dispose();
cm.dispose();
added.clear();
changed.clear();
deleted.clear();
enable.clear();
disable.clear();
for (Manager manager : managers) {
manager.dispose();
}
managers.clear();
systems.clear();
if (eventSystem != null) {
eventSystem.dispose();
eventSystem = null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy