module Slickr::EntityManager

Provides a central repository for storing and querying for Entities that exhibit some behavior.

Each scene of your game will probably have many entities. When you instantiate one of those Entities, it’s automatically registered to the EntityManager, with the behaviors it implements.

@example

class Boss < Slickr::Entity
  use Spatial, x: 0, y: 0
end

boss = Boss.new
# => #<Boss components=[:spatial]>

EntityManager.entities
# => [#<Boss components=[:spatial]>]

Systems and Renderers are the two things that will likely need to alter or manipulate entities. Systems change the data associated with an entity and Renderers draw that to the screen. These objects can ask the EntityManager for any entities that care about the behaviors they affect.

@example

class Systems::Input
  def call(delta)
    entities.each { |e| e.up(delta) } if up_key?
  end

  def entities
    EntityManager.entities_with(:controllable, :spatial)
  end
end

The Input system cares about entities that can be moved by keyboard or mouse input and have spatial awareness; that is, things that can move. The above System tells an entity to move up if the up key is pressed. What “moving up” means is determined by the component. The System doesn’t care; it just reacts to events in the world and tells entities to do stuff based on that.

It’s important to view :controllable and :spatial as behaviors. Systems and Renderers expect these objects to conform to some standard API. We don’t care where the object came from, what type it is or what it does outside of what we expect. We’re going for good object oriented design through duck typing here.

Public Instance Methods

entities() click to toggle source

@!attribute entities

Hash of entities and their registered components
# File lib/slickr/entity_manager.rb, line 58
def entities
  @entities ||= reset!
end
entities_with(*components) click to toggle source

Retrieve all registered entities that include all of the components passed.

@param components [Array<Component>] List of components

@example

EntityManager.entities
=> { #<Entity components=[:spatial, :size]>, #<Entity components=[:spatial]> }

EntityManager.entities_with(:spatial, :size)
=> #<Entity components=[:spatial, :size]>
# File lib/slickr/entity_manager.rb, line 84
def entities_with(*components)
  entities.select { |entity, types| includes_all?(types, Set[*components]) }.keys
end
register(entity, type) click to toggle source

Register an Entity as conforming to a specific Component behavior.

@param entity [Entity] The Entity that includes the behavior @param type [Module] A Component module.

# File lib/slickr/entity_manager.rb, line 68
def register(entity, type)
  entities[entity] << symbolize(type)
end
reset!() click to toggle source

Remove all entities.

# File lib/slickr/entity_manager.rb, line 90
def reset!
  @entities = Hash.new { |h,k| h[k] = Set.new }
end

Private Instance Methods

includes_all?(types, items) click to toggle source
# File lib/slickr/entity_manager.rb, line 96
def includes_all?(types, items)
  items.subset?(types)
end
symbolize(type) click to toggle source
# File lib/slickr/entity_manager.rb, line 100
def symbolize(type)
  type.name.demodulize.underscore.gsub("_behavior", "").to_sym
end