game_actor_component_component_manager.js
import DrawableComponent from "./drawable_component.js";
import CollisionComponent from "./collision_component.js";
import PhysicsComponent from "./physics_component.js";
/**
* @module ComponentManager
* @fileoverview Contains ComponentManager class.
*/
/**
* @class
* Manager for components of an actor.
*/
class ComponentManager {
/**
* Create a new component manager.
* @param {Actor} actor Actor to be a part of
* @constructor
*/
constructor(actor) {
this._actor = actor;
this._components = new Map();
this._drawables = new Map();
this._collisions = new Map();
this._physics = new Map();
}
/**
* Call the destructor for all attached components.
*/
destructor() {
this._components.forEach(comp => comp.destructor());
}
//
// Management
//
/**
* Add a component to the actor.
* @typedef T
* @param {string} id Identifier of component
* @param {ActorComponent|T} comp Component to add
* @returns {T} Component that was added
*/
add(id, comp) {
this._components.set(id, comp);
if (comp instanceof DrawableComponent)
this._drawables.set(id, comp);
else if (comp instanceof CollisionComponent)
this._collisions.set(id, comp);
else if (comp instanceof PhysicsComponent)
this._physics.set(id, comp);
comp.actor = this._actor;
if (this._actor.initialized)
comp.init();
return comp;
}
/**
* Remove a component from the actor.
* @param {string} id Identifier of component to remove
*/
remove(id) {
const comp = this._components.get(id);
if (!comp)
return;
comp.destructor();
this._components.delete(id);
if (comp instanceof DrawableComponent)
this._drawables.delete(id);
else if (comp instanceof CollisionComponent)
this._collisions.delete(id);
else if (comp instanceof PhysicsComponent)
this._physics.delete(id);
}
/**
* Get a specific component.
* @param {string} id Identifier of component
* @returns {ActorComponent} Specified component
*/
get(id) {
if (!this._components.has(id))
return null;
return this._components.get(id);
}
/**
* Check if the actor has a component with a specified identifier.
* @param {string} id Identifier to check for
* @returns {boolean} Whether actor has component with specified identifier
*/
has(id) {
return this._components.has(id);
}
/**
* Get the total number of components.
* @returns {number} Number of components
*/
get count() {
return this._components.size;
}
/**
* Get an iterable iterator of all components.
* @returns {IterableIterator<ActorComponent>} All components
*/
getAll() {
return this._components.values();
}
/**
* Run a function for each component.
* @param {function} func Function to run for each component
*/
forAll(func = (comp, id) => {}) {
this._components.forEach(func);
}
//
// Specific Types
//
/**
* Get an iterable iterator of all DrawableComponents.
* @returns {IterableIterator<DrawableComponent>} All drawable components
*/
getDrawables() {
return this._drawables.values();
}
/**
* Get the amount of DrawableComponents.
* @returns {number} Number of drawable components
*/
get drawableCount() {
return this._drawables.size;
}
/**
* Get an iterable iterator of all CollisionComponents.
* @returns {IterableIterator<CollisionComponent>} All collision components
*/
getCollisions() {
return this._collisions.values();
}
/**
* Get the amount of CollisionComponents
* @returns {number} Number of collision components
*/
get collisionCount() {
return this._collisions.size;
}
/**
* Get an iterable iterator of all PhysicsComponents.
* @returns {IterableIterator<PhysicsComponent>} All physics components
*/
getPhysics() {
return this._physics.values();
}
/**
* Get the amount of PhysicsComponents
* @returns {number} Number of physics components
*/
get physicsCount() {
return this._physics.size;
}
//
// Update & Draw
//
/**
* Update all components.
* @param {number} elapsed Time since last update frame in seconds
*/
updateAll(elapsed) {
this._components.forEach(comp => comp.update(elapsed));
}
/**
* Draw all drawable components.
* @param {CanvasRenderingContext2D} ctx Canvas context for drawing
*/
drawAll(ctx) {
this._drawables.forEach(comp => comp.draw(ctx));
}
/**
* Draw debug info for all drawable components.
* @param {CanvasRenderingContext2D} ctx Canvas context for drawing
*/
drawDebugAll(ctx) {
this._components.forEach(comp => comp.drawDebug(ctx));
}
}
export default ComponentManager;