summaryrefslogtreecommitdiffhomepage
path: root/system_manager.rb
diff options
context:
space:
mode:
authorrealtradam <[email protected]>2021-06-16 07:09:43 -0400
committerrealtradam <[email protected]>2021-06-16 07:09:43 -0400
commitba707eebb995eb46141d3c5e1701cd7252ba81c8 (patch)
treedfddbfd069825f55ace5ab25a4a3c09540744476 /system_manager.rb
parentf88af5840b9d6af0f78090c894818c5ee138979c (diff)
downloadFelECS-ba707eebb995eb46141d3c5e1701cd7252ba81c8.tar.gz
FelECS-ba707eebb995eb46141d3c5e1701cd7252ba81c8.zip
entities, components, and systems improved
Diffstat (limited to 'system_manager.rb')
-rw-r--r--system_manager.rb110
1 files changed, 107 insertions, 3 deletions
diff --git a/system_manager.rb b/system_manager.rb
index 14f37d4..4bd37b2 100644
--- a/system_manager.rb
+++ b/system_manager.rb
@@ -1,7 +1,111 @@
-#require 'app/ECS/systems/00_movement.rb'
-#require 'app/ECS/systems/01_flying.rb'
-
class FelFlame
class Systems
+ # How early this System should be executed in a list of Systems
+ attr_accessor :priority
+
+ # The Constant name assigned to this System
+ attr_accessor :const_name
+
+ # How many frames need to pass before this System is executed when controlled by {FelFlame::Stage}
+ attr_accessor :frame
+
+ attr_writer :addition_triggers
+
+ def addition_triggers
+ @addition_triggers ||= []
+ end
+
+ attr_writer :removal_triggers
+
+ def removal_triggers
+ @removal_triggers ||= []
+ end
+
+ class <<self
+ include Enumerable
+
+ # Iterate over all Systems, sorted by their priority. You also call other enumerable methods instead of each, such as +each_with_index+ or +select+
+ # @return [Enumerator]
+ def each(&block)
+ constants.map { |sym| const_get(sym) }.sort_by(&:priority).reverse.each(&block)
+ end
+ end
+
+ # Creates a new System which can be accessed as a constant under the namespace {FelFlame::Systems}.
+ # The name given is what constant the system is assigned to
+ #
+ # @example
+ # FelFlame::Systems.new('PassiveHeal', priority: -2, frame: 2) do
+ # FelFlame::Components::Health.each do |component|
+ # component.hp += 5
+ # end
+ # end
+ # # Only heal all characters with health every other frame.
+ # # Give it a low priority so other systems such as a
+ # # Poison system would kill the player first
+ #
+ # @param name [String] The name this system will use. Needs to to be in the Ruby Constant format.
+ # @param priority [Integer] Which priority order this system should be executed in relative to other systems. Higher means executed earlier.
+ # @param block [Proc] The code you wish to be executed when the system is triggered. Can be defined by using a +do end+ block or using +{ }+ braces.
+ def initialize(name, priority: 0, &block)
+ FelFlame::Systems.const_set(name, self)
+ @const_name = name
+ @priority = priority
+ @block = block
+ end
+
+ # Manually execute the system a single time
+ def call
+ @block.call
+ end
+
+ # Attempt to execute the system following the frame parameter set on this system.
+ # @return [Boolean] +true+ if the frame of the {FelFlame::Stage} is a multiple of this System's frame setting and this system has executed, +false+ otherwise where the system has not executed.
+ # For example if a System has its frame set to 3, it will only execute once every third frame that is called in FelFlame::Stage
+ #
+ def step; end
+
+ # Redefine what code is executed by this System when it is called upon.
+ # @param block [Proc] The code you wish to be executed when the system is triggered. Can be defined by using a +do end+ block or using +{ }+ braces.
+ def redefine(&block)
+ @block = block
+ end
+
+ # Removes triggers from this system
+ # @param component_or_manager [Component or ComponentManager] The object to clear triggers from. Use Nil to clear triggers from all components associated with this system.
+ # @return [Boolean] true
+ def clear_triggers(*trigger_types, component_or_manager: nil)
+ trigger_types = [:addition_triggers, :removal_triggers] if trigger_types.empty?
+ trigger_types.each do |trigger_type|
+ if component_or_manager.nil?
+ send(trigger_type).each do |trigger|
+ trigger.send(trigger_type).delete self
+ end
+ self.addition_triggers = []
+ else
+ send(trigger_type).delete component_or_manager
+ component_or_manager.send(trigger_type).delete self
+ end
+ end
+ true
+ end
+
+ # Add a component or component manager so that it triggers this system when the component or a component from the component manager is added to an entity
+ # @param component_or_manager [Component or ComponentManager] The component or component manager to trigger this system when added
+ # @return [Boolean] true
+ def trigger_when_added(component_or_manager)
+ self.addition_triggers |= [component_or_manager]
+ component_or_manager.addition_triggers |= [self]
+ true
+ end
+
+ # Add a component or component manager so that it triggers this system when the component or a component from the component manager is removed from an entity
+ # @param component_or_manager [Component or ComponentManager] The component or component manager to trigger this system when removed
+ # @return [Boolean] true
+ def trigger_when_removed(component_or_manager)
+ self.removal_triggers |= [component_or_manager]
+ component_or_manager.removal_triggers |= [self]
+ true
+ end
end
end