Skip to content

Instantly share code, notes, and snippets.

@mbuffa
Last active March 13, 2019 10:56
Show Gist options
  • Save mbuffa/b11518fd6b5b82edf1ade168b30255e0 to your computer and use it in GitHub Desktop.
Save mbuffa/b11518fd6b5b82edf1ade168b30255e0 to your computer and use it in GitHub Desktop.
An attempt at creating an Entity-Component-System architecture, in Ruby
require 'securerandom'
Entity = Struct.new(:uuid)
class Component
attr_accessor :entity_uuid
def initialize(entity_uuid)
@entity_uuid = entity_uuid
ComponentsStore.register_component(self)
end
end
class System
class << self
def update(payload = nil)
SystemsStore.all.each do |systems|
systems.each do |sistem|
sistem.update(payload)
end
end
end
end
def initialize(*component_types)
@component_types = component_types
SystemsStore.register_system(self, @component_types)
end
def update(payload = nil)
raise 'You must implement this method!'
end
end
class SystemsStore
class << self
def all
instance.systems.values
end
def register_system(sistem, component_types)
instance.systems[component_types] ||= []
instance.systems[component_types] << sistem
self
end
private
def instance
@instance ||= new
end
end
attr_reader :systems
private
def initialize
@systems = {}
end
end
class ComponentsStore
class << self
def fetch_by_types(types)
Array(types).map do |type|
instance.components[type]
end.flatten
end
def register_component(component)
instance.components[component.class] ||= []
instance.components[component.class] << component
self
end
private
def instance
@instance ||= new
end
end
attr_reader :components
private
def initialize
@components = {}
end
end
RSpec.describe 'Ruby Entity-Component-System architecture' do
class YoloComponent < Component
end
class YoloSystem < System
def initialize
super(YoloComponent)
end
def update(payload = nil)
ComponentsStore.fetch_by_types(*@component_types).each do |component|
puts "#{component.class} says: Yolo!"
end
end
end
before do
@yolo_entity = Entity.new(SecureRandom.uuid)
@yolo_component = YoloComponent.new(@yolo_entity.uuid)
@yolo_system = YoloSystem.new
end
describe System do
it "doesn't crash" do
expect { described_class.update }.not_to raise_error
end
it 'sends updates to all systems' do
allow(@yolo_system).to receive(:update)
described_class.update
expect(@yolo_system).to have_received(:update).exactly(1).times
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment