summaryrefslogtreecommitdiffhomepage
path: root/lib
diff options
context:
space:
mode:
author_Tradam <[email protected]>2021-12-30 07:33:27 -0500
committerGitHub <[email protected]>2021-12-30 07:33:27 -0500
commit3104eaf4ca0515572aeedc114cb6095a07825d90 (patch)
treea1feb0d69557f1a24f9884567d0d939c129c6447 /lib
parent5ef652300e71b572ca58b061610d606840ce19a9 (diff)
downloadFelECS-revert-12-arry.tar.gz
FelECS-revert-12-arry.zip
Revert "Major 4.0 update (#12)"revert-12-arry
This reverts commit 5ef652300e71b572ca58b061610d606840ce19a9.
Diffstat (limited to 'lib')
-rw-r--r--lib/felflame.rb18
-rw-r--r--lib/felflame/component_manager.rb128
-rw-r--r--lib/felflame/entity_manager.rb99
-rw-r--r--lib/felflame/scene_manager.rb8
-rw-r--r--lib/felflame/stage_manager.rb8
-rw-r--r--lib/felflame/system_manager.rb4
6 files changed, 124 insertions, 141 deletions
diff --git a/lib/felflame.rb b/lib/felflame.rb
index 54084bf..cf58990 100644
--- a/lib/felflame.rb
+++ b/lib/felflame.rb
@@ -4,10 +4,10 @@ require_relative 'felflame/system_manager'
require_relative 'felflame/scene_manager'
require_relative 'felflame/stage_manager'
-require_relative 'felflame/version'
+require_relative "felflame/version"
# The FelFlame namespace where all its functionality resides under.
-module FelFlame
+class FelFlame
class <<self
# :nocov:
@@ -18,26 +18,26 @@ module FelFlame
# :nocov:
end
- # Creates and manages Entities. Allows iterating or accessing Entities using array methods directly on the class. Entities are just collections of Components.
+ # Creates and manages Entities. Allows accessing Entities using their {FelFlame::Entities#id ID}. Entities are just collections of Components.
class Entities; end
- # Creates component managers and allows accessing them them under the {FelFlame::Components} namespace as Constants.
+ # Creates component managers and allows accessing them them under the {FelFlame::Components} namespace as Constants
#
# To see how component managers are used please look at the {FelFlame::ComponentManager} documentation.
- module Components; end
+ class Components; end
- # Creates an manages Systems. Systems are the logic of the game and do not contain any data within them. Any systems you create are accessable under the {FelFlame::Systems} namespace as Constants.
+ # Creates an manages Systems. Systems are the logic of the game and do not contain any data within them.
#
# TODO: Improve Systems overview
class Systems; end
- # Creates and manages Scenes. Scenes are collections of Systems, and execute all the Systems when called upon. Any scenes you create are accessable under the {FelFlame::Scenes} namespace as Constants.
+ # Creates and manages Scenes. Scenes are collections of Systems, and execute all the Systems when called upon.
#
# TODO: Improve Scenes overview
class Scenes; end
- # Stores Scenes you add to it which you want to execute on each frame. When called upon will execute all Systems in the Scenes in the Stage and will execute them according to their priority order.
- module Stage; end
+ # Stores Scenes which you want to execute on each frame. When called upon will execute all Systems in the Scenes in the Stage and will execute them according to their priority order.
+ class Stage; end
end
# An alias for {FelFlame}
diff --git a/lib/felflame/component_manager.rb b/lib/felflame/component_manager.rb
index ca5be89..43932d2 100644
--- a/lib/felflame/component_manager.rb
+++ b/lib/felflame/component_manager.rb
@@ -1,7 +1,8 @@
-module FelFlame
- module Components
+class FelFlame
+ class Components
@component_map = []
class <<self
+ include Enumerable
# Creates a new {FelFlame::ComponentManager component manager}.
#
# @example
@@ -45,26 +46,10 @@ module FelFlame
FelFlame::Components.const_get(component_name)
end
- # Makes component module behave like an array of component
- # managers with additional methods for managing the array
- # @!visibility private
- def respond_to_missing?(method, *)
- if constants.respond_to? method
- true
- else
- super
- end
- end
-
- # Makes component module behave like arrays with additional
- # methods for managing the array
- # @!visibility private
- def method_missing(method, *args, **kwargs, &block)
- if constants.respond_to? method
- constants.send(method, *args, **kwargs, &block)
- else
- super
- end
+ # Iterate over all existing component managers. You also call other enumerable methods instead of each, such as +each_with_index+ or +select+
+ # @return [Enumerator]
+ def each(&block)
+ constants.each(&block)
end
end
end
@@ -73,6 +58,16 @@ module FelFlame
# When a Component is created from a Component Manager that has accessors given to it, you can set or get the values of those accessors using standard ruby message sending (e.g [email protected] = 5+), or by using the {#attrs} and {#update_attrs} methods instead.
class ComponentManager
+ # Holds the {id unique ID} of a component. The {id ID} is only unique within the scope of the component manager it was created from.
+ # @return [Integer]
+ attr_reader :id
+
+ # A seperate attr_writer was made for documentation readability reasons.
+ # Yard will list attr_reader is readonly which is my intention.
+ # This value needs to be changable as it is set by other functions.
+ # @!visibility private
+ attr_writer :id
+
# Allows overwriting the storage of triggers, such as for clearing.
# This method should generally only need to be used internally and
# not by a game developer.
@@ -109,43 +104,25 @@ module FelFlame
def initialize(**attrs)
# Prepare the object
# (this is a function created with metaprogramming
- # in FelFlame::Components)
+ # in FelFlame::Components
set_defaults
+ # Generate ID
+ new_id = self.class.data.find_index { |i| i.nil? }
+ new_id = self.class.data.size if new_id.nil?
+ @id = new_id
+
# Fill params
attrs.each do |key, value|
send "#{key}=", value
end
# Save Component
- self.class.push self
+ self.class.data[new_id] = self
end
class <<self
- # Makes component managers behave like arrays with additional
- # methods for managing the array
- # @!visibility private
- def respond_to_missing?(method, *)
- if self._data.respond_to? method
- true
- else
- super
- end
- end
-
- # Makes component managers behave like arrays with additional
- # methods for managing the array
- # @!visibility private
- def method_missing(method, *args, **kwargs, &block)
- if self._data.respond_to? method
- self._data.send(method, *args, **kwargs, &block)
- else
- super
- end
- end
-
-
# Allows overwriting the storage of triggers, such as for clearing.
# This method should generally only need to be used internally and
# not by a game developer.
@@ -178,26 +155,39 @@ module FelFlame
# @return [Array<Component>] Array of all Components that belong to a given component manager
# @!visibility private
- def _data
+ def data
@data ||= []
end
+
+ # Gets a Component from the given {id unique ID}. Usage is simular to how an Array lookup works.
+ #
+ # @example
+ # # this gets the 'Health' Component with ID 7
+ # FelFlame::Components::Health[7]
+ # @param component_id [Integer]
+ # @return [Component] Returns the Component that uses the given unique {id ID}, nil if there is no Component associated with the given {id ID}
+ def [](component_id)
+ data[component_id]
+ end
+
+ # Iterates over all components within the component manager.
+ # Special Enumerable methods like +map+ or +each_with_index+ are not implemented
+ # @return [Enumerator]
+ def each(&block)
+ data.compact.each(&block)
+ end
end
- # Entities that have this component
- # @return [Array<Component>]
- def entities
- @entities ||= []
+ # An alias for the {id ID Reader}
+ # @return [Integer]
+ def to_i
+ id
end
- # A single entity. Use this if you expect the component to only belong to one entity and you want to access it.
- # @return [Component]
- def entity
- if entities.empty?
- Warning.warn("This component belongs to NO entities but you called the method that is intended for components belonging to a single entity.\nYou may have a bug in your logic.")
- elsif entities.length > 1
- Warning.warn("This component belongs to MANY entities but you called the method that is intended for components belonging to a single entity.\nYou may have a bug in your logic.")
- end
- entities.first
+ # A list of entity ids that are linked to the component
+ # @return [Array<Integer>]
+ def entities
+ @entities ||= []
end
# Update attribute values using a hash or keywords.
@@ -216,19 +206,25 @@ module FelFlame
systems_to_execute |= attr_triggers[attr] unless attr_triggers[attr].nil?
- systems_to_execute.sort_by(&:priority).reverse_each(&:call)
+ systems_to_execute.sort_by(&:priority).reverse.each(&:call)
true
end
- # Removes this component from the list and purges all references to this Component from other Entities, as well as its data.
+
+ # Removes this component from the list and purges all references to this Component from other Entities, as well as its {id ID} and data.
# @return [Boolean] +true+.
def delete
addition_triggers.each do |system|
system.clear_triggers component_or_manager: self
end
- entities.reverse_each do |entity|
+ # This needs to be cloned because indices get deleted as
+ # the remove command is called, breaking the loop if it
+ # wasn't referencing a clone(will get Nil errors)
+ iter = entities.map(&:clone)
+ iter.each do |entity|
+ #FelFlame::Entities[entity_id].remove self #unless FelFlame::Entities[entity_id].nil?
entity.remove self
end
- self.class._data.delete self
+ self.class.data[id] = nil
instance_variables.each do |var|
instance_variable_set(var, nil)
end
@@ -236,7 +232,7 @@ module FelFlame
end
# @return [Hash<Symbol, Value>] A hash, where all the keys are attributes linked to their respective values.
- def to_h
+ def attrs
return_hash = instance_variables.each_with_object({}) do |key, final|
final[key.to_s.delete_prefix('@').to_sym] = instance_variable_get(key)
end
diff --git a/lib/felflame/entity_manager.rb b/lib/felflame/entity_manager.rb
index 9489f29..a05ef93 100644
--- a/lib/felflame/entity_manager.rb
+++ b/lib/felflame/entity_manager.rb
@@ -1,59 +1,53 @@
-module FelFlame
+class FelFlame
class Entities
+ # Holds the unique ID of this entity
+ # @return [Integer]
+ attr_reader :id
+
+ # A seperate attr_writer was made for documentation readability reasons.
+ # Yard will list attr_reader is readonly which is my intention.
+ # This value needs to be changable as it is set by other functions.
+ # @!visibility private
+ attr_writer :id
# Creating a new Entity
# @param components [Components] Can be any number of components, identical duplicates will be automatically purged however different components from the same component manager are allowed.
# @return [Entity]
def initialize(*components)
+ # Assign new unique ID
+ new_id = self.class.data.find_index(&:nil?)
+ new_id = self.class.data.size if new_id.nil?
+ self.id = new_id
+
# Add each component
add(*components)
- # Fancy method redirection for when the `component` method is called
- @component_redirect = Object.new
- @component_redirect.instance_variable_set(:@entity, self)
- @component_redirect.define_singleton_method(:[]) do |component_manager|
- instance_variable_get(:@entity).component(component_manager)
- end
-
- self.class._data.push self
+ self.class.data[id] = self
end
- # A hash that uses component manager constant names as keys, and where the values of those keys are arrays that contain the the components attached to this entity.
+ # A hash that uses component manager constant names as keys, and where the values of those keys are arrays that contain the {FelFlame::ComponentManager#id IDs} of the components attached to this entity.
# @return [Hash<Component_Manager, Array<Integer>>]
def components
@components ||= {}
end
- # A single component from a component manager. Use this if you expect the component to only belong to one entity and you want to access it. Access the component using either parameter notation or array notation.
- # @example
- # @entity.component[@component_manager] # array notation
- # @entity.component(@component_manager) # method notation
- # @param manager [ComponentManager] If you pass nil you can then use array notation to access the same value.
- # @return [Component]
- def component(manager = nil)
- if manager.nil?
- @component_redirect
- else
- if components[manager].nil?
- raise "This entity(#{self}) doesnt have any components of this type: #{manager}"
- elsif components[manager].length > 1
- Warning.warn("This entity has MANY of this component but you called the method that is intended for having a single of this component type.\nYou may have a bug in your logic.")
- end
- components[manager].first
- end
+ # An alias for the {#id ID reader}
+ # @return [Integer]
+ def to_i
+ id
end
-
- # Removes this Entity from the list and purges all references to this Entity from other Components, as well as its data.
+ # Removes this Entity from the list and purges all references to this Entity from other Components, as well as its {id ID} and data.
# @return [Boolean] +true+
def delete
components.each do |component_manager, component_array|
- component_array.reverse_each do |component|
+ component_array.each do |component|
component.entities.delete(self)
end
end
- FelFlame::Entities._data.delete self
+ FelFlame::Entities.data[id] = nil
@components = {}
+ @id = nil
true
end
@@ -95,9 +89,6 @@ module FelFlame
check_systems component, :removal_triggers if component.entities.include? self
component.entities.delete self
components[component.class].delete component
- if components[component.class].empty?
- components.delete component.class
- end
end
true
end
@@ -108,33 +99,29 @@ module FelFlame
#def to_json() end
class <<self
- # Makes component managers behave like arrays with additional
- # methods for managing the array
+ include Enumerable
+ # @return [Array<Entity>] Array of all Entities that exist
# @!visibility private
- def respond_to_missing?(method, *)
- if self._data.respond_to? method
- true
- else
- super
- end
+ def data
+ @data ||= []
end
- # Makes component managers behave like arrays with additional
- # methods for managing the array
- # @!visibility private
- def method_missing(method, *args, **kwargs, &block)
- if self._data.respond_to? method
- self._data.send(method, *args, **kwargs, &block)
- else
- super
- end
+ # Gets an Entity from the given {id unique ID}. Usage is simular to how an Array lookup works
+ #
+ # @example
+ # # This gets the Entity with ID 7
+ # FelFlame::Entities[7]
+ # @param entity_id [Integer]
+ # @return [Entity] returns the Entity that uses the given unique ID, nil if there is no Entity associated with the given ID
+ def [](entity_id)
+ data[entity_id]
end
-
- # @return [Array<Entity>] Array of all Entities that exist
- # @!visibility private
- def _data
- @data ||= []
+ # Iterates over all entities. The data is compacted so that means index does not correlate to ID.
+ # You also call other enumerable methods instead of each, such as +each_with_index+ or +select+
+ # @return [Enumerator]
+ def each(&block)
+ data.compact.each(&block)
end
# Creates a new entity using the data from a JSON string
diff --git a/lib/felflame/scene_manager.rb b/lib/felflame/scene_manager.rb
index a9d3ac7..315dd55 100644
--- a/lib/felflame/scene_manager.rb
+++ b/lib/felflame/scene_manager.rb
@@ -1,4 +1,4 @@
-module FelFlame
+class FelFlame
class Scenes
# The Constant name assigned to this Scene
attr_reader :const_name
@@ -33,16 +33,16 @@ module FelFlame
# @return [Boolean] +true+
def add(*systems_to_add)
self.systems |= systems_to_add
- self.systems = systems.sort_by(&:priority)
+ systems.sort_by!(&:priority)
FelFlame::Stage.update_systems_list if FelFlame::Stage.scenes.include? self
true
end
- # Removes any number of Systems from this Scene
+ # Removes any number of SystemS from this Scene
# @return [Boolean] +true+
def remove(*systems_to_remove)
self.systems -= systems_to_remove
- self.systems = systems.sort_by(&:priority)
+ systems.sort_by!(&:priority)
FelFlame::Stage.update_systems_list if FelFlame::Stage.scenes.include? self
true
end
diff --git a/lib/felflame/stage_manager.rb b/lib/felflame/stage_manager.rb
index 05b5c19..87ee955 100644
--- a/lib/felflame/stage_manager.rb
+++ b/lib/felflame/stage_manager.rb
@@ -1,5 +1,5 @@
-module FelFlame
- module Stage
+class FelFlame
+ class Stage
class <<self
# Allows clearing of scenes and systems.
# Used internally by FelFlame and shouldn't need to be ever used by developers
@@ -13,7 +13,7 @@ module FelFlame
scenes_to_add.each do |scene|
self.systems |= scene.systems
end
- self.systems = systems.sort_by(&:priority)
+ systems.sort_by!(&:priority)
true
end
@@ -34,7 +34,7 @@ module FelFlame
scenes.each do |scene|
self.systems |= scene.systems
end
- self.systems = systems.sort_by(&:priority)
+ systems.sort_by!(&:priority)
true
end
diff --git a/lib/felflame/system_manager.rb b/lib/felflame/system_manager.rb
index d936e8e..cab2c4d 100644
--- a/lib/felflame/system_manager.rb
+++ b/lib/felflame/system_manager.rb
@@ -1,4 +1,4 @@
-module FelFlame
+class FelFlame
class Systems
# How early this System should be executed in a list of Systems
attr_accessor :priority
@@ -14,7 +14,7 @@ module FelFlame
def priority=(priority)
@priority = priority
- FelFlame::Stage.systems = FelFlame::Stage.systems.sort_by(&:priority)
+ FelFlame::Stage.systems.sort_by!(&:priority)
end
# Stores references to components or their managers that trigger
# this component when a component or component from that manager