What
EntityEngine is a nice pattern for externalizing the different components (logic) of an entity (object). And particularly effective in games, where features of an object is shared among many different types. This way the behavior of the object is put into separate components. The idea is that an entity is pretty much just an ID, and the components are referenced via. the entity ID.$engine = new EntityEngine();
$entity = new SimpleEntity($engine);
$entity->setComponent(new DialogComponent());
$entity->getComponent('Dialog')->talk();
Alternative:$engine->getComponent($entity, 'Dialog')->talk();
Why
Entity engines works very well as an alternative (and improvement) to deep inheritance trees. Inheritance can fall short when, for example you want a Rock to be able to speak (wouldn't want a Rock to inherit from Human, right?).Another advantage is that the engine, keep the components in an array based on their type. This means that we can fetch all components of a given type, without knowing (or caring) which entities own them.
$engine = new EntityEngine();
$entity = new SimpleEntity($engine);
$entity->setComponent(new CollisionComponent());
foreach($engine->getAll('Collision') as $comp) {
$comp->update();
}
Note: The only reason these examples are in PHP is for prototyping.EntityEngine Interfaces and Implementation
class EntityEngine
{
private $components = array();
/**
* @param Entity $entity
* @param string $componentName
* @return Component
*/
public function getComponent(Entity $entity, $componentName)
{
if($this->hasComponent($entity, $componentName)) {
return $this->components[$componentName][$entity->getId()];
}
return null;
}
/**
* @param Entity $entity
* @param string $componentName
* @return boolean
*/
public function hasComponent(Entity $entity, $componentName)
{
return isset($this->components[$componentName][$entity->getId()]);
}
/**
* @param Entity $entity
* @param Component $component
*/
public function setComponent(Entity $entity, Component $component)
{
$this->components[$component->getName()][$entity->getId()] = $component;
}
/**
* @param string $componentName
* @return array of Component
*/
public function getAll($componentName)
{
if(! isset($this->components[$componentName])) {
return array();
}
return $this->components[$componentName];
}
}
interface Entity
{
/**
* @return unique identifier for this instance
*/
public function getId();
/**
* @param string $component
* @return Component
*/
public function getComponent($componentName);
/**
* @param Component $component
*/
public function setComponent(Component $component);
}
abstract class SimpleEntity implements Entity
{
private $engine;
/**
* @param EntityEngine $engine
*/
public function __construct(EntityEngine $engine)
{
$this->engine = $engine;
}
public function getId()
{
return spl_object_hash($this);
}
public function getComponent($componentName)
{
return $this->engine->getComponent($this, $componentName);
}
public function setComponent(Component $component)
{
$this->engine->setComponent($this, $component);
}
}
interface Component
{
public function getName();
}Component Implementations of the Examples
class DialogComponent implements Component
{
public function getName()
{
return "Dialog";
}
public function moveRight();
}
class CollisionComponent implements Component
{
public function getName()
{
return "Collision";
}
public function update();
}
No comments:
Post a Comment