From 9ae334ecc6aaef009f14c0bb8b57afcb721f709b Mon Sep 17 00:00:00 2001 From: realtradam Date: Thu, 20 Jan 2022 22:41:04 -0500 Subject: rename to FelECS --- Gemfile.lock | 4 +- README.mdown | 487 ++++++++++++++++++---------------- docs/_index.html | 101 +------ docs/class_list.html | 2 +- docs/file.README.html | 540 ++++++++++++++++++++++++-------------- docs/index.html | 540 ++++++++++++++++++++++++-------------- docs/method_list.html | 368 -------------------------- docs/top-level-namespace.html | 39 +-- felecs.gemspec | 45 ++++ felflame.gemspec | 45 ---- lib/felecs.rb | 67 +++++ lib/felecs/component_manager.rb | 277 +++++++++++++++++++ lib/felecs/entity_manager.rb | 160 +++++++++++ lib/felecs/order.rb | 24 ++ lib/felecs/scene_manager.rb | 69 +++++ lib/felecs/stage_manager.rb | 47 ++++ lib/felecs/system_manager.rb | 258 ++++++++++++++++++ lib/felecs/version.rb | 9 + lib/felflame.rb | 67 ----- lib/felflame/component_manager.rb | 277 ------------------- lib/felflame/entity_manager.rb | 160 ----------- lib/felflame/order.rb | 24 -- lib/felflame/scene_manager.rb | 69 ----- lib/felflame/stage_manager.rb | 47 ---- lib/felflame/system_manager.rb | 258 ------------------ lib/felflame/version.rb | 9 - logos/felecs-logo-text.png | Bin 0 -> 44520 bytes logos/felecs-logo-text.png.png | Bin 44520 -> 0 bytes spec/component_manager_spec.rb | 52 ++-- spec/entity_manager_spec.rb | 38 +-- spec/order_spec.rb | 18 +- spec/scene_manager_spec.rb | 14 +- spec/stage_manager_spec.rb | 40 +-- spec/system_manager_spec.rb | 74 +++--- 34 files changed, 2007 insertions(+), 2222 deletions(-) create mode 100644 felecs.gemspec delete mode 100644 felflame.gemspec create mode 100644 lib/felecs.rb create mode 100644 lib/felecs/component_manager.rb create mode 100644 lib/felecs/entity_manager.rb create mode 100644 lib/felecs/order.rb create mode 100644 lib/felecs/scene_manager.rb create mode 100644 lib/felecs/stage_manager.rb create mode 100644 lib/felecs/system_manager.rb create mode 100644 lib/felecs/version.rb delete mode 100644 lib/felflame.rb delete mode 100644 lib/felflame/component_manager.rb delete mode 100644 lib/felflame/entity_manager.rb delete mode 100644 lib/felflame/order.rb delete mode 100644 lib/felflame/scene_manager.rb delete mode 100644 lib/felflame/stage_manager.rb delete mode 100644 lib/felflame/system_manager.rb delete mode 100644 lib/felflame/version.rb create mode 100644 logos/felecs-logo-text.png delete mode 100644 logos/felecs-logo-text.png.png diff --git a/Gemfile.lock b/Gemfile.lock index 7b5b5fe..5ce0ad2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - felflame (4.0.0) + felecs (5.0.0) GEM remote: https://rubygems.org/ @@ -69,7 +69,7 @@ PLATFORMS ruby DEPENDENCIES - felflame! + felecs! minitest-reporters (~> 1.4, >= 1.4.3) rake (~> 13.0) redcarpet (~> 3.5, >= 3.5.1) diff --git a/README.mdown b/README.mdown index acae578..8cc18d9 100644 --- a/README.mdown +++ b/README.mdown @@ -1,10 +1,10 @@ -![FelFlame](https://raw.githubusercontent.com/realtradam/FelFlame/master/logos/felflame-logo-text.png) - +![FelECS](https://raw.githubusercontent.com/realtradam/FelECS/master/logos/felecs-logo-text.png) + -[![Maintainability](https://api.codeclimate.com/v1/badges/56d425d9078e98efb74b/maintainability)](https://codeclimate.com/github/realtradam/FelFlame/maintainability) -[![Test Coverage](https://api.codeclimate.com/v1/badges/56d425d9078e98efb74b/test_coverage)](https://codeclimate.com/github/realtradam/FelFlame/test_coverage) -[![Inline docs](http://inch-ci.org/github/realtradam/FelFlame.svg?branch=master)](http://inch-ci.org/github/realtradam/FelFlame) -[![MIT License](https://img.shields.io/github/license/realtradam/FelFlame?label=license&style=flat)](https://github.com/realtradam/FelFlame/blob/master/LICENSE) +[![Maintainability](https://api.codeclimate.com/v1/badges/56d425d9078e98efb74b/maintainability)](https://codeclimate.com/github/realtradam/FelECS/maintainability) +[![Test Coverage](https://api.codeclimate.com/v1/badges/56d425d9078e98efb74b/test_coverage)](https://codeclimate.com/github/realtradam/FelECS/test_coverage) +[![Inline docs](http://inch-ci.org/github/realtradam/FelECS.svg?branch=master)](http://inch-ci.org/github/realtradam/FelECS) +[![MIT License](https://img.shields.io/github/license/realtradam/FelECS?label=license&style=flat)](https://github.com/realtradam/FelECS/blob/master/LICENSE) [![Ko-Fi](https://img.shields.io/static/v1?message=Buy%20me%20a%20coffee&logo=kofi&labelColor=ff5e5b&color=434B57&logoColor=white&label=%20)](https://ko-fi.com/tradam) **[Check out the comprehensive documentation here!](https://felflame.tradam.fyi/)** @@ -13,7 +13,7 @@ -* [What is FelFlame?](#what-is-felflame) +* [What is FelECS?](#what-is-felecs) * [What is ECS?](#what-is-ecs) * [Components](#components) * [Entities](#entities) @@ -35,12 +35,33 @@ * [Accessing Attributes and Changing Them](#accessing-attributes-and-changing-them) * [Deleting Components](#deleting-components) * [Accessing Components' attached Entities](#accessing-components-attached-entities) +* [get the first entity attached.](#get-the-first-entity-attached) +* [this will throw a warning if there is more or less then](#this-will-throw-a-warning-if-there-is-more-or-less-then) +* [exactly one entity](#exactly-one-entity) * [Systems](#systems-1) * [Creation](#creation-1) +* [Code and Logic](#code-and-logic) +* [do something with these components](#do-something-with-these-components) * [Execution](#execution) * [Alternative Execution](#alternative-execution) +* [When this Component is added to an Entity, this System will be called](#when-this-component-is-added-to-an-entity-this-system-will-be-called) +* [When this Component is removed from an Entity, this System will be called](#when-this-component-is-removed-from-an-entity-this-system-will-be-called) +* [When this Component's health attribute is changed, this System will be called](#when-this-components-health-attribute-is-changed-this-system-will-be-called) +* [When a Component from this Component Manager is added to an Entity, this System will be called](#when-a-component-from-this-component-manager-is-added-to-an-entity-this-system-will-be-called) +* [When a Component from this Component Manager is removed from an Entity, this System will be called](#when-a-component-from-this-component-manager-is-removed-from-an-entity-this-system-will-be-called) +* [When this Component's health attribute from this Component Manager is changed, this System will be called](#when-this-components-health-attribute-from-this-component-manager-is-changed-this-system-will-be-called) * [Clearing Alternative Executions](#clearing-alternative-executions) +* [clears ALL triggers with this system](#clears-all-triggers-with-this-system) +* [clears ALL triggers with this Component Manager](#clears-all-triggers-with-this-component-manager) +* [clear the 'trigger_when_added' for this Component](#clear-the-trigger_when_added-for-this-component) +* [clear the 'trigger_when_removed' for this Component](#clear-the-trigger_when_removed-for-this-component) +* [clear the 'trigger_when_is_set' for this Component specifically for the health attribute](#clear-the-trigger_when_is_set-for-this-component-specifically-for-the-health-attribute) +* [clears ALL triggers with this Component](#clears-all-triggers-with-this-component) +* [clear the 'trigger_when_added' for this Component Manager](#clear-the-trigger_when_added-for-this-component-manager) +* [clear the 'trigger_when_removed' for this Component Manager](#clear-the-trigger_when_removed-for-this-component-manager) +* [clear the 'trigger_when_is_set' for this Component Manager specifically for the health attribute](#clear-the-trigger_when_is_set-for-this-component-manager-specifically-for-the-health-attribute) * [Redefinition](#redefinition) +* [Some new logic or code](#some-new-logic-or-code) * [Scenes](#scenes-1) * [Creation](#creation-2) * [Accessing](#accessing-2) @@ -59,407 +80,407 @@ -# What is FelFlame? +# What is FelECS? -FelFlame is an ECS framework for developing games in the Ruby language. FelFlame has been designed from the ground up with these three ideas in mind: + FelECS is an ECS framework for developing games in the Ruby language. FelECS has been designed from the ground up with these three ideas in mind: -1. **Engine Agnostic:** FelFlame has been designed to be rendering engine agnostic as long as the target rendering engine is written in Ruby. This means that this framework can be dropped into existing rendering engines such as [Ruby2D](http://www.ruby2d.com) or [DRGTK](https://dragonruby.org/toolkit/game) with little modifications. -2. **Easily Extensible:** FelFlame has been designed such that extensions to its capabilities can be easily added. Extensions such as rendering engine wrappers, premade systems, premade components, etcetera can be easily coded and then distributed as gems. -3. **Principle of (My) Least Astonishment:** I want to develop games using a language and framework I love and makes sense to me, inspired by the [Philosophy of the creator of Ruby](https://en.wikipedia.org/wiki/Ruby_(programming_language)#Philosophy). + 1. **Engine Agnostic:** FelECS has been designed to be rendering engine agnostic as long as the target rendering engine is written in Ruby. This means that this framework can be dropped into existing rendering engines such as [Ruby2D](http://www.ruby2d.com) or [DRGTK](https://dragonruby.org/toolkit/game) with little modifications. + 2. **Easily Extensible:** FelECS has been designed such that extensions to its capabilities can be easily added. Extensions such as rendering engine wrappers, premade systems, premade components, etcetera can be easily coded and then distributed as gems. + 3. **Principle of (My) Least Astonishment:** I want to develop games using a language and framework I love and makes sense to me, inspired by the [Philosophy of the creator of Ruby](https://en.wikipedia.org/wiki/Ruby_(programming_language)#Philosophy). # What is ECS? -ECS is a software architectural pattern that is used in video game development. Traditionally games were programmed using an object oriented method, while ECS instead attempts to program games using a data oriented method instead. -ECS stands for Entity, Component, and System. + ECS is a software architectural pattern that is used in video game development. Traditionally games were programmed using an object oriented method, while ECS instead attempts to program games using a data oriented method instead. + ECS stands for Entity, Component, and System. ---- + --- ### Components -This is where the data or information of a given "object" is stored. There is no logic or code here. + This is where the data or information of a given "object" is stored. There is no logic or code here. ### Entities -Entities will contain one or more Components, but contains no logic or data otherwise + Entities will contain one or more Components, but contains no logic or data otherwise ### Systems -Systems are where all the logic or code is kept. There is no data stored in here. + Systems are where all the logic or code is kept. There is no data stored in here. ---- + --- -By using this pattern it allows programmers to easily control what an "object" or entity can do and how much data it needs to have. It avoids the issue of inhertance as no inhertance is ever required in this system. If you need a certain entity to have a certain functionality you just add the relevant component to it, and the systems that automatically go over specific components will give your entitiy the desired functionality. + By using this pattern it allows programmers to easily control what an "object" or entity can do and how much data it needs to have. It avoids the issue of inhertance as no inhertance is ever required in this system. If you need a certain entity to have a certain functionality you just add the relevant component to it, and the systems that automatically go over specific components will give your entitiy the desired functionality. -**"But your framework also has `Scenes`, `Stage`, and `Order`, what is that about?"** + **"But your framework also has `Scenes`, `Stage`, and `Order`, what is that about?"** ---- + --- ### Scenes -Scenes are simply a collection or subset of Systems. This allows for an easy way to activate and deactivate Systems. + Scenes are simply a collection or subset of Systems. This allows for an easy way to activate and deactivate Systems. ### Stage -The Stage is Scenes which are activated. This means any Scenes on the Stage are executed each frame, while the rest of the Systems are not. + The Stage is Scenes which are activated. This means any Scenes on the Stage are executed each frame, while the rest of the Systems are not. ### Order -Order is a helper class which can set the priority of Scenes and Systems. + Order is a helper class which can set the priority of Scenes and Systems. ---- + --- # Usage -There are 2 ways of using FelFlame. You can either `include` it as a gem in your project if your game engine supports this. The other option is to download the single file export of FelFlame and then `require_relative` this file in your project. The single file export takes all the ruby code in the various files and concatenates them into a single file so it is more portable and easy to add. + There are 2 ways of using FelECS. You can either `include` it as a gem in your project if your game engine supports this. The other option is to download the single file export of FelECS and then `require_relative` this file in your project. The single file export takes all the ruby code in the various files and concatenates them into a single file so it is more portable and easy to add. -To use the gem method you can do the following: install the gem using `gem install felflame` or using bundler `bundle add felflame` and then require it in your project like so: `require 'felflame'`. + To use the gem method you can do the following: install the gem using `gem install felflame` or using bundler `bundle add felflame` and then require it in your project like so: `require 'felflame'`. -To use the single file export method you simply download the felflame.rb file from the [releases page on Github](https://github.com/realtradam/FelFlame/releases) and add it to your source folder and add a `require relative 'felflame.rb'` line or wherever you have placed the file to use it. + To use the single file export method you simply download the felflame.rb file from the [releases page on Github](https://github.com/realtradam/FelECS/releases) and add it to your source folder and add a `require relative 'felflame.rb'` line or wherever you have placed the file to use it. ## Entities ### Creation -Entities are essentially "objects" in the game world. To create a new Entity we do the following: + Entities are essentially "objects" in the game world. To create a new Entity we do the following: -```ruby -@entity = FelFlame::Entities.new -``` -or if we want to add (any number of)components to it when creating it: + ```ruby + @entity = FelECS::Entities.new + ``` + or if we want to add (any number of)components to it when creating it: -```ruby -@entity = FelFlame::Entites.new( - FelFlame::Components::Health.new, - @component, - FelFlame::Components::EnemyTeam.first -) -``` + ```ruby +@entity = FelECS::Entites.new( + FelECS::Components::Health.new, + @component, + FelECS::Components::EnemyTeam.first + ) + ``` ### Accessing -Oftentimes you will not be accessing an Entity this way. Later we will shows you a more common way of accessing entities. -If you need to you can access Entities using the `Entities` module: + Oftentimes you will not be accessing an Entity this way. Later we will shows you a more common way of accessing entities. + If you need to you can access Entities using the `Entities` module: -```ruby -@entity = FelFlame::Entities[2] -@entity = FelFlame::Entities.first -@entity = FelFlame::Entities.each # you can iterate over all entities this way. Any valid array method can be used -``` + ```ruby + @entity = FelECS::Entities[2] + @entity = FelECS::Entities.first + @entity = FelECS::Entities.each # you can iterate over all entities this way. Any valid array method can be used + ``` ### Adding and Removing Components -We can still add or remove Components from an Entity after it has been created. Here is how: + We can still add or remove Components from an Entity after it has been created. Here is how: -```ruby -@entity.add @component -@entity.remove @component -``` + ```ruby + @entity.add @component + @entity.remove @component + ``` ### Accessing Entities' Attached Components -This is the most common way of accessing an Entity + This is the most common way of accessing an Entity -When Components are added to Entities, they can be accessed from the Entity. By using a Component Manager as a key we can access an array of all components created from that Component Manager that are attached to an entity: + When Components are added to Entities, they can be accessed from the Entity. By using a Component Manager as a key we can access an array of all components created from that Component Manager that are attached to an entity: -```ruby -@entity.components[@component_manager] # => [@component1, @component2, @component3] -``` + ```ruby + @entity.components[@component_manager] # => [@component1, @component2, @component3] + ``` ### Deletion -To have all Components from an Entity **removed** and the Entity deleted we do the following: + To have all Components from an Entity **removed** and the Entity deleted we do the following: -NOTE: The components will **not be deleted**. They are simply **removed** from the entity and then the entity is destroyed. You must handle component deletion yourself as for example singleton components need to removed instead of deleted. + NOTE: The components will **not be deleted**. They are simply **removed** from the entity and then the entity is destroyed. You must handle component deletion yourself as for example singleton components need to removed instead of deleted. -```ruby -@entity.delete -``` + ```ruby + @entity.delete + ``` ## Components ### Creating a Component Manager -Components are where all the data is stored. The data is stored in variables or accessors in each component. -These accessors and their defaults are configured when a component manager is created, like so: + Components are where all the data is stored. The data is stored in variables or accessors in each component. + These accessors and their defaults are configured when a component manager is created, like so: -```ruby -@component_manager = FelFlame::Components.new('Stats', :armour, hp: 100) -``` + ```ruby + @component_manager = FelECS::Components.new('Stats', :armour, hp: 100) + ``` -In this example we created a component manager called "Stats". -The name given to component managers must follow the same rules for naming constants in ruby for a reason you will shortly see. -The parameters following are all creating the attributes we can set. -We can set any number of parameters we wish, in this example we define two. -The `:armour` parameter is being created without a default, it will equal to `nil` when a new component is created, while `hp` will be equal to 100 when a component is created. -When defining attributes symbols should be used. + In this example we created a component manager called "Stats". + The name given to component managers must follow the same rules for naming constants in ruby for a reason you will shortly see. + The parameters following are all creating the attributes we can set. + We can set any number of parameters we wish, in this example we define two. + The `:armour` parameter is being created without a default, it will equal to `nil` when a new component is created, while `hp` will be equal to 100 when a component is created. + When defining attributes symbols should be used. ### Creating a Component from a Component Manager -Now that we have a component manager we can make components from it like so: + Now that we have a component manager we can make components from it like so: -```ruby -@component = FelFlame::Components::Stats.new -``` + ```ruby + @component = FelECS::Components::Stats.new + ``` -Or we can even override the defaults when creating the component: + Or we can even override the defaults when creating the component: -```ruby -@component = FelFlame::Components::Stats.new(armour: 'steel') -``` + ```ruby + @component = FelECS::Components::Stats.new(armour: 'steel') + ``` ### Accessing -You can access components using any array method. + You can access components using any array method. -```ruby -@component = FelFlame::Components::Stats[2] -@component = FelFlame::Components::Stats.first -@component = FelFlame::Components::Stats.each # you can use iterators this way -``` + ```ruby + @component = FelECS::Components::Stats[2] + @component = FelECS::Components::Stats.first + @component = FelECS::Components::Stats.each # you can use iterators this way + ``` ### Accessing Attributes and Changing Them -There are a few different ways we can read or change the attributes of a component depending on what our needs are. -Here are the ways to edit attrubutes, followed by the ways to read them. -```ruby -@component.armour = 'Mythril' -@component.update_attrs(armour: 'Leather', hp: 95) -``` -```ruby -@component.hp # => 95 -@component.to_h # => {armour: 'Leather', hp: 95} -``` + There are a few different ways we can read or change the attributes of a component depending on what our needs are. + Here are the ways to edit attrubutes, followed by the ways to read them. + ```ruby + @component.armour = 'Mythril' + @component.update_attrs(armour: 'Leather', hp: 95) + ``` + ```ruby + @component.hp # => 95 + @component.to_h # => {armour: 'Leather', hp: 95} + ``` ### Deleting Components -Deleting a Component is the same convention as deleting an Entity. When a Component is deleted referenced to it such as to entities are automatically cleared. + Deleting a Component is the same convention as deleting an Entity. When a Component is deleted referenced to it such as to entities are automatically cleared. -```ruby -@component.delete -``` + ```ruby + @component.delete + ``` ### Accessing Components' attached Entities -Components also keep track of what Entities are using it. To access this list we do the following: + Components also keep track of what Entities are using it. To access this list we do the following: -```ruby -@component.entities # => [@entity1, @entity2, @entity3] + ```ruby + @component.entities # => [@entity1, @entity2, @entity3] # get the first entity attached. # this will throw a warning if there is more or less then # exactly one entity -@component.entity # => @entity -``` + @component.entity # => @entity + ``` ## Systems ### Creation -We can create Systems like so: + We can create Systems like so: -```ruby -FelFlame::Systems.new('Render', priority: 2) do - # Code and Logic -end -``` + ```ruby + FelECS::Systems.new('Render', priority: 2) do +# Code and Logic + end + ``` -The name we assign is how we can access the System, like so: + The name we assign is how we can access the System, like so: -```ruby -FelFlame::Systems::Render -``` -Priority determines the order Systems should be executed, this is used for `Scenes` and the `Stage`. -The lower the number, the earlier a given System will be executed. -E.g priority 1 will go first, priority 2 will go second, etcetera. + ```ruby + FelECS::Systems::Render + ``` + Priority determines the order Systems should be executed, this is used for `Scenes` and the `Stage`. + The lower the number, the earlier a given System will be executed. + E.g priority 1 will go first, priority 2 will go second, etcetera. -Both Scenes and Systems have a priority. System priority will decide the order it will be called inside of a Scene, which the Scene priority will decide the order it will be called inside of the Stage. + Both Scenes and Systems have a priority. System priority will decide the order it will be called inside of a Scene, which the Scene priority will decide the order it will be called inside of the Stage. -Often we will want to execute some logic on each Component in a given Component Manager so our code might look like this: + Often we will want to execute some logic on each Component in a given Component Manager so our code might look like this: -```ruby -FelFlame::Systems.new('Render', priority: 2) do - FelFlame::Components::Sprites.each do |component| - # do something with these components - end -end -``` + ```ruby + FelECS::Systems.new('Render', priority: 2) do + FelECS::Components::Sprites.each do |component| +# do something with these components + end + end + ``` ### Execution -After we create a System, it won't do anything on its own until we tell it to. Here is how: + After we create a System, it won't do anything on its own until we tell it to. Here is how: -```ruby -FelFlame::Systems::Render.call -``` + ```ruby + FelECS::Systems::Render.call + ``` -Sometimes you might want to manually activate a System, but the more common way to have Systems be triggered is to use Scenes and the Stage or the alternative ways of execution. + Sometimes you might want to manually activate a System, but the more common way to have Systems be triggered is to use Scenes and the Stage or the alternative ways of execution. ### Alternative Execution -Sometimes you want a System to automatically trigger when a special even happens. FelFlame can keep track of when a Component is added, removed, or when an attribute is changed and then execute Systems linked to these events. Here is how to create these links: + Sometimes you want a System to automatically trigger when a special even happens. FelECS can keep track of when a Component is added, removed, or when an attribute is changed and then execute Systems linked to these events. Here is how to create these links: -```ruby + ```ruby # When this Component is added to an Entity, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_added(@component) +FelECS::Systems::PassiveRegen.trigger_when_added(@component) # When this Component is removed from an Entity, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_removed(@component) +FelECS::Systems::PassiveRegen.trigger_when_removed(@component) # When this Component's health attribute is changed, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_is_set(@component, :health) -``` +FelECS::Systems::PassiveRegen.trigger_when_is_set(@component, :health) + ``` -If we want these triggers to happen for all Components that belong to specific Component Manager then we can do that instead: + If we want these triggers to happen for all Components that belong to specific Component Manager then we can do that instead: -```ruby + ```ruby # When a Component from this Component Manager is added to an Entity, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_added(@component_manager) +FelECS::Systems::PassiveRegen.trigger_when_added(@component_manager) # When a Component from this Component Manager is removed from an Entity, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_removed(@component_manager) +FelECS::Systems::PassiveRegen.trigger_when_removed(@component_manager) # When this Component's health attribute from this Component Manager is changed, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_is_set(@component_manager, :health) -``` +FelECS::Systems::PassiveRegen.trigger_when_is_set(@component_manager, :health) + ``` -We can create any number of these links between Systems, Components, and Component Manangers as we like, simply call the method again with our other Components and Component Managers + We can create any number of these links between Systems, Components, and Component Manangers as we like, simply call the method again with our other Components and Component Managers ### Clearing Alternative Executions -If we wish to remove these links that we created, we can do that using the follwing function in any of the following ways: + If we wish to remove these links that we created, we can do that using the follwing function in any of the following ways: -```ruby + ```ruby # clears ALL triggers with this system -FelFlame::Systems::PassiveRegen.clear_triggers + FelECS::Systems::PassiveRegen.clear_triggers # clears ALL triggers with this Component Manager -FelFlame::Systems::PassiveRegen.clear_triggers(@component) +FelECS::Systems::PassiveRegen.clear_triggers(@component) # clear the 'trigger_when_added' for this Component -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :added) +FelECS::Systems::PassiveRegen.clear_triggers(@component, :added) # clear the 'trigger_when_removed' for this Component -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :removed) +FelECS::Systems::PassiveRegen.clear_triggers(@component, :removed) # clear the 'trigger_when_is_set' for this Component specifically for the health attribute -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :is_set, :health) -``` +FelECS::Systems::PassiveRegen.clear_triggers(@component, :is_set, :health) + ``` -Likewise we can do the same with Component Managers: + Likewise we can do the same with Component Managers: -```ruby + ```ruby # clears ALL triggers with this Component -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager) +FelECS::Systems::PassiveRegen.clear_triggers(@component_manager) # clear the 'trigger_when_added' for this Component Manager -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :added) +FelECS::Systems::PassiveRegen.clear_triggers(@component_manager, :added) # clear the 'trigger_when_removed' for this Component Manager -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :removed) +FelECS::Systems::PassiveRegen.clear_triggers(@component_manager, :removed) # clear the 'trigger_when_is_set' for this Component Manager specifically for the health attribute -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :is_set, :health) -``` +FelECS::Systems::PassiveRegen.clear_triggers(@component_manager, :is_set, :health) + ``` ### Redefinition -If we wanted to change what code or logic a given System executes, we could do that with: + If we wanted to change what code or logic a given System executes, we could do that with: -```ruby -FelFlame::Systems::PassiveRegen.redefine do - # Some new logic or code -end -``` + ```ruby + FelECS::Systems::PassiveRegen.redefine do +# Some new logic or code + end + ``` ## Scenes ### Creation -Once we have all the core parts of ECS, we will want to organize our Systems. To do this we will use Scenes to group up Systems so they can quickly be enabled or disabled. Note that [Alternative Executions](#alternative-execution) will occur even if they are not part of a Scene. Here is how we make a new Scene: + Once we have all the core parts of ECS, we will want to organize our Systems. To do this we will use Scenes to group up Systems so they can quickly be enabled or disabled. Note that [Alternative Executions](#alternative-execution) will occur even if they are not part of a Scene. Here is how we make a new Scene: -```ruby -@scene = FelFlame::Scenes.new('ExampleScene', priority: 5) -``` + ```ruby + @scene = FelECS::Scenes.new('ExampleScene', priority: 5) + ``` ### Accessing -Just like other classes in FelFlame, the name we gave the Scene is how we access it: + Just like other classes in FelECS, the name we gave the Scene is how we access it: -```ruby -@scene = FelFlame::Scenes::ExampleScene -``` + ```ruby + @scene = FelECS::Scenes::ExampleScene + ``` ### Adding Systems -Adding Systems is simple. We can add as many as we want. In this example we add 3 different systems: + Adding Systems is simple. We can add as many as we want. In this example we add 3 different systems: -```ruby -FelFlame::Scenes::ExampleScene.add( - FelFlame::Systems::Render, - @system2, - @system3 -) -``` + ```ruby +FelECS::Scenes::ExampleScene.add( + FelECS::Systems::Render, + @system2, + @system3 + ) + ``` ### Removing Systems -Removing Systems works similarly: + Removing Systems works similarly: -```ruby -FelFlame::Scenes::ExampleScene.remove( - FelFlame::Systems::Render, - @system2, - @system3 -) -``` + ```ruby +FelECS::Scenes::ExampleScene.remove( + FelECS::Systems::Render, + @system2, + @system3 + ) + ``` ### Clearing -If you want to remove all Systems from a Scene here is how we do it: + If you want to remove all Systems from a Scene here is how we do it: -```ruby -@scene.clear -``` + ```ruby + @scene.clear + ``` ### Execution -To execute all Systems within a scene once we can just do: + To execute all Systems within a scene once we can just do: -```ruby -@scene.call -``` + ```ruby + @scene.call + ``` -The Scene will make sure that the systems are executed in the correct order based on their given priorities + The Scene will make sure that the systems are executed in the correct order based on their given priorities ## Stage ### Adding Scenes -Finally we have the Stage. There is only a single Stage and we do not have to create it as it exists by default. By adding a Scene to the Stage we are saying that the Scene is 'active'. To add a Scene we do the following: + Finally we have the Stage. There is only a single Stage and we do not have to create it as it exists by default. By adding a Scene to the Stage we are saying that the Scene is 'active'. To add a Scene we do the following: -```ruby -FelFlame::Stage.add FelFlame::Scene::ExampleScene -``` + ```ruby + FelECS::Stage.add FelECS::Scene::ExampleScene + ``` ### Removing Scenes -Likewise we can remove Scenes: + Likewise we can remove Scenes: -```ruby -FelFlame::Stage.remove FelFlame::Scene::ExampleScene -``` + ```ruby + FelECS::Stage.remove FelECS::Scene::ExampleScene + ``` ### Executing -On each frame of the game generally we will want to execute the Stage once. When the Stage is executed it is progressing your game 1 frame forward. The Stage will call all Scenes you added to it in the order of their priority. Here is how we do it: + On each frame of the game generally we will want to execute the Stage once. When the Stage is executed it is progressing your game 1 frame forward. The Stage will call all Scenes you added to it in the order of their priority. Here is how we do it: -```ruby -FelFlame::Stage.call -``` + ```ruby + FelECS::Stage.call + ``` ## Order ### Setting the order -To set the order you just need to call `FelFlame::Order.sort` and pass Scenes or Systems in the parameters in the order you wish for them to execute + To set the order you just need to call `FelECS::Order.sort` and pass Scenes or Systems in the parameters in the order you wish for them to execute -```ruby -FelFlame::Order.sort( - @system1, - @system2, - @system3 -) -``` + ```ruby +FelECS::Order.sort( + @system1, + @system2, + @system3 + ) + ``` -If you want some Scenes or Systems to have the same priority then just pass them as an array: + If you want some Scenes or Systems to have the same priority then just pass them as an array: -```ruby -FelFlame::Order.sort( - @scene1, - [@scene2_1, @scene2_2], - @scene3 -) -``` + ```ruby +FelECS::Order.sort( + @scene1, + [@scene2_1, @scene2_2], + @scene3 + ) + ``` ## Closing Notes -There are some methods I haven't gone over in the overview. If you want to see everything and read in more detail check out the [Documentation](https://felflame.tradam.fyi)! + There are some methods I haven't gone over in the overview. If you want to see everything and read in more detail check out the [Documentation](https://felflame.tradam.fyi)! # Contribution -Contributors are welcome! I am always looking to impove the capabilities of game development in Ruby. Feel free to open an issue to discuss a proposed changed or fix. To code a change or fix first fork the project. Next write your changes or fixes. Make sure all your changes and fixes are properly documented using Yard(I will not merge if it is not 100% documented) and make sure everything has tests written for it with Rspec(I will also not merge if it does not have 100% test coverage). Once you have your changes made then simply make a pull request. + Contributors are welcome! I am always looking to impove the capabilities of game development in Ruby. Feel free to open an issue to discuss a proposed changed or fix. To code a change or fix first fork the project. Next write your changes or fixes. Make sure all your changes and fixes are properly documented using Yard(I will not merge if it is not 100% documented) and make sure everything has tests written for it with Rspec(I will also not merge if it does not have 100% test coverage). Once you have your changes made then simply make a pull request. -If you need help writing documentation or tests feel free to ask! + If you need help writing documentation or tests feel free to ask! -If you want to contribute to development with a thanks you can always [buy me a coffee ;^)](https://ko-fi.com/tradam) + If you want to contribute to development with a thanks you can always [buy me a coffee ;^)](https://ko-fi.com/tradam) diff --git a/docs/_index.html b/docs/_index.html index 3a4b9fb..f850b17 100644 --- a/docs/_index.html +++ b/docs/_index.html @@ -75,105 +75,6 @@ - - - - - - - - - - - - - - - @@ -183,7 +84,7 @@ diff --git a/docs/class_list.html b/docs/class_list.html index 8275577..3f4c240 100644 --- a/docs/class_list.html +++ b/docs/class_list.html @@ -43,7 +43,7 @@ diff --git a/docs/file.README.html b/docs/file.README.html index f62e0db..fbe3543 100644 --- a/docs/file.README.html +++ b/docs/file.README.html @@ -57,14 +57,14 @@
-

FelFlame

+

FelECS

- + -

Maintainability -Test Coverage -Inline docs -MIT License +

Maintainability +Test Coverage +Inline docs +MIT License Ko-Fi

Check out the comprehensive documentation here!

@@ -74,7 +74,7 @@ + +
  • get the first entity attached.
  • +
  • this will throw a warning if there is more or less then
  • +
  • exactly one entity + +
  • +
  • Code and Logic
  • +
  • do something with these components + * Execution + * Alternative Execution
  • +
  • When this Component is added to an Entity, this System will be called
  • +
  • When this Component is removed from an Entity, this System will be called
  • +
  • When this Component's health attribute is changed, this System will be called
  • +
  • When a Component from this Component Manager is added to an Entity, this System will be called
  • +
  • When a Component from this Component Manager is removed from an Entity, this System will be called
  • +
  • When this Component's health attribute from this Component Manager is changed, this System will be called + * Clearing Alternative Executions
  • +
  • clears ALL triggers with this system
  • +
  • clears ALL triggers with this Component Manager
  • +
  • clear the 'trigger_when_added' for this Component
  • +
  • clear the 'trigger_when_removed' for this Component
  • +
  • clear the 'trigger_when_is_set' for this Component specifically for the health attribute
  • +
  • clears ALL triggers with this Component
  • +
  • clear the 'trigger_when_added' for this Component Manager
  • +
  • clear the 'trigger_when_removed' for this Component Manager
  • +
  • clear the 'trigger_when_is_set' for this Component Manager specifically for the health attribute + * Redefinition
  • +
  • Some new logic or code + +
    • Scenes
        @@ -142,415 +169,522 @@ -

        What is FelFlame?

        +

        What is FelECS?

        -

        FelFlame is an ECS framework for developing games in the Ruby language. FelFlame has been designed from the ground up with these three ideas in mind:

        +
        FelECS is an ECS framework for developing games in the Ruby language. FelECS has been designed from the ground up with these three ideas in mind:
         
        -
          -
        1. Engine Agnostic: FelFlame has been designed to be rendering engine agnostic as long as the target rendering engine is written in Ruby. This means that this framework can be dropped into existing rendering engines such as Ruby2D or DRGTK with little modifications.
        2. -
        3. Easily Extensible: FelFlame has been designed such that extensions to its capabilities can be easily added. Extensions such as rendering engine wrappers, premade systems, premade components, etcetera can be easily coded and then distributed as gems.
        4. -
        5. Principle of (My) Least Astonishment: I want to develop games using a language and framework I love and makes sense to me, inspired by the Philosophy of the creator of Ruby.
        6. -
        +1. **Engine Agnostic:** FelECS has been designed to be rendering engine agnostic as long as the target rendering engine is written in Ruby. This means that this framework can be dropped into existing rendering engines such as [Ruby2D](http://www.ruby2d.com) or [DRGTK](https://dragonruby.org/toolkit/game) with little modifications. +2. **Easily Extensible:** FelECS has been designed such that extensions to its capabilities can be easily added. Extensions such as rendering engine wrappers, premade systems, premade components, etcetera can be easily coded and then distributed as gems. +3. **Principle of (My) Least Astonishment:** I want to develop games using a language and framework I love and makes sense to me, inspired by the [Philosophy of the creator of Ruby](https://en.wikipedia.org/wiki/Ruby_(programming_language)#Philosophy). +

        What is ECS?

        -

        ECS is a software architectural pattern that is used in video game development. Traditionally games were programmed using an object oriented method, while ECS instead attempts to program games using a data oriented method instead.
        -ECS stands for Entity, Component, and System.

        +
        ECS is a software architectural pattern that is used in video game development. Traditionally games were programmed using an object oriented method, while ECS instead attempts to program games using a data oriented method instead.  
        +ECS stands for Entity, Component, and System.
         
        -
        +--- +

        Components

        -

        This is where the data or information of a given "object" is stored. There is no logic or code here.

        +
        This is where the data or information of a given "object" is stored. There is no logic or code here. 
        +

        Entities

        -

        Entities will contain one or more Components, but contains no logic or data otherwise

        +
        Entities will contain one or more Components, but contains no logic or data otherwise
        +

        Systems

        -

        Systems are where all the logic or code is kept. There is no data stored in here.

        +
        Systems are where all the logic or code is kept. There is no data stored in here.
         
        -
        +--- -

        By using this pattern it allows programmers to easily control what an "object" or entity can do and how much data it needs to have. It avoids the issue of inhertance as no inhertance is ever required in this system. If you need a certain entity to have a certain functionality you just add the relevant component to it, and the systems that automatically go over specific components will give your entitiy the desired functionality.

        +By using this pattern it allows programmers to easily control what an "object" or entity can do and how much data it needs to have. It avoids the issue of inhertance as no inhertance is ever required in this system. If you need a certain entity to have a certain functionality you just add the relevant component to it, and the systems that automatically go over specific components will give your entitiy the desired functionality. -

        "But your framework also has Scenes, Stage, and Order, what is that about?"

        +**"But your framework also has `Scenes`, `Stage`, and `Order`, what is that about?"** -
        +--- +

        Scenes

        -

        Scenes are simply a collection or subset of Systems. This allows for an easy way to activate and deactivate Systems.

        +
        Scenes are simply a collection or subset of Systems. This allows for an easy way to activate and deactivate Systems.
        +

        Stage

        -

        The Stage is Scenes which are activated. This means any Scenes on the Stage are executed each frame, while the rest of the Systems are not.

        +
        The Stage is Scenes which are activated. This means any Scenes on the Stage are executed each frame, while the rest of the Systems are not.
        +

        Order

        -

        Order is a helper class which can set the priority of Scenes and Systems.

        +
        Order is a helper class which can set the priority of Scenes and Systems.
         
        -
        +--- +

        Usage

        -

        There are 2 ways of using FelFlame. You can either include it as a gem in your project if your game engine supports this. The other option is to download the single file export of FelFlame and then require_relative this file in your project. The single file export takes all the ruby code in the various files and concatenates them into a single file so it is more portable and easy to add.

        +
        There are 2 ways of using FelECS. You can either `include` it as a gem in your project if your game engine supports this. The other option is to download the single file export of FelECS and then `require_relative` this file in your project. The single file export takes all the ruby code in the various files and concatenates them into a single file so it is more portable and easy to add.
         
        -

        To use the gem method you can do the following: install the gem using gem install felflame or using bundler bundle add felflame and then require it in your project like so: require 'felflame'.

        +To use the gem method you can do the following: install the gem using `gem install felflame` or using bundler `bundle add felflame` and then require it in your project like so: `require 'felflame'`. -

        To use the single file export method you simply download the felflame.rb file from the releases page on Github and add it to your source folder and add a require relative 'felflame.rb' line or wherever you have placed the file to use it.

        +To use the single file export method you simply download the felflame.rb file from the [releases page on Github](https://github.com/realtradam/FelECS/releases) and add it to your source folder and add a `require relative 'felflame.rb'` line or wherever you have placed the file to use it. +

        Entities

        Creation

        -

        Entities are essentially "objects" in the game world. To create a new Entity we do the following:

        - -
        @entity = FelFlame::Entities.new
        -
        +
        Entities are essentially "objects" in the game world. To create a new Entity we do the following:
         
        -

        or if we want to add (any number of)components to it when creating it:

        +```ruby +@entity = FelECS::Entities.new +``` +or if we want to add (any number of)components to it when creating it: -
        @entity = FelFlame::Entites.new(
        -  FelFlame::Components::Health.new,
        -  @component,
        -  FelFlame::Components::EnemyTeam.first
        -)
        +```ruby
         
        +

        @entity = FelECS::Entites.new( + FelECS::Components::Health.new, + @component, + FelECS::Components::EnemyTeam.first + ) + ```

        +

        Accessing

        -

        Oftentimes you will not be accessing an Entity this way. Later we will shows you a more common way of accessing entities. -If you need to you can access Entities using the Entities module:

        +
        Oftentimes you will not be accessing an Entity this way. Later we will shows you a more common way of accessing entities.
        +If you need to you can access Entities using the `Entities` module:
         
        -
        @entity = FelFlame::Entities[2]
        -@entity = FelFlame::Entities.first
        -@entity = FelFlame::Entities.each # you can iterate over all entities this way. Any valid array method can be used
        -
        +```ruby +@entity = FelECS::Entities[2] +@entity = FelECS::Entities.first +@entity = FelECS::Entities.each # you can iterate over all entities this way. Any valid array method can be used +``` +

        Adding and Removing Components

        -

        We can still add or remove Components from an Entity after it has been created. Here is how:

        +
        We can still add or remove Components from an Entity after it has been created. Here is how:
         
        -
        @entity.add @component
        -@entity.remove @component
        +```ruby
        +@entity.add @component
        +@entity.remove @component
        +```
         

        Accessing Entities' Attached Components

        -

        This is the most common way of accessing an Entity

        +
        This is the most common way of accessing an Entity
         
        -

        When Components are added to Entities, they can be accessed from the Entity. By using a Component Manager as a key we can access an array of all components created from that Component Manager that are attached to an entity:

        +When Components are added to Entities, they can be accessed from the Entity. By using a Component Manager as a key we can access an array of all components created from that Component Manager that are attached to an entity: -
        @entity.components[@component_manager] # => [@component1, @component2, @component3]
        -
        +```ruby +@entity.components[@component_manager] # => [@component1, @component2, @component3] +``` +

        Deletion

        -

        To have all Components from an Entity removed and the Entity deleted we do the following:

        +
        To have all Components from an Entity **removed** and the Entity deleted we do the following:
         
        -

        NOTE: The components will not be deleted. They are simply removed from the entity and then the entity is destroyed. You must handle component deletion yourself as for example singleton components need to removed instead of deleted.

        +NOTE: The components will **not be deleted**. They are simply **removed** from the entity and then the entity is destroyed. You must handle component deletion yourself as for example singleton components need to removed instead of deleted. -
        @entity.delete
        +```ruby
        +@entity.delete
        +```
         

        Components

        Creating a Component Manager

        -

        Components are where all the data is stored. The data is stored in variables or accessors in each component. -These accessors and their defaults are configured when a component manager is created, like so:

        +
        Components are where all the data is stored. The data is stored in variables or accessors in each component.
        +These accessors and their defaults are configured when a component manager is created, like so:
         
        -
        @component_manager = FelFlame::Components.new('Stats', :armour, hp: 100)
        -
        +```ruby +@component_manager = FelECS::Components.new('Stats', :armour, hp: 100) +``` -

        In this example we created a component manager called "Stats". +In this example we created a component manager called "Stats". The name given to component managers must follow the same rules for naming constants in ruby for a reason you will shortly see. The parameters following are all creating the attributes we can set. We can set any number of parameters we wish, in this example we define two. -The :armour parameter is being created without a default, it will equal to nil when a new component is created, while hp will be equal to 100 when a component is created. -When defining attributes symbols should be used.

        +The `:armour` parameter is being created without a default, it will equal to `nil` when a new component is created, while `hp` will be equal to 100 when a component is created. +When defining attributes symbols should be used. +

        Creating a Component from a Component Manager

        -

        Now that we have a component manager we can make components from it like so:

        +
        Now that we have a component manager we can make components from it like so:
         
        -
        @component = FelFlame::Components::Stats.new
        -
        +```ruby +@component = FelECS::Components::Stats.new +``` -

        Or we can even override the defaults when creating the component:

        +Or we can even override the defaults when creating the component: -
        @component = FelFlame::Components::Stats.new(armour: 'steel')
        +```ruby
        +@component = FelECS::Components::Stats.new(armour: 'steel')
        +```
         

        Accessing

        -

        You can access components using any array method.

        +
        You can access components using any array method.
         
        -
        @component = FelFlame::Components::Stats[2]
        -@component = FelFlame::Components::Stats.first
        -@component = FelFlame::Components::Stats.each # you can use iterators this way
        -
        +```ruby +@component = FelECS::Components::Stats[2] +@component = FelECS::Components::Stats.first +@component = FelECS::Components::Stats.each # you can use iterators this way +``` +

        Accessing Attributes and Changing Them

        -

        There are a few different ways we can read or change the attributes of a component depending on what our needs are. -Here are the ways to edit attrubutes, followed by the ways to read them.

        - -
        @component.armour = 'Mythril'
        -@component.update_attrs(armour: 'Leather', hp: 95)
        +
        There are a few different ways we can read or change the attributes of a component depending on what our needs are.
        +Here are the ways to edit attrubutes, followed by the ways to read them.
        +```ruby
        +@component.armour = 'Mythril'
        +@component.update_attrs(armour: 'Leather', hp: 95)
        +```
        +```ruby
        +@component.hp # => 95
        +@component.to_h # => {armour: 'Leather', hp: 95}
        +```
         
        -
        @component.hp # => 95
        -@component.to_h # => {armour: 'Leather', hp: 95}
        -
        -

        Deleting Components

        -

        Deleting a Component is the same convention as deleting an Entity. When a Component is deleted referenced to it such as to entities are automatically cleared.

        +
        Deleting a Component is the same convention as deleting an Entity. When a Component is deleted referenced to it such as to entities are automatically cleared.
         
        -
        @component.delete
        +```ruby
        +@component.delete
        +```
         

        Accessing Components' attached Entities

        -

        Components also keep track of what Entities are using it. To access this list we do the following:

        +
        Components also keep track of what Entities are using it. To access this list we do the following:
         
        -
        @component.entities # => [@entity1, @entity2, @entity3]
        -
        -# get the first entity attached.
        -# this will throw a warning if there is more or less then
        -# exactly one entity
        -@component.entity # => @entity
        -
        +```ruby +@component.entities # => [@entity1, @entity2, @entity3] +
        + +

        get the first entity attached.

        + +

        this will throw a warning if there is more or less then

        + +

        exactly one entity

        + +
        @component.entity # => @entity
        +```
        +

        Systems

        Creation

        -

        We can create Systems like so:

        +
        We can create Systems like so:
         
        -
        FelFlame::Systems.new('Render', priority: 2) do
        -  # Code and Logic
        -end
        +```ruby
        +FelECS::Systems.new('Render', priority: 2) do
         
        -

        The name we assign is how we can access the System, like so:

        +

        Code and Logic

        -
        FelFlame::Systems::Render
        -
        +
        end
        +```
        +
        +The name we assign is how we can access the System, like so:
         
        -

        Priority determines the order Systems should be executed, this is used for Scenes and the Stage. +```ruby +FelECS::Systems::Render +``` +Priority determines the order Systems should be executed, this is used for `Scenes` and the `Stage`. The lower the number, the earlier a given System will be executed. -E.g priority 1 will go first, priority 2 will go second, etcetera.

        +E.g priority 1 will go first, priority 2 will go second, etcetera. -

        Both Scenes and Systems have a priority. System priority will decide the order it will be called inside of a Scene, which the Scene priority will decide the order it will be called inside of the Stage.

        +Both Scenes and Systems have a priority. System priority will decide the order it will be called inside of a Scene, which the Scene priority will decide the order it will be called inside of the Stage. -

        Often we will want to execute some logic on each Component in a given Component Manager so our code might look like this:

        +Often we will want to execute some logic on each Component in a given Component Manager so our code might look like this: -
        FelFlame::Systems.new('Render', priority: 2) do
        -  FelFlame::Components::Sprites.each do |component|
        -    # do something with these components
        -  end
        -end
        +```ruby
        +FelECS::Systems.new('Render', priority: 2) do
        +FelECS::Components::Sprites.each do |component|
        +
        + +

        do something with these components

        + +
        end
        +end
        +```
         

        Execution

        -

        After we create a System, it won't do anything on its own until we tell it to. Here is how:

        +
        After we create a System, it won't do anything on its own until we tell it to. Here is how:
         
        -
        FelFlame::Systems::Render.call
        -
        +```ruby +FelECS::Systems::Render.call +``` -

        Sometimes you might want to manually activate a System, but the more common way to have Systems be triggered is to use Scenes and the Stage or the alternative ways of execution.

        +Sometimes you might want to manually activate a System, but the more common way to have Systems be triggered is to use Scenes and the Stage or the alternative ways of execution. +

        Alternative Execution

        -

        Sometimes you want a System to automatically trigger when a special even happens. FelFlame can keep track of when a Component is added, removed, or when an attribute is changed and then execute Systems linked to these events. Here is how to create these links:

        +
        Sometimes you want a System to automatically trigger when a special even happens. FelECS can keep track of when a Component is added, removed, or when an attribute is changed and then execute Systems linked to these events. Here is how to create these links:
         
        -
        # When this Component is added to an Entity, this System will be called
        -FelFlame::Systems::PassiveRegen.trigger_when_added(@component)
        +```ruby
        +
        -# When this Component is removed from an Entity, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_removed(@component) +

        When this Component is added to an Entity, this System will be called

        -# When this Component's health attribute is changed, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_is_set(@component, :health) -
        +

        FelECS::Systems::PassiveRegen.trigger_when_added(@component)

        -

        If we want these triggers to happen for all Components that belong to specific Component Manager then we can do that instead:

        +

        When this Component is removed from an Entity, this System will be called

        -
        # When a Component from this Component Manager is added to an Entity, this System will be called
        -FelFlame::Systems::PassiveRegen.trigger_when_added(@component_manager)
        +

        FelECS::Systems::PassiveRegen.trigger_when_removed(@component)

        -# When a Component from this Component Manager is removed from an Entity, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_removed(@component_manager) +

        When this Component's health attribute is changed, this System will be called

        -# When this Component's health attribute from this Component Manager is changed, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_is_set(@component_manager, :health) +

        FelECS::Systems::PassiveRegen.trigger_when_is_set(@component, :health) + ```

        + +
        If we want these triggers to happen for all Components that belong to specific Component Manager then we can do that instead:
        +
        +```ruby
         
        -

        We can create any number of these links between Systems, Components, and Component Manangers as we like, simply call the method again with our other Components and Component Managers

        +

        When a Component from this Component Manager is added to an Entity, this System will be called

        -

        Clearing Alternative Executions

        +

        FelECS::Systems::PassiveRegen.trigger_when_added(@component_manager)

        + +

        When a Component from this Component Manager is removed from an Entity, this System will be called

        + +

        FelECS::Systems::PassiveRegen.trigger_when_removed(@component_manager)

        -

        If we wish to remove these links that we created, we can do that using the follwing function in any of the following ways:

        +

        When this Component's health attribute from this Component Manager is changed, this System will be called

        -
        # clears ALL triggers with this system
        -FelFlame::Systems::PassiveRegen.clear_triggers
        +

        FelECS::Systems::PassiveRegen.trigger_when_is_set(@component_manager, :health) + ```

        -# clears ALL triggers with this Component Manager -FelFlame::Systems::PassiveRegen.clear_triggers(@component) +
        We can create any number of these links between Systems, Components, and Component Manangers as we like, simply call the method again with our other Components and Component Managers
        +
        + +

        Clearing Alternative Executions

        -# clear the 'trigger_when_added' for this Component -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :added) +
        If we wish to remove these links that we created, we can do that using the follwing function in any of the following ways:
        +
        +```ruby
        +
        -# clear the 'trigger_when_removed' for this Component -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :removed) +

        clears ALL triggers with this system

        -# clear the 'trigger_when_is_set' for this Component specifically for the health attribute -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :is_set, :health) +
        FelECS::Systems::PassiveRegen.clear_triggers
         
        -

        Likewise we can do the same with Component Managers:

        +

        clears ALL triggers with this Component Manager

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component)

        + +

        clear the 'trigger_when_added' for this Component

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component, :added)

        + +

        clear the 'trigger_when_removed' for this Component

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component, :removed)

        -
        # clears ALL triggers with this Component
        -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager) 
        +

        clear the 'trigger_when_is_set' for this Component specifically for the health attribute

        -# clear the 'trigger_when_added' for this Component Manager -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :added) +

        FelECS::Systems::PassiveRegen.clear_triggers(@component, :is_set, :health) + ```

        -# clear the 'trigger_when_removed' for this Component Manager -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :removed) +
        Likewise we can do the same with Component Managers:
         
        -# clear the 'trigger_when_is_set' for this Component Manager specifically for the health attribute
        -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :is_set, :health) 
        +```ruby
         
        +

        clears ALL triggers with this Component

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component_manager)

        + +

        clear the 'trigger_when_added' for this Component Manager

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component_manager, :added)

        + +

        clear the 'trigger_when_removed' for this Component Manager

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component_manager, :removed)

        + +

        clear the 'trigger_when_is_set' for this Component Manager specifically for the health attribute

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component_manager, :is_set, :health) + ```

        +

        Redefinition

        -

        If we wanted to change what code or logic a given System executes, we could do that with:

        +
        If we wanted to change what code or logic a given System executes, we could do that with:
         
        -
        FelFlame::Systems::PassiveRegen.redefine do
        -  # Some new logic or code
        -end
        +```ruby
        +FelECS::Systems::PassiveRegen.redefine do
        +
        + +

        Some new logic or code

        + +
        end
        +```
         

        Scenes

        Creation

        -

        Once we have all the core parts of ECS, we will want to organize our Systems. To do this we will use Scenes to group up Systems so they can quickly be enabled or disabled. Note that Alternative Executions will occur even if they are not part of a Scene. Here is how we make a new Scene:

        +
        Once we have all the core parts of ECS, we will want to organize our Systems. To do this we will use Scenes to group up Systems so they can quickly be enabled or disabled. Note that [Alternative Executions](#alternative-execution) will occur even if they are not part of a Scene. Here is how we make a new Scene:
         
        -
        @scene = FelFlame::Scenes.new('ExampleScene', priority: 5)
        +```ruby
        +@scene = FelECS::Scenes.new('ExampleScene', priority: 5)
        +```
         

        Accessing

        -

        Just like other classes in FelFlame, the name we gave the Scene is how we access it:

        +
        Just like other classes in FelECS, the name we gave the Scene is how we access it:
         
        -
        @scene = FelFlame::Scenes::ExampleScene
        +```ruby
        +@scene = FelECS::Scenes::ExampleScene
        +```
         

        Adding Systems

        -

        Adding Systems is simple. We can add as many as we want. In this example we add 3 different systems:

        +
        Adding Systems is simple. We can add as many as we want. In this example we add 3 different systems:
         
        -
        FelFlame::Scenes::ExampleScene.add(
        -  FelFlame::Systems::Render,
        -  @system2,
        -  @system3
        -)
        +```ruby
         
        +

        FelECS::Scenes::ExampleScene.add( + FelECS::Systems::Render, + @system2, + @system3 + ) + ```

        +

        Removing Systems

        -

        Removing Systems works similarly:

        +
        Removing Systems works similarly:
         
        -
        FelFlame::Scenes::ExampleScene.remove(
        -  FelFlame::Systems::Render,
        -  @system2,
        -  @system3
        -)
        +```ruby
         
        +

        FelECS::Scenes::ExampleScene.remove( + FelECS::Systems::Render, + @system2, + @system3 + ) + ```

        +

        Clearing

        -

        If you want to remove all Systems from a Scene here is how we do it:

        +
        If you want to remove all Systems from a Scene here is how we do it:
         
        -
        @scene.clear
        +```ruby
        +@scene.clear
        +```
         

        Execution

        -

        To execute all Systems within a scene once we can just do:

        +
        To execute all Systems within a scene once we can just do:
         
        -
        @scene.call
        -
        +```ruby +@scene.call +``` -

        The Scene will make sure that the systems are executed in the correct order based on their given priorities

        +The Scene will make sure that the systems are executed in the correct order based on their given priorities +

        Stage

        Adding Scenes

        -

        Finally we have the Stage. There is only a single Stage and we do not have to create it as it exists by default. By adding a Scene to the Stage we are saying that the Scene is 'active'. To add a Scene we do the following:

        +
        Finally we have the Stage. There is only a single Stage and we do not have to create it as it exists by default. By adding a Scene to the Stage we are saying that the Scene is 'active'. To add a Scene we do the following:
         
        -
        FelFlame::Stage.add FelFlame::Scene::ExampleScene
        +```ruby
        +FelECS::Stage.add FelECS::Scene::ExampleScene
        +```
         

        Removing Scenes

        -

        Likewise we can remove Scenes:

        +
        Likewise we can remove Scenes:
         
        -
        FelFlame::Stage.remove FelFlame::Scene::ExampleScene
        +```ruby
        +FelECS::Stage.remove FelECS::Scene::ExampleScene
        +```
         

        Executing

        -

        On each frame of the game generally we will want to execute the Stage once. When the Stage is executed it is progressing your game 1 frame forward. The Stage will call all Scenes you added to it in the order of their priority. Here is how we do it:

        +
        On each frame of the game generally we will want to execute the Stage once. When the Stage is executed it is progressing your game 1 frame forward. The Stage will call all Scenes you added to it in the order of their priority. Here is how we do it:
         
        -
        FelFlame::Stage.call
        +```ruby
        +FelECS::Stage.call
        +```
         

        Order

        Setting the order

        -

        To set the order you just need to call FelFlame::Order.sort and pass Scenes or Systems in the parameters in the order you wish for them to execute

        +
        To set the order you just need to call `FelECS::Order.sort` and pass Scenes or Systems in the parameters in the order you wish for them to execute
         
        -
        FelFlame::Order.sort(
        -  @system1,
        -  @system2,
        -  @system3
        -)
        +```ruby
         
        -

        If you want some Scenes or Systems to have the same priority then just pass them as an array:

        +

        FelECS::Order.sort( + @system1, + @system2, + @system3 + ) + ```

        -
        FelFlame::Order.sort(
        -  @scene1,
        -  [@scene2_1, @scene2_2],
        -  @scene3
        -) 
        +
        If you want some Scenes or Systems to have the same priority then just pass them as an array:
        +
        +```ruby
         
        +

        FelECS::Order.sort( + @scene1, + [@scene2_1, @scene2_2], + @scene3 + ) + ```

        +

        Closing Notes

        -

        There are some methods I haven't gone over in the overview. If you want to see everything and read in more detail check out the Documentation!

        +
        There are some methods I haven't gone over in the overview. If you want to see everything and read in more detail check out the [Documentation](https://felflame.tradam.fyi)!
        +

        Contribution

        -

        Contributors are welcome! I am always looking to impove the capabilities of game development in Ruby. Feel free to open an issue to discuss a proposed changed or fix. To code a change or fix first fork the project. Next write your changes or fixes. Make sure all your changes and fixes are properly documented using Yard(I will not merge if it is not 100% documented) and make sure everything has tests written for it with Rspec(I will also not merge if it does not have 100% test coverage). Once you have your changes made then simply make a pull request.

        +
        Contributors are welcome! I am always looking to impove the capabilities of game development in Ruby. Feel free to open an issue to discuss a proposed changed or fix. To code a change or fix first fork the project. Next write your changes or fixes. Make sure all your changes and fixes are properly documented using Yard(I will not merge if it is not 100% documented) and make sure everything has tests written for it with Rspec(I will also not merge if it does not have 100% test coverage). Once you have your changes made then simply make a pull request.  
         
        -

        If you need help writing documentation or tests feel free to ask!

        +If you need help writing documentation or tests feel free to ask! -

        If you want to contribute to development with a thanks you can always buy me a coffee ;^)

        +If you want to contribute to development with a thanks you can always [buy me a coffee ;^)](https://ko-fi.com/tradam) +
  • diff --git a/docs/index.html b/docs/index.html index 83af15a..e81dd9d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -57,14 +57,14 @@
    -

    FelFlame

    +

    FelECS

    - + -

    Maintainability -Test Coverage -Inline docs -MIT License +

    Maintainability +Test Coverage +Inline docs +MIT License Ko-Fi

    Check out the comprehensive documentation here!

    @@ -74,7 +74,7 @@ + +
  • get the first entity attached.
  • +
  • this will throw a warning if there is more or less then
  • +
  • exactly one entity + +
  • +
  • Code and Logic
  • +
  • do something with these components + * Execution + * Alternative Execution
  • +
  • When this Component is added to an Entity, this System will be called
  • +
  • When this Component is removed from an Entity, this System will be called
  • +
  • When this Component's health attribute is changed, this System will be called
  • +
  • When a Component from this Component Manager is added to an Entity, this System will be called
  • +
  • When a Component from this Component Manager is removed from an Entity, this System will be called
  • +
  • When this Component's health attribute from this Component Manager is changed, this System will be called + * Clearing Alternative Executions
  • +
  • clears ALL triggers with this system
  • +
  • clears ALL triggers with this Component Manager
  • +
  • clear the 'trigger_when_added' for this Component
  • +
  • clear the 'trigger_when_removed' for this Component
  • +
  • clear the 'trigger_when_is_set' for this Component specifically for the health attribute
  • +
  • clears ALL triggers with this Component
  • +
  • clear the 'trigger_when_added' for this Component Manager
  • +
  • clear the 'trigger_when_removed' for this Component Manager
  • +
  • clear the 'trigger_when_is_set' for this Component Manager specifically for the health attribute + * Redefinition
  • +
  • Some new logic or code + +
    • Scenes
        @@ -142,415 +169,522 @@ -

        What is FelFlame?

        +

        What is FelECS?

        -

        FelFlame is an ECS framework for developing games in the Ruby language. FelFlame has been designed from the ground up with these three ideas in mind:

        +
        FelECS is an ECS framework for developing games in the Ruby language. FelECS has been designed from the ground up with these three ideas in mind:
         
        -
          -
        1. Engine Agnostic: FelFlame has been designed to be rendering engine agnostic as long as the target rendering engine is written in Ruby. This means that this framework can be dropped into existing rendering engines such as Ruby2D or DRGTK with little modifications.
        2. -
        3. Easily Extensible: FelFlame has been designed such that extensions to its capabilities can be easily added. Extensions such as rendering engine wrappers, premade systems, premade components, etcetera can be easily coded and then distributed as gems.
        4. -
        5. Principle of (My) Least Astonishment: I want to develop games using a language and framework I love and makes sense to me, inspired by the Philosophy of the creator of Ruby.
        6. -
        +1. **Engine Agnostic:** FelECS has been designed to be rendering engine agnostic as long as the target rendering engine is written in Ruby. This means that this framework can be dropped into existing rendering engines such as [Ruby2D](http://www.ruby2d.com) or [DRGTK](https://dragonruby.org/toolkit/game) with little modifications. +2. **Easily Extensible:** FelECS has been designed such that extensions to its capabilities can be easily added. Extensions such as rendering engine wrappers, premade systems, premade components, etcetera can be easily coded and then distributed as gems. +3. **Principle of (My) Least Astonishment:** I want to develop games using a language and framework I love and makes sense to me, inspired by the [Philosophy of the creator of Ruby](https://en.wikipedia.org/wiki/Ruby_(programming_language)#Philosophy). +

        What is ECS?

        -

        ECS is a software architectural pattern that is used in video game development. Traditionally games were programmed using an object oriented method, while ECS instead attempts to program games using a data oriented method instead.
        -ECS stands for Entity, Component, and System.

        +
        ECS is a software architectural pattern that is used in video game development. Traditionally games were programmed using an object oriented method, while ECS instead attempts to program games using a data oriented method instead.  
        +ECS stands for Entity, Component, and System.
         
        -
        +--- +

        Components

        -

        This is where the data or information of a given "object" is stored. There is no logic or code here.

        +
        This is where the data or information of a given "object" is stored. There is no logic or code here. 
        +

        Entities

        -

        Entities will contain one or more Components, but contains no logic or data otherwise

        +
        Entities will contain one or more Components, but contains no logic or data otherwise
        +

        Systems

        -

        Systems are where all the logic or code is kept. There is no data stored in here.

        +
        Systems are where all the logic or code is kept. There is no data stored in here.
         
        -
        +--- -

        By using this pattern it allows programmers to easily control what an "object" or entity can do and how much data it needs to have. It avoids the issue of inhertance as no inhertance is ever required in this system. If you need a certain entity to have a certain functionality you just add the relevant component to it, and the systems that automatically go over specific components will give your entitiy the desired functionality.

        +By using this pattern it allows programmers to easily control what an "object" or entity can do and how much data it needs to have. It avoids the issue of inhertance as no inhertance is ever required in this system. If you need a certain entity to have a certain functionality you just add the relevant component to it, and the systems that automatically go over specific components will give your entitiy the desired functionality. -

        "But your framework also has Scenes, Stage, and Order, what is that about?"

        +**"But your framework also has `Scenes`, `Stage`, and `Order`, what is that about?"** -
        +--- +

        Scenes

        -

        Scenes are simply a collection or subset of Systems. This allows for an easy way to activate and deactivate Systems.

        +
        Scenes are simply a collection or subset of Systems. This allows for an easy way to activate and deactivate Systems.
        +

        Stage

        -

        The Stage is Scenes which are activated. This means any Scenes on the Stage are executed each frame, while the rest of the Systems are not.

        +
        The Stage is Scenes which are activated. This means any Scenes on the Stage are executed each frame, while the rest of the Systems are not.
        +

        Order

        -

        Order is a helper class which can set the priority of Scenes and Systems.

        +
        Order is a helper class which can set the priority of Scenes and Systems.
         
        -
        +--- +

        Usage

        -

        There are 2 ways of using FelFlame. You can either include it as a gem in your project if your game engine supports this. The other option is to download the single file export of FelFlame and then require_relative this file in your project. The single file export takes all the ruby code in the various files and concatenates them into a single file so it is more portable and easy to add.

        +
        There are 2 ways of using FelECS. You can either `include` it as a gem in your project if your game engine supports this. The other option is to download the single file export of FelECS and then `require_relative` this file in your project. The single file export takes all the ruby code in the various files and concatenates them into a single file so it is more portable and easy to add.
         
        -

        To use the gem method you can do the following: install the gem using gem install felflame or using bundler bundle add felflame and then require it in your project like so: require 'felflame'.

        +To use the gem method you can do the following: install the gem using `gem install felflame` or using bundler `bundle add felflame` and then require it in your project like so: `require 'felflame'`. -

        To use the single file export method you simply download the felflame.rb file from the releases page on Github and add it to your source folder and add a require relative 'felflame.rb' line or wherever you have placed the file to use it.

        +To use the single file export method you simply download the felflame.rb file from the [releases page on Github](https://github.com/realtradam/FelECS/releases) and add it to your source folder and add a `require relative 'felflame.rb'` line or wherever you have placed the file to use it. +

        Entities

        Creation

        -

        Entities are essentially "objects" in the game world. To create a new Entity we do the following:

        - -
        @entity = FelFlame::Entities.new
        -
        +
        Entities are essentially "objects" in the game world. To create a new Entity we do the following:
         
        -

        or if we want to add (any number of)components to it when creating it:

        +```ruby +@entity = FelECS::Entities.new +``` +or if we want to add (any number of)components to it when creating it: -
        @entity = FelFlame::Entites.new(
        -  FelFlame::Components::Health.new,
        -  @component,
        -  FelFlame::Components::EnemyTeam.first
        -)
        +```ruby
         
        +

        @entity = FelECS::Entites.new( + FelECS::Components::Health.new, + @component, + FelECS::Components::EnemyTeam.first + ) + ```

        +

        Accessing

        -

        Oftentimes you will not be accessing an Entity this way. Later we will shows you a more common way of accessing entities. -If you need to you can access Entities using the Entities module:

        +
        Oftentimes you will not be accessing an Entity this way. Later we will shows you a more common way of accessing entities.
        +If you need to you can access Entities using the `Entities` module:
         
        -
        @entity = FelFlame::Entities[2]
        -@entity = FelFlame::Entities.first
        -@entity = FelFlame::Entities.each # you can iterate over all entities this way. Any valid array method can be used
        -
        +```ruby +@entity = FelECS::Entities[2] +@entity = FelECS::Entities.first +@entity = FelECS::Entities.each # you can iterate over all entities this way. Any valid array method can be used +``` +

        Adding and Removing Components

        -

        We can still add or remove Components from an Entity after it has been created. Here is how:

        +
        We can still add or remove Components from an Entity after it has been created. Here is how:
         
        -
        @entity.add @component
        -@entity.remove @component
        +```ruby
        +@entity.add @component
        +@entity.remove @component
        +```
         

        Accessing Entities' Attached Components

        -

        This is the most common way of accessing an Entity

        +
        This is the most common way of accessing an Entity
         
        -

        When Components are added to Entities, they can be accessed from the Entity. By using a Component Manager as a key we can access an array of all components created from that Component Manager that are attached to an entity:

        +When Components are added to Entities, they can be accessed from the Entity. By using a Component Manager as a key we can access an array of all components created from that Component Manager that are attached to an entity: -
        @entity.components[@component_manager] # => [@component1, @component2, @component3]
        -
        +```ruby +@entity.components[@component_manager] # => [@component1, @component2, @component3] +``` +

        Deletion

        -

        To have all Components from an Entity removed and the Entity deleted we do the following:

        +
        To have all Components from an Entity **removed** and the Entity deleted we do the following:
         
        -

        NOTE: The components will not be deleted. They are simply removed from the entity and then the entity is destroyed. You must handle component deletion yourself as for example singleton components need to removed instead of deleted.

        +NOTE: The components will **not be deleted**. They are simply **removed** from the entity and then the entity is destroyed. You must handle component deletion yourself as for example singleton components need to removed instead of deleted. -
        @entity.delete
        +```ruby
        +@entity.delete
        +```
         

        Components

        Creating a Component Manager

        -

        Components are where all the data is stored. The data is stored in variables or accessors in each component. -These accessors and their defaults are configured when a component manager is created, like so:

        +
        Components are where all the data is stored. The data is stored in variables or accessors in each component.
        +These accessors and their defaults are configured when a component manager is created, like so:
         
        -
        @component_manager = FelFlame::Components.new('Stats', :armour, hp: 100)
        -
        +```ruby +@component_manager = FelECS::Components.new('Stats', :armour, hp: 100) +``` -

        In this example we created a component manager called "Stats". +In this example we created a component manager called "Stats". The name given to component managers must follow the same rules for naming constants in ruby for a reason you will shortly see. The parameters following are all creating the attributes we can set. We can set any number of parameters we wish, in this example we define two. -The :armour parameter is being created without a default, it will equal to nil when a new component is created, while hp will be equal to 100 when a component is created. -When defining attributes symbols should be used.

        +The `:armour` parameter is being created without a default, it will equal to `nil` when a new component is created, while `hp` will be equal to 100 when a component is created. +When defining attributes symbols should be used. +

        Creating a Component from a Component Manager

        -

        Now that we have a component manager we can make components from it like so:

        +
        Now that we have a component manager we can make components from it like so:
         
        -
        @component = FelFlame::Components::Stats.new
        -
        +```ruby +@component = FelECS::Components::Stats.new +``` -

        Or we can even override the defaults when creating the component:

        +Or we can even override the defaults when creating the component: -
        @component = FelFlame::Components::Stats.new(armour: 'steel')
        +```ruby
        +@component = FelECS::Components::Stats.new(armour: 'steel')
        +```
         

        Accessing

        -

        You can access components using any array method.

        +
        You can access components using any array method.
         
        -
        @component = FelFlame::Components::Stats[2]
        -@component = FelFlame::Components::Stats.first
        -@component = FelFlame::Components::Stats.each # you can use iterators this way
        -
        +```ruby +@component = FelECS::Components::Stats[2] +@component = FelECS::Components::Stats.first +@component = FelECS::Components::Stats.each # you can use iterators this way +``` +

        Accessing Attributes and Changing Them

        -

        There are a few different ways we can read or change the attributes of a component depending on what our needs are. -Here are the ways to edit attrubutes, followed by the ways to read them.

        - -
        @component.armour = 'Mythril'
        -@component.update_attrs(armour: 'Leather', hp: 95)
        +
        There are a few different ways we can read or change the attributes of a component depending on what our needs are.
        +Here are the ways to edit attrubutes, followed by the ways to read them.
        +```ruby
        +@component.armour = 'Mythril'
        +@component.update_attrs(armour: 'Leather', hp: 95)
        +```
        +```ruby
        +@component.hp # => 95
        +@component.to_h # => {armour: 'Leather', hp: 95}
        +```
         
        -
        @component.hp # => 95
        -@component.to_h # => {armour: 'Leather', hp: 95}
        -
        -

        Deleting Components

        -

        Deleting a Component is the same convention as deleting an Entity. When a Component is deleted referenced to it such as to entities are automatically cleared.

        +
        Deleting a Component is the same convention as deleting an Entity. When a Component is deleted referenced to it such as to entities are automatically cleared.
         
        -
        @component.delete
        +```ruby
        +@component.delete
        +```
         

        Accessing Components' attached Entities

        -

        Components also keep track of what Entities are using it. To access this list we do the following:

        +
        Components also keep track of what Entities are using it. To access this list we do the following:
         
        -
        @component.entities # => [@entity1, @entity2, @entity3]
        -
        -# get the first entity attached.
        -# this will throw a warning if there is more or less then
        -# exactly one entity
        -@component.entity # => @entity
        -
        +```ruby +@component.entities # => [@entity1, @entity2, @entity3] +
        + +

        get the first entity attached.

        + +

        this will throw a warning if there is more or less then

        + +

        exactly one entity

        + +
        @component.entity # => @entity
        +```
        +

        Systems

        Creation

        -

        We can create Systems like so:

        +
        We can create Systems like so:
         
        -
        FelFlame::Systems.new('Render', priority: 2) do
        -  # Code and Logic
        -end
        +```ruby
        +FelECS::Systems.new('Render', priority: 2) do
         
        -

        The name we assign is how we can access the System, like so:

        +

        Code and Logic

        -
        FelFlame::Systems::Render
        -
        +
        end
        +```
        +
        +The name we assign is how we can access the System, like so:
         
        -

        Priority determines the order Systems should be executed, this is used for Scenes and the Stage. +```ruby +FelECS::Systems::Render +``` +Priority determines the order Systems should be executed, this is used for `Scenes` and the `Stage`. The lower the number, the earlier a given System will be executed. -E.g priority 1 will go first, priority 2 will go second, etcetera.

        +E.g priority 1 will go first, priority 2 will go second, etcetera. -

        Both Scenes and Systems have a priority. System priority will decide the order it will be called inside of a Scene, which the Scene priority will decide the order it will be called inside of the Stage.

        +Both Scenes and Systems have a priority. System priority will decide the order it will be called inside of a Scene, which the Scene priority will decide the order it will be called inside of the Stage. -

        Often we will want to execute some logic on each Component in a given Component Manager so our code might look like this:

        +Often we will want to execute some logic on each Component in a given Component Manager so our code might look like this: -
        FelFlame::Systems.new('Render', priority: 2) do
        -  FelFlame::Components::Sprites.each do |component|
        -    # do something with these components
        -  end
        -end
        +```ruby
        +FelECS::Systems.new('Render', priority: 2) do
        +FelECS::Components::Sprites.each do |component|
        +
        + +

        do something with these components

        + +
        end
        +end
        +```
         

        Execution

        -

        After we create a System, it won't do anything on its own until we tell it to. Here is how:

        +
        After we create a System, it won't do anything on its own until we tell it to. Here is how:
         
        -
        FelFlame::Systems::Render.call
        -
        +```ruby +FelECS::Systems::Render.call +``` -

        Sometimes you might want to manually activate a System, but the more common way to have Systems be triggered is to use Scenes and the Stage or the alternative ways of execution.

        +Sometimes you might want to manually activate a System, but the more common way to have Systems be triggered is to use Scenes and the Stage or the alternative ways of execution. +

        Alternative Execution

        -

        Sometimes you want a System to automatically trigger when a special even happens. FelFlame can keep track of when a Component is added, removed, or when an attribute is changed and then execute Systems linked to these events. Here is how to create these links:

        +
        Sometimes you want a System to automatically trigger when a special even happens. FelECS can keep track of when a Component is added, removed, or when an attribute is changed and then execute Systems linked to these events. Here is how to create these links:
         
        -
        # When this Component is added to an Entity, this System will be called
        -FelFlame::Systems::PassiveRegen.trigger_when_added(@component)
        +```ruby
        +
        -# When this Component is removed from an Entity, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_removed(@component) +

        When this Component is added to an Entity, this System will be called

        -# When this Component's health attribute is changed, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_is_set(@component, :health) -
        +

        FelECS::Systems::PassiveRegen.trigger_when_added(@component)

        -

        If we want these triggers to happen for all Components that belong to specific Component Manager then we can do that instead:

        +

        When this Component is removed from an Entity, this System will be called

        -
        # When a Component from this Component Manager is added to an Entity, this System will be called
        -FelFlame::Systems::PassiveRegen.trigger_when_added(@component_manager)
        +

        FelECS::Systems::PassiveRegen.trigger_when_removed(@component)

        -# When a Component from this Component Manager is removed from an Entity, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_removed(@component_manager) +

        When this Component's health attribute is changed, this System will be called

        -# When this Component's health attribute from this Component Manager is changed, this System will be called -FelFlame::Systems::PassiveRegen.trigger_when_is_set(@component_manager, :health) +

        FelECS::Systems::PassiveRegen.trigger_when_is_set(@component, :health) + ```

        + +
        If we want these triggers to happen for all Components that belong to specific Component Manager then we can do that instead:
        +
        +```ruby
         
        -

        We can create any number of these links between Systems, Components, and Component Manangers as we like, simply call the method again with our other Components and Component Managers

        +

        When a Component from this Component Manager is added to an Entity, this System will be called

        -

        Clearing Alternative Executions

        +

        FelECS::Systems::PassiveRegen.trigger_when_added(@component_manager)

        + +

        When a Component from this Component Manager is removed from an Entity, this System will be called

        + +

        FelECS::Systems::PassiveRegen.trigger_when_removed(@component_manager)

        -

        If we wish to remove these links that we created, we can do that using the follwing function in any of the following ways:

        +

        When this Component's health attribute from this Component Manager is changed, this System will be called

        -
        # clears ALL triggers with this system
        -FelFlame::Systems::PassiveRegen.clear_triggers
        +

        FelECS::Systems::PassiveRegen.trigger_when_is_set(@component_manager, :health) + ```

        -# clears ALL triggers with this Component Manager -FelFlame::Systems::PassiveRegen.clear_triggers(@component) +
        We can create any number of these links between Systems, Components, and Component Manangers as we like, simply call the method again with our other Components and Component Managers
        +
        + +

        Clearing Alternative Executions

        -# clear the 'trigger_when_added' for this Component -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :added) +
        If we wish to remove these links that we created, we can do that using the follwing function in any of the following ways:
        +
        +```ruby
        +
        -# clear the 'trigger_when_removed' for this Component -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :removed) +

        clears ALL triggers with this system

        -# clear the 'trigger_when_is_set' for this Component specifically for the health attribute -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :is_set, :health) +
        FelECS::Systems::PassiveRegen.clear_triggers
         
        -

        Likewise we can do the same with Component Managers:

        +

        clears ALL triggers with this Component Manager

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component)

        + +

        clear the 'trigger_when_added' for this Component

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component, :added)

        + +

        clear the 'trigger_when_removed' for this Component

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component, :removed)

        -
        # clears ALL triggers with this Component
        -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager) 
        +

        clear the 'trigger_when_is_set' for this Component specifically for the health attribute

        -# clear the 'trigger_when_added' for this Component Manager -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :added) +

        FelECS::Systems::PassiveRegen.clear_triggers(@component, :is_set, :health) + ```

        -# clear the 'trigger_when_removed' for this Component Manager -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :removed) +
        Likewise we can do the same with Component Managers:
         
        -# clear the 'trigger_when_is_set' for this Component Manager specifically for the health attribute
        -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :is_set, :health) 
        +```ruby
         
        +

        clears ALL triggers with this Component

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component_manager)

        + +

        clear the 'trigger_when_added' for this Component Manager

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component_manager, :added)

        + +

        clear the 'trigger_when_removed' for this Component Manager

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component_manager, :removed)

        + +

        clear the 'trigger_when_is_set' for this Component Manager specifically for the health attribute

        + +

        FelECS::Systems::PassiveRegen.clear_triggers(@component_manager, :is_set, :health) + ```

        +

        Redefinition

        -

        If we wanted to change what code or logic a given System executes, we could do that with:

        +
        If we wanted to change what code or logic a given System executes, we could do that with:
         
        -
        FelFlame::Systems::PassiveRegen.redefine do
        -  # Some new logic or code
        -end
        +```ruby
        +FelECS::Systems::PassiveRegen.redefine do
        +
        + +

        Some new logic or code

        + +
        end
        +```
         

        Scenes

        Creation

        -

        Once we have all the core parts of ECS, we will want to organize our Systems. To do this we will use Scenes to group up Systems so they can quickly be enabled or disabled. Note that Alternative Executions will occur even if they are not part of a Scene. Here is how we make a new Scene:

        +
        Once we have all the core parts of ECS, we will want to organize our Systems. To do this we will use Scenes to group up Systems so they can quickly be enabled or disabled. Note that [Alternative Executions](#alternative-execution) will occur even if they are not part of a Scene. Here is how we make a new Scene:
         
        -
        @scene = FelFlame::Scenes.new('ExampleScene', priority: 5)
        +```ruby
        +@scene = FelECS::Scenes.new('ExampleScene', priority: 5)
        +```
         

        Accessing

        -

        Just like other classes in FelFlame, the name we gave the Scene is how we access it:

        +
        Just like other classes in FelECS, the name we gave the Scene is how we access it:
         
        -
        @scene = FelFlame::Scenes::ExampleScene
        +```ruby
        +@scene = FelECS::Scenes::ExampleScene
        +```
         

        Adding Systems

        -

        Adding Systems is simple. We can add as many as we want. In this example we add 3 different systems:

        +
        Adding Systems is simple. We can add as many as we want. In this example we add 3 different systems:
         
        -
        FelFlame::Scenes::ExampleScene.add(
        -  FelFlame::Systems::Render,
        -  @system2,
        -  @system3
        -)
        +```ruby
         
        +

        FelECS::Scenes::ExampleScene.add( + FelECS::Systems::Render, + @system2, + @system3 + ) + ```

        +

        Removing Systems

        -

        Removing Systems works similarly:

        +
        Removing Systems works similarly:
         
        -
        FelFlame::Scenes::ExampleScene.remove(
        -  FelFlame::Systems::Render,
        -  @system2,
        -  @system3
        -)
        +```ruby
         
        +

        FelECS::Scenes::ExampleScene.remove( + FelECS::Systems::Render, + @system2, + @system3 + ) + ```

        +

        Clearing

        -

        If you want to remove all Systems from a Scene here is how we do it:

        +
        If you want to remove all Systems from a Scene here is how we do it:
         
        -
        @scene.clear
        +```ruby
        +@scene.clear
        +```
         

        Execution

        -

        To execute all Systems within a scene once we can just do:

        +
        To execute all Systems within a scene once we can just do:
         
        -
        @scene.call
        -
        +```ruby +@scene.call +``` -

        The Scene will make sure that the systems are executed in the correct order based on their given priorities

        +The Scene will make sure that the systems are executed in the correct order based on their given priorities +

        Stage

        Adding Scenes

        -

        Finally we have the Stage. There is only a single Stage and we do not have to create it as it exists by default. By adding a Scene to the Stage we are saying that the Scene is 'active'. To add a Scene we do the following:

        +
        Finally we have the Stage. There is only a single Stage and we do not have to create it as it exists by default. By adding a Scene to the Stage we are saying that the Scene is 'active'. To add a Scene we do the following:
         
        -
        FelFlame::Stage.add FelFlame::Scene::ExampleScene
        +```ruby
        +FelECS::Stage.add FelECS::Scene::ExampleScene
        +```
         

        Removing Scenes

        -

        Likewise we can remove Scenes:

        +
        Likewise we can remove Scenes:
         
        -
        FelFlame::Stage.remove FelFlame::Scene::ExampleScene
        +```ruby
        +FelECS::Stage.remove FelECS::Scene::ExampleScene
        +```
         

        Executing

        -

        On each frame of the game generally we will want to execute the Stage once. When the Stage is executed it is progressing your game 1 frame forward. The Stage will call all Scenes you added to it in the order of their priority. Here is how we do it:

        +
        On each frame of the game generally we will want to execute the Stage once. When the Stage is executed it is progressing your game 1 frame forward. The Stage will call all Scenes you added to it in the order of their priority. Here is how we do it:
         
        -
        FelFlame::Stage.call
        +```ruby
        +FelECS::Stage.call
        +```
         

        Order

        Setting the order

        -

        To set the order you just need to call FelFlame::Order.sort and pass Scenes or Systems in the parameters in the order you wish for them to execute

        +
        To set the order you just need to call `FelECS::Order.sort` and pass Scenes or Systems in the parameters in the order you wish for them to execute
         
        -
        FelFlame::Order.sort(
        -  @system1,
        -  @system2,
        -  @system3
        -)
        +```ruby
         
        -

        If you want some Scenes or Systems to have the same priority then just pass them as an array:

        +

        FelECS::Order.sort( + @system1, + @system2, + @system3 + ) + ```

        -
        FelFlame::Order.sort(
        -  @scene1,
        -  [@scene2_1, @scene2_2],
        -  @scene3
        -) 
        +
        If you want some Scenes or Systems to have the same priority then just pass them as an array:
        +
        +```ruby
         
        +

        FelECS::Order.sort( + @scene1, + [@scene2_1, @scene2_2], + @scene3 + ) + ```

        +

        Closing Notes

        -

        There are some methods I haven't gone over in the overview. If you want to see everything and read in more detail check out the Documentation!

        +
        There are some methods I haven't gone over in the overview. If you want to see everything and read in more detail check out the [Documentation](https://felflame.tradam.fyi)!
        +

        Contribution

        -

        Contributors are welcome! I am always looking to impove the capabilities of game development in Ruby. Feel free to open an issue to discuss a proposed changed or fix. To code a change or fix first fork the project. Next write your changes or fixes. Make sure all your changes and fixes are properly documented using Yard(I will not merge if it is not 100% documented) and make sure everything has tests written for it with Rspec(I will also not merge if it does not have 100% test coverage). Once you have your changes made then simply make a pull request.

        +
        Contributors are welcome! I am always looking to impove the capabilities of game development in Ruby. Feel free to open an issue to discuss a proposed changed or fix. To code a change or fix first fork the project. Next write your changes or fixes. Make sure all your changes and fixes are properly documented using Yard(I will not merge if it is not 100% documented) and make sure everything has tests written for it with Rspec(I will also not merge if it does not have 100% test coverage). Once you have your changes made then simply make a pull request.  
         
        -

        If you need help writing documentation or tests feel free to ask!

        +If you need help writing documentation or tests feel free to ask! -

        If you want to contribute to development with a thanks you can always buy me a coffee ;^)

        +If you want to contribute to development with a thanks you can always [buy me a coffee ;^)](https://ko-fi.com/tradam) +
  • diff --git a/docs/method_list.html b/docs/method_list.html index 5f38f92..48eea1f 100644 --- a/docs/method_list.html +++ b/docs/method_list.html @@ -44,374 +44,6 @@
    diff --git a/docs/top-level-namespace.html b/docs/top-level-namespace.html index cc16af8..6ab8ca4 100644 --- a/docs/top-level-namespace.html +++ b/docs/top-level-namespace.html @@ -78,43 +78,6 @@
    -

    Defined Under Namespace

    -

    - - - Modules: FelFlame, Felflame - - - - -

    - - -

    - Constant Summary - collapse -

    - -
    - -
    FF = -
    -
    - -

    An alias for FelFlame

    - - -
    -
    -
    - - -
    -
    -
    FelFlame
    - -
    - @@ -127,7 +90,7 @@
    diff --git a/felecs.gemspec b/felecs.gemspec new file mode 100644 index 0000000..6fe379a --- /dev/null +++ b/felecs.gemspec @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require_relative 'lib/felecs/version' + +Gem::Specification.new do |spec| + spec.name = 'felecs' + spec.version = FelECS::VERSION + spec.authors = ['Tradam'] + spec.email = ['felflame@tradam.dev'] + + spec.summary = 'The Engine Agnostic ECS Ruby Framework' + # spec.description = "TODO: Write a longer description or delete this line." + spec.homepage = 'https://felflame.tradam.fyi' + spec.license = 'MIT' + spec.required_ruby_version = '>= 2.4.0' + + # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" + + spec.metadata['homepage_uri'] = spec.homepage + spec.metadata['source_code_uri'] = 'https://github.com/realtradam/FelFlame' + # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." + + # Specify which files should be added to the gem when it is released. + # The `git ls-files -z` loads the files in the RubyGem that have been added into git. + spec.files = Dir.chdir(File.expand_path(__dir__)) do + `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features|deprecated|codeclimate|logos)/}) } + end + spec.bindir = 'exe' + spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } + spec.require_paths = ['lib'] + + # Uncomment to register a new dependency of your gem + # spec.add_dependency "example-gem", "~> 1.0" + spec.add_development_dependency 'minitest-reporters', '~> 1.4', '>= 1.4.3' # , require: false + spec.add_development_dependency 'redcarpet', '~> 3.5', '>= 3.5.1' # , require: false + spec.add_development_dependency 'rspec', '~> 3.10' + spec.add_development_dependency 'rubocop', '~> 1.7' + spec.add_development_dependency 'simplecov', '~> 0.21.2' # , require: false + spec.add_development_dependency 'simplecov-console', '~> 0.9.1' + spec.add_development_dependency 'simplecov_json_formatter', '~> 0.1.3' # , require: false + spec.add_development_dependency 'yard', '~> 0.9.26' # , require: false + + # For more information and examples about making a new gem, checkout our + # guide at: https://bundler.io/guides/creating_gem.html +end diff --git a/felflame.gemspec b/felflame.gemspec deleted file mode 100644 index 6f26e6f..0000000 --- a/felflame.gemspec +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true - -require_relative 'lib/felflame/version' - -Gem::Specification.new do |spec| - spec.name = 'felflame' - spec.version = Felflame::VERSION - spec.authors = ['Tradam'] - spec.email = ['felflame@tradam.dev'] - - spec.summary = 'The Engine Agnostic ECS Ruby Framework' - # spec.description = "TODO: Write a longer description or delete this line." - spec.homepage = 'https://felflame.tradam.fyi' - spec.license = 'MIT' - spec.required_ruby_version = '>= 2.4.0' - - # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" - - spec.metadata['homepage_uri'] = spec.homepage - spec.metadata['source_code_uri'] = 'https://github.com/realtradam/FelFlame' - # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." - - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path(__dir__)) do - `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features|deprecated|codeclimate|logos)/}) } - end - spec.bindir = 'exe' - spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } - spec.require_paths = ['lib'] - - # Uncomment to register a new dependency of your gem - # spec.add_dependency "example-gem", "~> 1.0" - spec.add_development_dependency 'minitest-reporters', '~> 1.4', '>= 1.4.3' # , require: false - spec.add_development_dependency 'redcarpet', '~> 3.5', '>= 3.5.1' # , require: false - spec.add_development_dependency 'rspec', '~> 3.10' - spec.add_development_dependency 'rubocop', '~> 1.7' - spec.add_development_dependency 'simplecov', '~> 0.21.2' # , require: false - spec.add_development_dependency 'simplecov-console', '~> 0.9.1' - spec.add_development_dependency 'simplecov_json_formatter', '~> 0.1.3' # , require: false - spec.add_development_dependency 'yard', '~> 0.9.26' # , require: false - - # For more information and examples about making a new gem, checkout our - # guide at: https://bundler.io/guides/creating_gem.html -end diff --git a/lib/felecs.rb b/lib/felecs.rb new file mode 100644 index 0000000..e00c9d2 --- /dev/null +++ b/lib/felecs.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require_relative 'felecs/entity_manager' +require_relative 'felecs/component_manager' +require_relative 'felecs/system_manager' +require_relative 'felecs/scene_manager' +require_relative 'felecs/stage_manager' +require_relative 'felecs/order' + +require_relative 'felecs/version' + +# The FelECS namespace where all its functionality resides under. +module FelECS + class << self + # :nocov: + + # An alias for {FelECS::Stage.call}. It executes a single frame in the game. + def call + FelECS::Stage.call + end + # :nocov: + end + + # Creates and manages Entities. Entities are just collections of Components. + # You can use array methods directly on this class to access Entities. + class Entities; end + + # Creates component managers and allows accessing them them under the {FelECS::Components} namespace as Constants. + # You can use array methods directly on this class to access Component Managers. + # + # To see how component managers are used please look at the {FelECS::ComponentManager} documentation. + module Components; end + + # Creates and 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 {FelECS::Systems} namespace as Constants. + # You can use array methods directly on this class to access Systems. + 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 {FelECS::Scenes} namespace as Constants. + 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 + + # Sets the priority of a list of Systems or Scenes for you in the order you pass them to this class. + module Order; end +end + +# An alias for {FelECS} +FECS = FelECS + +# An alias for {FelECS::Entities} +FECS::Ent = FelECS::Entities + +# An alias for {FelECS::Components} +FECS::Cmp = FelECS::Components + +# An alias for {FelECS::Systems} +FECS::Sys = FelECS::Systems + +# An alias for {FelECS::Scenes} +FECS::Scn = FelECS::Scenes + +# An alias for {FelECS::Stage} +FECS::Stg = FelECS::Stage + +# An alias for {FelECS:: +FECS::Odr = FelECS::Order diff --git a/lib/felecs/component_manager.rb b/lib/felecs/component_manager.rb new file mode 100644 index 0000000..36916cb --- /dev/null +++ b/lib/felecs/component_manager.rb @@ -0,0 +1,277 @@ +# frozen_string_literal: true + +module FelECS + module Components + @component_map = [] + class << self + # Creates a new {FelECS::ComponentManager component manager}. + # + # @example + # # Here color is set to default to red + # # while max and current are nil until set. + # # When you make a new component using this component manager + # # these are the values and accessors it will have. + # FelECS::Component.new('Health', :max, :current, color: 'red') + # + # @param component_name [String] Name of your new component manager. Must be stylized in the format of constants in Ruby + # @param attrs [:Symbols] New components made with this manager will include these symbols as accessors, the values of these accessors will default to nil + # @param attrs_with_defaults [Keyword: DefaultValue] New components made with this manager will include these keywords as accessors, their defaults set to the values given to the keywords + # @return [ComponentManager] + def new(component_name, *attrs, **attrs_with_defaults) + if FelECS::Components.const_defined?(component_name) + raise(NameError.new, "Component Manager '#{component_name}' is already defined") + end + + const_set(component_name, Class.new(FelECS::ComponentManager) {}) + update_const_cache + + attrs.each do |attr| + if FelECS::Components.const_get(component_name).method_defined?(attr.to_s) || FelECS::Components.const_get(component_name).method_defined?("#{attr}=") + raise NameError, "The attribute name \"#{attr}\" is already a method" + end + + FelECS::Components.const_get(component_name).attr_accessor attr + end + attrs_with_defaults.each do |attr, _default| + attrs_with_defaults[attr] = _default.dup + FelECS::Components.const_get(component_name).attr_reader attr + FelECS::Components.const_get(component_name).define_method("#{attr}=") do |value| + attr_changed_trigger_systems(attr) unless value.equal? send(attr) + instance_variable_set("@#{attr}", value) + end + end + FelECS::Components.const_get(component_name).define_method(:set_defaults) do + attrs_with_defaults.each do |attr, default| + instance_variable_set("@#{attr}", default.dup) + end + end + FelECS::Components.const_get(component_name) + end + + # Stores the components managers in {FelECS::Components}. This + # is needed because calling `FelECS::Components.constants` + # will not let you iterate over the value of the constants + # but will instead give you an array of symbols. This caches + # the convertion of those symbols to the actual value of the + # constants + # @!visibility private + def const_cache + @const_cache || update_const_cache + end + + # Updates the array that stores the constants. + # Used internally by FelECS + # @!visibility private + def update_const_cache + @const_cache = constants.map do |constant| + const_get constant + end + end + + # Forwards undefined methods to the array of constants + # if the array can handle the request. Otherwise tells + # the programmer their code errored + # @!visibility private + def respond_to_missing?(method, *) + if const_cache.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 const_cache.respond_to? method + const_cache.send(method, *args, **kwargs, &block) + else + super + end + end + end + end + + # Component Managers are what is used to create individual components which can be attached to entities. + # 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 +@component.var = 5+), or by using the {#to_h} and {#update_attrs} methods instead. + class ComponentManager + # 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. + # @!visibility private + attr_writer :addition_triggers, :removal_triggers, :attr_triggers + + # Stores references to systems that should be triggered when a + # component from this manager is added. + # Do not edit this array as it is managed by FelECS automatically. + # @return [Array] + def addition_triggers + @addition_triggers ||= [] + end + + # Stores references to systems that should be triggered when a + # component from this manager is removed. + # Do not edit this array as it is managed by FelECS automatically. + # @return [Array] + def removal_triggers + @removal_triggers ||= [] + end + + # Stores references to systems that should be triggered when an + # attribute from this manager is changed. + # Do not edit this hash as it is managed by FelECS automatically. + # @return [Hash>] + def attr_triggers + @attr_triggers ||= {} + end + + # Creates a new component and sets the values of the attributes given to it. If an attritbute is not passed then it will remain as the default. + # @param attrs [Keyword: Value] You can pass any number of Keyword-Value pairs + # @return [Component] + def initialize(**attrs) + # Prepare the object + # (this is a function created with metaprogramming + # in FelECS::Components) + set_defaults + + # Fill params + attrs.each do |key, value| + send "#{key}=", value + end + + # Save Component + self.class.push 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 _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 _data.respond_to? method + _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. + # @!visibility private + attr_writer :addition_triggers, :removal_triggers, :attr_triggers + + # Stores references to systems that should be triggered when this + # component is added to an enitity. + # Do not edit this array as it is managed by FelECS automatically. + # @return [Array] + def addition_triggers + @addition_triggers ||= [] + end + + # Stores references to systems that should be triggered when this + # component is removed from an enitity. + # Do not edit this array as it is managed by FelECS automatically. + # @return [Array] + def removal_triggers + @removal_triggers ||= [] + end + + # Stores references to systems that should be triggered when an + # attribute from this component changed. + # Do not edit this hash as it is managed by FelECS automatically. + # @return [Hash] + def attr_triggers + @attr_triggers ||= {} + end + + # @return [Array] Array of all Components that belong to a given component manager + # @!visibility private + def _data + @data ||= [] + end + end + + # Entities that have this component + # @return [Array] + def entities + @entities ||= [] + 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 + end + + # Update attribute values using a hash or keywords. + # @return [Hash] Hash of updated attributes + def update_attrs(**opts) + opts.each do |key, value| + send "#{key}=", value + end + end + + # Execute systems that have been added to execute on variable change + # @return [Boolean] +true+ + # @!visibility private + def attr_changed_trigger_systems(attr) + systems_to_execute = self.class.attr_triggers[attr] + systems_to_execute = [] if systems_to_execute.nil? + + systems_to_execute |= attr_triggers[attr] unless attr_triggers[attr].nil? + + 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. + # @return [Boolean] +true+. + def delete + addition_triggers.each do |system| + system.clear_triggers component_or_manager: self + end + entities.reverse_each do |entity| + entity.remove self + end + self.class._data.delete self + instance_variables.each do |var| + instance_variable_set(var, nil) + end + true + end + + # @return [Hash] A hash, where all the keys are attributes storing their respective values. + def to_h + return_hash = instance_variables.each_with_object({}) do |key, final| + final[key.to_s.delete_prefix('@').to_sym] = instance_variable_get(key) + end + return_hash.delete(:attr_triggers) + return_hash + end + + # Export all data into a JSON String, which could then later be loaded or saved to a file + # TODO: This function is not yet complete + # @return [String] a JSON formatted String + # def to_json + # # should return a json or hash of all data in this component + # end + end +end diff --git a/lib/felecs/entity_manager.rb b/lib/felecs/entity_manager.rb new file mode 100644 index 0000000..a457ed2 --- /dev/null +++ b/lib/felecs/entity_manager.rb @@ -0,0 +1,160 @@ +# frozen_string_literal: true + +module FelECS + class Entities + # 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) + # Add each component + add(*components) + self.class._data.push 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. + # @return [Hash>] + 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. Array notation is conventional for better readablility. + # @example + # @entity.component[@component_manager] # array notation(the standard) + # @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? + FelECS::Entities.component_redirect.entity = self + FelECS::Entities.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 + end + + # Removes this Entity from the list and purges all references to this Entity from other Components, as well as its data. + # @return [Boolean] +true+ + def delete + components.each do |_component_manager, component_array| + component_array.reverse_each do |component| + component.entities.delete(self) + end + end + FelECS::Entities._data.delete self + @components = {} + true + end + + # Add any number components to the Entity. + # @param components_to_add [Component] Any number of components created from any component manager + # @return [Boolean] +true+ + def add(*components_to_add) + components_to_add.each do |component| + if components[component.class].nil? + components[component.class] = [component] + component.entities.push self + check_systems component, :addition_triggers + elsif !components[component.class].include? component + components[component.class].push component + component.entities.push self + check_systems component, :addition_triggers + end + end + true + end + + # triggers every system associated with this component's trigger + # @return [Boolean] +true+ + # @!visibility private + def check_systems(component, trigger_type) + component_calls = component.class.send(trigger_type) + component.send(trigger_type).each do |system| + component_calls |= [system] + end + component_calls.sort_by(&:priority).reverse.each(&:call) + true + end + + # Remove a component from the Entity + # @param components_to_remove [Component] A component created from any component manager + # @return [Boolean] +true+ + def remove(*components_to_remove) + components_to_remove.each do |component| + check_systems component, :removal_triggers if component.entities.include? self + component.entities.delete self + components[component.class].delete component + components.delete component.class if components[component.class].empty? + end + true + end + + # Export all data into a JSON String which can then be saved into a file + # TODO: This function is not yet complete + # @return [String] A JSON formatted String + # def to_json() end + + class << self + # Makes component managers behave like arrays with additional + # methods for managing the array + # @!visibility private + def respond_to_missing?(method, *) + if _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 _data.respond_to? method + _data.send(method, *args, **kwargs, &block) + else + super + end + end + + # Fancy method redirection for when the `component` method is called + # in an Entity + # WARNING: This method will not correctly work with multithreading + # @!visibility private + def component_redirect + if @component_redirect + else + @component_redirect = Object.new + @component_redirect.instance_variable_set(:@entity, nil) + @component_redirect.define_singleton_method(:entity) do + instance_variable_get(:@entity) + end + @component_redirect.define_singleton_method(:entity=) do |value| + instance_variable_set(:@entity, value) + end + @component_redirect.define_singleton_method(:[]) do |component_manager| + entity.component(component_manager) + end + end + @component_redirect + end + + # @return [Array] Array of all Entities that exist + # @!visibility private + def _data + @data ||= [] + end + + # Creates a new entity using the data from a JSON string + # TODO: This function is not yet complete + # @param json_string [String] A string that was exported originally using the {FelECS::Entities#to_json to_json} function + # @param opts [Keywords] What values(its {FelECS::Entities#id ID} or the {FelECS::ComponentManager#id component IDs}) should be overwritten TODO: this might change + # def from_json(json_string, **opts) end + end + end +end diff --git a/lib/felecs/order.rb b/lib/felecs/order.rb new file mode 100644 index 0000000..3e9b656 --- /dev/null +++ b/lib/felecs/order.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module FelECS + module Order + # Sets the priority of all items passed into this method + # according to the order they were passed. + # If an array is one of the elements then it will give all + # of those elements in the array the same priority. + # @param sortables [(Systems and Array) or (Scenes and Array)] + # @return [Boolean] +true+. + def self.sort(*sortables) + sortables.each_with_index do |sorted, index| + if sorted.respond_to? :priority + sorted.priority = index + else + sorted.each do |item| + item.priority = index + end + end + end + true + end + end +end diff --git a/lib/felecs/scene_manager.rb b/lib/felecs/scene_manager.rb new file mode 100644 index 0000000..af61b9c --- /dev/null +++ b/lib/felecs/scene_manager.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module FelECS + class Scenes + # Allows overwriting the storage of systems, such as for clearing. + # This method should generally only need to be used internally and + # not by a game developer/ + # @!visibility private + attr_writer :systems + + # How early this Scene should be executed in a list of Scenes + attr_accessor :priority + + def priority=(priority) + @priority = priority + FelECS::Stage.scenes = FelECS::Stage.scenes.sort_by(&:priority) + priority + end + + # Create a new Scene using the name given + # @param name [String] String format must follow requirements of a constant + def initialize(name, priority: 0) + self.priority = priority + FelECS::Scenes.const_set(name, self) + end + + # The list of Systems this Scene contains + # @return [Array] + def systems + @systems ||= [] + end + + # Execute all systems in this Scene, in the order of their priority + # @return [Boolean] +true+ + def call + systems.each(&:call) + true + end + + # Adds any number of Systems to this Scene + # @return [Boolean] +true+ + def add(*systems_to_add) + self.systems |= systems_to_add + self.systems = systems.sort_by(&:priority) + systems_to_add.each do |system| + system.scenes |= [self] + end + true + end + + # Removes any number of Systems from this Scene + # @return [Boolean] +true+ + def remove(*systems_to_remove) + self.systems -= systems_to_remove + true + end + + # Removes all Systems from this Scene + # @return [Boolean] +true+ + def clear + systems.each do |system| + system.scenes.delete self + end + systems.clear + # FelECS::Stage.update_systems_list if FelECS::Stage.scenes.include? self + true + end + end +end diff --git a/lib/felecs/stage_manager.rb b/lib/felecs/stage_manager.rb new file mode 100644 index 0000000..b2a5b7c --- /dev/null +++ b/lib/felecs/stage_manager.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module FelECS + module Stage + class << self + # Allows clearing of scenes and systems. + # Used internally by FelECS and shouldn't need to be ever used by developers + # @!visibility private + attr_writer :scenes + + # Add any number of Scenes to the Stage + # @return [Boolean] +true+ + def add(*scenes_to_add) + self.scenes |= scenes_to_add + self.scenes = scenes.sort_by(&:priority) + true + end + + # Remove any number of Scenes from the Stage + # @return [Boolean] +true+ + def remove(*scenes_to_remove) + self.scenes -= scenes_to_remove + true + end + + # Clears all Scenes that were added to the Stage + # @return [Boolean] +true+ + def clear + self.scenes.clear + true + end + + # Executes one frame of the game. This executes all the Scenes added to the Stage in order of their priority. + # @return [Boolean] +true+ + def call + self.scenes.each(&:call) + true + end + + # Contains all the Scenes added to the Stage + # @return [Array] + def scenes + @scenes ||= [] + end + end + end +end diff --git a/lib/felecs/system_manager.rb b/lib/felecs/system_manager.rb new file mode 100644 index 0000000..6cd260b --- /dev/null +++ b/lib/felecs/system_manager.rb @@ -0,0 +1,258 @@ +# frozen_string_literal: true + +module FelECS + class Systems + # How early this System should be executed in a list of Systems + attr_accessor :priority + + # The Constant name assigned to this System + + # 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. + # @!visibility private + attr_writer :addition_triggers, :removal_triggers, :attr_triggers + + # Stores all the scenes this system is a part of. + attr_writer :scenes + + def scenes + @scenes ||= [] + end + + def priority=(priority) + @priority = priority + scenes.each do |scene| + scene.systems = scene.systems.sort_by(&:priority) + end + end + + # Stores references to components or their managers that trigger + # this component when a component or component from that manager + # is added to an entity. + # Do not edit this hash as it is managed by FelECS automatically. + # @return [Array] + def addition_triggers + @addition_triggers ||= [] + end + + # Stores references to components or their managers that trigger + # this component when a component or component from that manager + # is removed from an entity. + # Do not edit this hash as it is managed by FelECS automatically. + # @return [Array] + def removal_triggers + @removal_triggers ||= [] + end + + # Stores references to systems that should be triggered when an + # attribute from this manager is changed + # Do not edit this hash as it is managed by FelECS automatically. + # @return [Hash>] + def attr_triggers + @attr_triggers ||= {} + end + + class << self + # Stores the systems in {FelECS::Components}. This + # is needed because calling `FelECS::Components.constants` + # will not let you iterate over the value of the constants + # but will instead give you an array of symbols. This caches + # the convertion of those symbols to the actual value of the + # constants + def const_cache + @const_cache || update_const_cache + end + + # Updates the array that stores the constants. + # Used internally by FelECS + # @!visibility private + def update_const_cache + @const_cache = constants.map do |constant| + const_get constant + end + end + + # Forwards undefined methods to the array of constants + # if the array can handle the request. Otherwise tells + # the programmer their code errored + # @!visibility private + def respond_to_missing?(method, *) + if const_cache.respond_to? method + true + else + super + end + end + + # Makes system module behave like arrays with additional + # methods for managing the array + # @!visibility private + def method_missing(method, *args, **kwargs, &block) + if const_cache.respond_to? method + const_cache.send(method, *args, **kwargs, &block) + else + super + end + end + end + + # Creates a new System which can be accessed as a constant under the namespace {FelECS::Systems}. + # The name given is what constant the system is assigned to + # + # @example + # FelECS::Systems.new('PassiveHeal', priority: -2) do + # FelECS::Components::Health.each do |component| + # component.hp += 5 + # end + # end + # # 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) + FelECS::Systems.const_set(name, self) + FelECS::Systems.update_const_cache + @priority = priority + @block = block + @scenes = [] + end + + # Manually execute the system a single time + def call + @block.call + 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. This function is fairly flexible so it can accept a few different inputs + # For addition and removal triggers, you can optionally pass in a component, or a manager to clear specifically + # the relevant triggers for that one component or manager. If you do not pass a component or manager then it will + # clear triggers for all components and managers. + # For attr_triggers + # @example + # # To clear all triggers that execute this system when a component is added: + # FelECS::Systems::ExampleSystem.clear_triggers :addition_triggers + # # Same as above but for when a component is removed instead + # FelECS::Systems::ExampleSystem.clear_triggers :removal_triggers + # # Same as above but for when a component has a certain attribute changed + # FelECS::Systems::ExampleSystem.clear_triggers :attr_triggers + # + # # Clear a trigger from a specific component + # FelECS::Systems::ExampleSystem.clear_triggers :addition_triggers, FelECS::Component::ExampleComponent[0] + # # Clear a trigger from a specific component manager + # FelECS::Systems::ExampleSystem.clear_triggers :addition_triggers, FelECS::Component::ExampleComponent + # + # # Clear the trigger that executes a system when the ':example_attr' is changes + # FelECS::Systems::ExampleSystem.clear_triggers :attr_triggers, :example_attr + # @param trigger_types [:Symbols] One or more of the following trigger types: +:addition_triggers+, +:removal_triggers+, or +:attr_triggers+. If attr_triggers is used then you may pass attributes you wish to be cleared as symbols in this parameter as well + # @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 = %i[addition_triggers removal_triggers attr_triggers] if trigger_types.empty? + + if trigger_types.include? :attr_triggers + if (trigger_types - %i[addition_triggers + removal_triggers + attr_triggers]).empty? + + if component_or_manager.nil? + # remove all attrs + attr_triggers.each do |cmp_or_mgr, attrs| + attrs.each do |attr| + next if cmp_or_mgr.attr_triggers[attr].nil? + + cmp_or_mgr.attr_triggers[attr].delete self + end + self.attr_triggers = {} + end + else + # remove attrs relevant to comp_or_man + unless attr_triggers[component_or_manager].nil? + attr_triggers[component_or_manager].each do |attr| + component_or_manager.attr_triggers[attr].delete self + end + attr_triggers[component_or_manager] = [] + end + end + + elsif component_or_manager.nil? + + (trigger_types - %i[addition_triggers removal_triggers attr_triggers]).each do |attr| + # remove attr + attr_triggers.each do |cmp_or_mgr, _attrs| + cmp_or_mgr.attr_triggers[attr].delete self + end + end + attr_triggers.delete(trigger_types - %i[addition_triggers + removal_triggers + attr_triggers]) + else + # remove attr from component_or_manager + (trigger_types - %i[addition_triggers removal_triggers attr_triggers]).each do |attr| + next if component_or_manager.attr_triggers[attr].nil? + + component_or_manager.attr_triggers[attr].delete self + end + attr_triggers[component_or_manager] -= trigger_types unless attr_triggers[component_or_manager].nil? + + end + end + + (trigger_types & %i[removal_triggers addition_triggers] - [:attr_triggers]).each do |trigger_type| + if component_or_manager.nil? + # remove all removal triggers + send(trigger_type).each do |trigger| + trigger.send(trigger_type).delete self + end + send("#{trigger_type}=", []) + else + # remove removal trigger relevant to comp/man + 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 + + # Add a component or component manager so that it triggers this system when a component's attribute is changed. + # @return [Boolean] +true+ + def trigger_when_is_changed(component_or_manager, attr) + if component_or_manager.attr_triggers[attr].nil? + component_or_manager.attr_triggers[attr] = [self] + else + component_or_manager.attr_triggers[attr] |= [self] + end + if attr_triggers[component_or_manager].nil? + attr_triggers[component_or_manager] = [attr] + else + attr_triggers[component_or_manager] |= [attr] + end + true + end + end +end diff --git a/lib/felecs/version.rb b/lib/felecs/version.rb new file mode 100644 index 0000000..295b905 --- /dev/null +++ b/lib/felecs/version.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# :nocov: +# Keeps the version of the Gem +module FelECS + # The version of the Gem + VERSION = '5.0.0' +end +# :nocov: diff --git a/lib/felflame.rb b/lib/felflame.rb deleted file mode 100644 index 21a6eaf..0000000 --- a/lib/felflame.rb +++ /dev/null @@ -1,67 +0,0 @@ -# frozen_string_literal: true - -require_relative 'felflame/entity_manager' -require_relative 'felflame/component_manager' -require_relative 'felflame/system_manager' -require_relative 'felflame/scene_manager' -require_relative 'felflame/stage_manager' -require_relative 'felflame/order' - -require_relative 'felflame/version' - -# The FelFlame namespace where all its functionality resides under. -module FelFlame - class << self - # :nocov: - - # An alias for {FelFlame::Stage.call}. It executes a single frame in the game. - def call - FelFlame::Stage.call - end - # :nocov: - end - - # Creates and manages Entities. Entities are just collections of Components. - # You can use array methods directly on this class to access Entities. - class Entities; end - - # Creates component managers and allows accessing them them under the {FelFlame::Components} namespace as Constants. - # You can use array methods directly on this class to access Component Managers. - # - # To see how component managers are used please look at the {FelFlame::ComponentManager} documentation. - module Components; end - - # Creates and 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. - # You can use array methods directly on this class to access Systems. - 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. - 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 - - # Sets the priority of a list of Systems or Scenes for you in the order you pass them to this class. - module Order; end -end - -# An alias for {FelFlame} -FF = FelFlame - -# An alias for {FelFlame::Entities} -FF::Ent = FelFlame::Entities - -# An alias for {FelFlame::Components} -FF::Cmp = FelFlame::Components - -# An alias for {FelFlame::Systems} -FF::Sys = FelFlame::Systems - -# An alias for {FelFlame::Scenes} -FF::Scn = FelFlame::Scenes - -# An alias for {FelFlame::Stage} -FF::Stg = FelFlame::Stage - -# An alias for {FelFlame:: -FF::Odr = FelFlame::Order diff --git a/lib/felflame/component_manager.rb b/lib/felflame/component_manager.rb deleted file mode 100644 index 6ac7463..0000000 --- a/lib/felflame/component_manager.rb +++ /dev/null @@ -1,277 +0,0 @@ -# frozen_string_literal: true - -module FelFlame - module Components - @component_map = [] - class << self - # Creates a new {FelFlame::ComponentManager component manager}. - # - # @example - # # Here color is set to default to red - # # while max and current are nil until set. - # # When you make a new component using this component manager - # # these are the values and accessors it will have. - # FelFlame::Component.new('Health', :max, :current, color: 'red') - # - # @param component_name [String] Name of your new component manager. Must be stylized in the format of constants in Ruby - # @param attrs [:Symbols] New components made with this manager will include these symbols as accessors, the values of these accessors will default to nil - # @param attrs_with_defaults [Keyword: DefaultValue] New components made with this manager will include these keywords as accessors, their defaults set to the values given to the keywords - # @return [ComponentManager] - def new(component_name, *attrs, **attrs_with_defaults) - if FelFlame::Components.const_defined?(component_name) - raise(NameError.new, "Component Manager '#{component_name}' is already defined") - end - - const_set(component_name, Class.new(FelFlame::ComponentManager) {}) - update_const_cache - - attrs.each do |attr| - if FelFlame::Components.const_get(component_name).method_defined?(attr.to_s) || FelFlame::Components.const_get(component_name).method_defined?("#{attr}=") - raise NameError, "The attribute name \"#{attr}\" is already a method" - end - - FelFlame::Components.const_get(component_name).attr_accessor attr - end - attrs_with_defaults.each do |attr, _default| - attrs_with_defaults[attr] = _default.dup - FelFlame::Components.const_get(component_name).attr_reader attr - FelFlame::Components.const_get(component_name).define_method("#{attr}=") do |value| - attr_changed_trigger_systems(attr) unless value.equal? send(attr) - instance_variable_set("@#{attr}", value) - end - end - FelFlame::Components.const_get(component_name).define_method(:set_defaults) do - attrs_with_defaults.each do |attr, default| - instance_variable_set("@#{attr}", default.dup) - end - end - FelFlame::Components.const_get(component_name) - end - - # Stores the components managers in {FelFlame::Components}. This - # is needed because calling `FelFlame::Components.constants` - # will not let you iterate over the value of the constants - # but will instead give you an array of symbols. This caches - # the convertion of those symbols to the actual value of the - # constants - # @!visibility private - def const_cache - @const_cache || update_const_cache - end - - # Updates the array that stores the constants. - # Used internally by FelFlame - # @!visibility private - def update_const_cache - @const_cache = constants.map do |constant| - const_get constant - end - end - - # Forwards undefined methods to the array of constants - # if the array can handle the request. Otherwise tells - # the programmer their code errored - # @!visibility private - def respond_to_missing?(method, *) - if const_cache.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 const_cache.respond_to? method - const_cache.send(method, *args, **kwargs, &block) - else - super - end - end - end - end - - # Component Managers are what is used to create individual components which can be attached to entities. - # 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 +@component.var = 5+), or by using the {#to_h} and {#update_attrs} methods instead. - class ComponentManager - # 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. - # @!visibility private - attr_writer :addition_triggers, :removal_triggers, :attr_triggers - - # Stores references to systems that should be triggered when a - # component from this manager is added. - # Do not edit this array as it is managed by FelFlame automatically. - # @return [Array] - def addition_triggers - @addition_triggers ||= [] - end - - # Stores references to systems that should be triggered when a - # component from this manager is removed. - # Do not edit this array as it is managed by FelFlame automatically. - # @return [Array] - def removal_triggers - @removal_triggers ||= [] - end - - # Stores references to systems that should be triggered when an - # attribute from this manager is changed. - # Do not edit this hash as it is managed by FelFlame automatically. - # @return [Hash>] - def attr_triggers - @attr_triggers ||= {} - end - - # Creates a new component and sets the values of the attributes given to it. If an attritbute is not passed then it will remain as the default. - # @param attrs [Keyword: Value] You can pass any number of Keyword-Value pairs - # @return [Component] - def initialize(**attrs) - # Prepare the object - # (this is a function created with metaprogramming - # in FelFlame::Components) - set_defaults - - # Fill params - attrs.each do |key, value| - send "#{key}=", value - end - - # Save Component - self.class.push 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 _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 _data.respond_to? method - _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. - # @!visibility private - attr_writer :addition_triggers, :removal_triggers, :attr_triggers - - # Stores references to systems that should be triggered when this - # component is added to an enitity. - # Do not edit this array as it is managed by FelFlame automatically. - # @return [Array] - def addition_triggers - @addition_triggers ||= [] - end - - # Stores references to systems that should be triggered when this - # component is removed from an enitity. - # Do not edit this array as it is managed by FelFlame automatically. - # @return [Array] - def removal_triggers - @removal_triggers ||= [] - end - - # Stores references to systems that should be triggered when an - # attribute from this component changed. - # Do not edit this hash as it is managed by FelFlame automatically. - # @return [Hash] - def attr_triggers - @attr_triggers ||= {} - end - - # @return [Array] Array of all Components that belong to a given component manager - # @!visibility private - def _data - @data ||= [] - end - end - - # Entities that have this component - # @return [Array] - def entities - @entities ||= [] - 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 - end - - # Update attribute values using a hash or keywords. - # @return [Hash] Hash of updated attributes - def update_attrs(**opts) - opts.each do |key, value| - send "#{key}=", value - end - end - - # Execute systems that have been added to execute on variable change - # @return [Boolean] +true+ - # @!visibility private - def attr_changed_trigger_systems(attr) - systems_to_execute = self.class.attr_triggers[attr] - systems_to_execute = [] if systems_to_execute.nil? - - systems_to_execute |= attr_triggers[attr] unless attr_triggers[attr].nil? - - 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. - # @return [Boolean] +true+. - def delete - addition_triggers.each do |system| - system.clear_triggers component_or_manager: self - end - entities.reverse_each do |entity| - entity.remove self - end - self.class._data.delete self - instance_variables.each do |var| - instance_variable_set(var, nil) - end - true - end - - # @return [Hash] A hash, where all the keys are attributes storing their respective values. - def to_h - return_hash = instance_variables.each_with_object({}) do |key, final| - final[key.to_s.delete_prefix('@').to_sym] = instance_variable_get(key) - end - return_hash.delete(:attr_triggers) - return_hash - end - - # Export all data into a JSON String, which could then later be loaded or saved to a file - # TODO: This function is not yet complete - # @return [String] a JSON formatted String - # def to_json - # # should return a json or hash of all data in this component - # end - end -end diff --git a/lib/felflame/entity_manager.rb b/lib/felflame/entity_manager.rb deleted file mode 100644 index ef70510..0000000 --- a/lib/felflame/entity_manager.rb +++ /dev/null @@ -1,160 +0,0 @@ -# frozen_string_literal: true - -module FelFlame - class Entities - # 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) - # Add each component - add(*components) - self.class._data.push 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. - # @return [Hash>] - 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. Array notation is conventional for better readablility. - # @example - # @entity.component[@component_manager] # array notation(the standard) - # @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? - FelFlame::Entities.component_redirect.entity = self - FelFlame::Entities.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 - end - - # Removes this Entity from the list and purges all references to this Entity from other Components, as well as its data. - # @return [Boolean] +true+ - def delete - components.each do |_component_manager, component_array| - component_array.reverse_each do |component| - component.entities.delete(self) - end - end - FelFlame::Entities._data.delete self - @components = {} - true - end - - # Add any number components to the Entity. - # @param components_to_add [Component] Any number of components created from any component manager - # @return [Boolean] +true+ - def add(*components_to_add) - components_to_add.each do |component| - if components[component.class].nil? - components[component.class] = [component] - component.entities.push self - check_systems component, :addition_triggers - elsif !components[component.class].include? component - components[component.class].push component - component.entities.push self - check_systems component, :addition_triggers - end - end - true - end - - # triggers every system associated with this component's trigger - # @return [Boolean] +true+ - # @!visibility private - def check_systems(component, trigger_type) - component_calls = component.class.send(trigger_type) - component.send(trigger_type).each do |system| - component_calls |= [system] - end - component_calls.sort_by(&:priority).reverse.each(&:call) - true - end - - # Remove a component from the Entity - # @param components_to_remove [Component] A component created from any component manager - # @return [Boolean] +true+ - def remove(*components_to_remove) - components_to_remove.each do |component| - check_systems component, :removal_triggers if component.entities.include? self - component.entities.delete self - components[component.class].delete component - components.delete component.class if components[component.class].empty? - end - true - end - - # Export all data into a JSON String which can then be saved into a file - # TODO: This function is not yet complete - # @return [String] A JSON formatted String - # def to_json() end - - class << self - # Makes component managers behave like arrays with additional - # methods for managing the array - # @!visibility private - def respond_to_missing?(method, *) - if _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 _data.respond_to? method - _data.send(method, *args, **kwargs, &block) - else - super - end - end - - # Fancy method redirection for when the `component` method is called - # in an Entity - # WARNING: This method will not correctly work with multithreading - # @!visibility private - def component_redirect - if @component_redirect - else - @component_redirect = Object.new - @component_redirect.instance_variable_set(:@entity, nil) - @component_redirect.define_singleton_method(:entity) do - instance_variable_get(:@entity) - end - @component_redirect.define_singleton_method(:entity=) do |value| - instance_variable_set(:@entity, value) - end - @component_redirect.define_singleton_method(:[]) do |component_manager| - entity.component(component_manager) - end - end - @component_redirect - end - - # @return [Array] Array of all Entities that exist - # @!visibility private - def _data - @data ||= [] - end - - # Creates a new entity using the data from a JSON string - # TODO: This function is not yet complete - # @param json_string [String] A string that was exported originally using the {FelFlame::Entities#to_json to_json} function - # @param opts [Keywords] What values(its {FelFlame::Entities#id ID} or the {FelFlame::ComponentManager#id component IDs}) should be overwritten TODO: this might change - # def from_json(json_string, **opts) end - end - end -end diff --git a/lib/felflame/order.rb b/lib/felflame/order.rb deleted file mode 100644 index c11438d..0000000 --- a/lib/felflame/order.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -module FelFlame - module Order - # Sets the priority of all items passed into this method - # according to the order they were passed. - # If an array is one of the elements then it will give all - # of those elements in the array the same priority. - # @param sortables [(Systems and Array) or (Scenes and Array)] - # @return [Boolean] +true+. - def self.sort(*sortables) - sortables.each_with_index do |sorted, index| - if sorted.respond_to? :priority - sorted.priority = index - else - sorted.each do |item| - item.priority = index - end - end - end - true - end - end -end diff --git a/lib/felflame/scene_manager.rb b/lib/felflame/scene_manager.rb deleted file mode 100644 index 0024815..0000000 --- a/lib/felflame/scene_manager.rb +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: true - -module FelFlame - class Scenes - # Allows overwriting the storage of systems, such as for clearing. - # This method should generally only need to be used internally and - # not by a game developer/ - # @!visibility private - attr_writer :systems - - # How early this Scene should be executed in a list of Scenes - attr_accessor :priority - - def priority=(priority) - @priority = priority - FelFlame::Stage.scenes = FelFlame::Stage.scenes.sort_by(&:priority) - priority - end - - # Create a new Scene using the name given - # @param name [String] String format must follow requirements of a constant - def initialize(name, priority: 0) - self.priority = priority - FelFlame::Scenes.const_set(name, self) - end - - # The list of Systems this Scene contains - # @return [Array] - def systems - @systems ||= [] - end - - # Execute all systems in this Scene, in the order of their priority - # @return [Boolean] +true+ - def call - systems.each(&:call) - true - end - - # Adds any number of Systems to this Scene - # @return [Boolean] +true+ - def add(*systems_to_add) - self.systems |= systems_to_add - self.systems = systems.sort_by(&:priority) - systems_to_add.each do |system| - system.scenes |= [self] - end - true - end - - # Removes any number of Systems from this Scene - # @return [Boolean] +true+ - def remove(*systems_to_remove) - self.systems -= systems_to_remove - true - end - - # Removes all Systems from this Scene - # @return [Boolean] +true+ - def clear - systems.each do |system| - system.scenes.delete self - end - systems.clear - # FelFlame::Stage.update_systems_list if FelFlame::Stage.scenes.include? self - true - end - end -end diff --git a/lib/felflame/stage_manager.rb b/lib/felflame/stage_manager.rb deleted file mode 100644 index a192b67..0000000 --- a/lib/felflame/stage_manager.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -module FelFlame - module Stage - class << self - # Allows clearing of scenes and systems. - # Used internally by FelFlame and shouldn't need to be ever used by developers - # @!visibility private - attr_writer :scenes - - # Add any number of Scenes to the Stage - # @return [Boolean] +true+ - def add(*scenes_to_add) - self.scenes |= scenes_to_add - self.scenes = scenes.sort_by(&:priority) - true - end - - # Remove any number of Scenes from the Stage - # @return [Boolean] +true+ - def remove(*scenes_to_remove) - self.scenes -= scenes_to_remove - true - end - - # Clears all Scenes that were added to the Stage - # @return [Boolean] +true+ - def clear - self.scenes.clear - true - end - - # Executes one frame of the game. This executes all the Scenes added to the Stage in order of their priority. - # @return [Boolean] +true+ - def call - self.scenes.each(&:call) - true - end - - # Contains all the Scenes added to the Stage - # @return [Array] - def scenes - @scenes ||= [] - end - end - end -end diff --git a/lib/felflame/system_manager.rb b/lib/felflame/system_manager.rb deleted file mode 100644 index 8982589..0000000 --- a/lib/felflame/system_manager.rb +++ /dev/null @@ -1,258 +0,0 @@ -# frozen_string_literal: true - -module 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 - - # 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. - # @!visibility private - attr_writer :addition_triggers, :removal_triggers, :attr_triggers - - # Stores all the scenes this system is a part of. - attr_writer :scenes - - def scenes - @scenes ||= [] - end - - def priority=(priority) - @priority = priority - scenes.each do |scene| - scene.systems = scene.systems.sort_by(&:priority) - end - end - - # Stores references to components or their managers that trigger - # this component when a component or component from that manager - # is added to an entity. - # Do not edit this hash as it is managed by FelFlame automatically. - # @return [Array] - def addition_triggers - @addition_triggers ||= [] - end - - # Stores references to components or their managers that trigger - # this component when a component or component from that manager - # is removed from an entity. - # Do not edit this hash as it is managed by FelFlame automatically. - # @return [Array] - def removal_triggers - @removal_triggers ||= [] - end - - # Stores references to systems that should be triggered when an - # attribute from this manager is changed - # Do not edit this hash as it is managed by FelFlame automatically. - # @return [Hash>] - def attr_triggers - @attr_triggers ||= {} - end - - class << self - # Stores the systems in {FelFlame::Components}. This - # is needed because calling `FelFlame::Components.constants` - # will not let you iterate over the value of the constants - # but will instead give you an array of symbols. This caches - # the convertion of those symbols to the actual value of the - # constants - def const_cache - @const_cache || update_const_cache - end - - # Updates the array that stores the constants. - # Used internally by FelFlame - # @!visibility private - def update_const_cache - @const_cache = constants.map do |constant| - const_get constant - end - end - - # Forwards undefined methods to the array of constants - # if the array can handle the request. Otherwise tells - # the programmer their code errored - # @!visibility private - def respond_to_missing?(method, *) - if const_cache.respond_to? method - true - else - super - end - end - - # Makes system module behave like arrays with additional - # methods for managing the array - # @!visibility private - def method_missing(method, *args, **kwargs, &block) - if const_cache.respond_to? method - const_cache.send(method, *args, **kwargs, &block) - else - super - end - 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) do - # FelFlame::Components::Health.each do |component| - # component.hp += 5 - # end - # end - # # 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) - FelFlame::Systems.update_const_cache - @priority = priority - @block = block - @scenes = [] - end - - # Manually execute the system a single time - def call - @block.call - 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. This function is fairly flexible so it can accept a few different inputs - # For addition and removal triggers, you can optionally pass in a component, or a manager to clear specifically - # the relevant triggers for that one component or manager. If you do not pass a component or manager then it will - # clear triggers for all components and managers. - # For attr_triggers - # @example - # # To clear all triggers that execute this system when a component is added: - # FelFlame::Systems::ExampleSystem.clear_triggers :addition_triggers - # # Same as above but for when a component is removed instead - # FelFlame::Systems::ExampleSystem.clear_triggers :removal_triggers - # # Same as above but for when a component has a certain attribute changed - # FelFlame::Systems::ExampleSystem.clear_triggers :attr_triggers - # - # # Clear a trigger from a specific component - # FelFlame::Systems::ExampleSystem.clear_triggers :addition_triggers, FelFlame::Component::ExampleComponent[0] - # # Clear a trigger from a specific component manager - # FelFlame::Systems::ExampleSystem.clear_triggers :addition_triggers, FelFlame::Component::ExampleComponent - # - # # Clear the trigger that executes a system when the ':example_attr' is changes - # FelFlame::Systems::ExampleSystem.clear_triggers :attr_triggers, :example_attr - # @param trigger_types [:Symbols] One or more of the following trigger types: +:addition_triggers+, +:removal_triggers+, or +:attr_triggers+. If attr_triggers is used then you may pass attributes you wish to be cleared as symbols in this parameter as well - # @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 = %i[addition_triggers removal_triggers attr_triggers] if trigger_types.empty? - - if trigger_types.include? :attr_triggers - if (trigger_types - %i[addition_triggers - removal_triggers - attr_triggers]).empty? - - if component_or_manager.nil? - # remove all attrs - attr_triggers.each do |cmp_or_mgr, attrs| - attrs.each do |attr| - next if cmp_or_mgr.attr_triggers[attr].nil? - - cmp_or_mgr.attr_triggers[attr].delete self - end - self.attr_triggers = {} - end - else - # remove attrs relevant to comp_or_man - unless attr_triggers[component_or_manager].nil? - attr_triggers[component_or_manager].each do |attr| - component_or_manager.attr_triggers[attr].delete self - end - attr_triggers[component_or_manager] = [] - end - end - - elsif component_or_manager.nil? - - (trigger_types - %i[addition_triggers removal_triggers attr_triggers]).each do |attr| - # remove attr - attr_triggers.each do |cmp_or_mgr, _attrs| - cmp_or_mgr.attr_triggers[attr].delete self - end - end - attr_triggers.delete(trigger_types - %i[addition_triggers - removal_triggers - attr_triggers]) - else - # remove attr from component_or_manager - (trigger_types - %i[addition_triggers removal_triggers attr_triggers]).each do |attr| - next if component_or_manager.attr_triggers[attr].nil? - - component_or_manager.attr_triggers[attr].delete self - end - attr_triggers[component_or_manager] -= trigger_types unless attr_triggers[component_or_manager].nil? - - end - end - - (trigger_types & %i[removal_triggers addition_triggers] - [:attr_triggers]).each do |trigger_type| - if component_or_manager.nil? - # remove all removal triggers - send(trigger_type).each do |trigger| - trigger.send(trigger_type).delete self - end - send("#{trigger_type}=", []) - else - # remove removal trigger relevant to comp/man - 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 - - # Add a component or component manager so that it triggers this system when a component's attribute is changed. - # @return [Boolean] +true+ - def trigger_when_is_changed(component_or_manager, attr) - if component_or_manager.attr_triggers[attr].nil? - component_or_manager.attr_triggers[attr] = [self] - else - component_or_manager.attr_triggers[attr] |= [self] - end - if attr_triggers[component_or_manager].nil? - attr_triggers[component_or_manager] = [attr] - else - attr_triggers[component_or_manager] |= [attr] - end - true - end - end -end diff --git a/lib/felflame/version.rb b/lib/felflame/version.rb deleted file mode 100644 index 9f7f09e..0000000 --- a/lib/felflame/version.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -# :nocov: -# Keeps the version of the Gem -module Felflame - # The version of the Gem - VERSION = '4.0.0' -end -# :nocov: diff --git a/logos/felecs-logo-text.png b/logos/felecs-logo-text.png new file mode 100644 index 0000000..cf17250 Binary files /dev/null and b/logos/felecs-logo-text.png differ diff --git a/logos/felecs-logo-text.png.png b/logos/felecs-logo-text.png.png deleted file mode 100644 index cf17250..0000000 Binary files a/logos/felecs-logo-text.png.png and /dev/null differ diff --git a/spec/component_manager_spec.rb b/spec/component_manager_spec.rb index 9bf9b9e..bd1df38 100644 --- a/spec/component_manager_spec.rb +++ b/spec/component_manager_spec.rb @@ -1,22 +1,22 @@ # frozen_string_literal: true -require_relative '../lib/felflame' +require_relative '../lib/felecs' describe 'Components' do # let :component_manager do - # @component_manager ||= FelFlame::Components.new('TestComponents', :param1, param2: 'def') + # @component_manager ||= FelECS::Components.new('TestComponents', :param1, param2: 'def') # end before :all do - @component_manager ||= FelFlame::Components.new('TestComponents', :param1, param2: 'def') + @component_manager ||= FelECS::Components.new('TestComponents', :param1, param2: 'def') end before :each do @orig_stderr = $stderr $stderr = StringIO.new - @ent0 = FelFlame::Entities.new - @ent1 = FelFlame::Entities.new - @ent2 = FelFlame::Entities.new + @ent0 = FelECS::Entities.new + @ent1 = FelECS::Entities.new + @ent2 = FelECS::Entities.new @cmp0 = @component_manager.new @cmp1 = @component_manager.new @cmp2 = @component_manager.new @@ -24,7 +24,7 @@ describe 'Components' do after :each do $stderr = @orig_stderr - FelFlame::Entities.reverse_each(&:delete) + FelECS::Entities.reverse_each(&:delete) @component_manager.reverse_each(&:delete) end @@ -57,19 +57,19 @@ describe 'Components' do end it 'Component module responds to array methods' do - expect(FelFlame::Components.respond_to?(:[])).to be true - expect(FelFlame::Components.respond_to?(:each)).to be true - FelFlame::Components.each do |component_manager| + expect(FelECS::Components.respond_to?(:[])).to be true + expect(FelECS::Components.respond_to?(:each)).to be true + FelECS::Components.each do |component_manager| expect(component_manager.respond_to?(:addition_triggers)).to be true end - expect(FelFlame::Components.respond_to?(:filter)).to be true - expect(FelFlame::Components.respond_to?(:first)).to be true - expect(FelFlame::Components.respond_to?(:last)).to be true - expect(FelFlame::Components.respond_to?(:somethingwrong)).to be false + expect(FelECS::Components.respond_to?(:filter)).to be true + expect(FelECS::Components.respond_to?(:first)).to be true + expect(FelECS::Components.respond_to?(:last)).to be true + expect(FelECS::Components.respond_to?(:somethingwrong)).to be false end it 'Component module doesnt respond to missing methods' do - expect { FelFlame::Components.somethingwrong }.to raise_error(NoMethodError) + expect { FelECS::Components.somethingwrong }.to raise_error(NoMethodError) end it 'can delete a component' do @@ -84,13 +84,13 @@ describe 'Components' do end it 'can iterate component managers' do - all_components_symbols = FelFlame::Components.constants + all_components_symbols = FelECS::Components.constants all_components = all_components_symbols.map do |symbol| - FelFlame::Components.const_get symbol + FelECS::Components.const_get symbol end - expect(all_components).to eq(FF::Components.each.to_a) + expect(all_components).to eq(FelECS::Components.each.to_a) expect(all_components.length).to be > 0 - expect(FelFlame::Components.each).to be_an Enumerator + expect(FelECS::Components.each).to be_an Enumerator end it 'can change params on initialization' do @@ -130,15 +130,15 @@ describe 'Components' do end it 'cant overwrite exiting component managers' do - FelFlame::Components.new('TestComponent1') - expect { FelFlame::Components.new('TestComponent1') }.to raise_error(NameError) + FelECS::Components.new('TestComponent1') + expect { FelECS::Components.new('TestComponent1') }.to raise_error(NameError) end it 'can\'t create an attribute when its name is an existing method' do - # expect { FelFlame::Components.new('TestComponent2', :id) }.to raise_error(NameError) - expect { FelFlame::Components.new('TestComponent2', :addition_triggers) }.to raise_error(NameError) - expect { FelFlame::Components.new('TestComponent2', :removal_triggers) }.to raise_error(NameError) - expect { FelFlame::Components.new('TestComponent2', :attr_triggers) }.to raise_error(NameError) - expect { FelFlame::Components.new('TestComponent3', :same, :same) }.to raise_error(NameError) + # expect { FelECS::Components.new('TestComponent2', :id) }.to raise_error(NameError) + expect { FelECS::Components.new('TestComponent2', :addition_triggers) }.to raise_error(NameError) + expect { FelECS::Components.new('TestComponent2', :removal_triggers) }.to raise_error(NameError) + expect { FelECS::Components.new('TestComponent2', :attr_triggers) }.to raise_error(NameError) + expect { FelECS::Components.new('TestComponent3', :same, :same) }.to raise_error(NameError) end end diff --git a/spec/entity_manager_spec.rb b/spec/entity_manager_spec.rb index 2068986..25afa45 100644 --- a/spec/entity_manager_spec.rb +++ b/spec/entity_manager_spec.rb @@ -1,21 +1,21 @@ # frozen_string_literal: true -require_relative '../lib/felflame' +require_relative '../lib/felecs' # class EntitiesTest < Minitest::Test describe 'Entities' do before :all do $VERBOSE = nil - @component_manager ||= FelFlame::Components.new('TestEntity', :param1, param2: 'def') + @component_manager ||= FelECS::Components.new('TestEntity', :param1, param2: 'def') end before :each do @orig_stderr = $stderr $stderr = StringIO.new - @ent0 = FelFlame::Entities.new - @ent1 = FelFlame::Entities.new - @ent2 = FelFlame::Entities.new + @ent0 = FelECS::Entities.new + @ent1 = FelECS::Entities.new + @ent2 = FelECS::Entities.new @cmp0 = @component_manager.new @cmp1 = @component_manager.new @cmp2 = @component_manager.new @@ -23,7 +23,7 @@ describe 'Entities' do after :each do $stderr = @orig_stderr - FelFlame::Entities.reverse_each(&:delete) + FelECS::Entities.reverse_each(&:delete) @component_manager.reverse_each(&:delete) end @@ -43,19 +43,19 @@ describe 'Entities' do end it 'responds to array methods' do - expect(FelFlame::Entities.respond_to?(:[])).to be true - expect(FelFlame::Entities.respond_to?(:each)).to be true - FelFlame::Entities.each do |entity| + expect(FelECS::Entities.respond_to?(:[])).to be true + expect(FelECS::Entities.respond_to?(:each)).to be true + FelECS::Entities.each do |entity| expect(entity.respond_to?(:components)).to be true end - expect(FelFlame::Entities.respond_to?(:filter)).to be true - expect(FelFlame::Entities.respond_to?(:first)).to be true - expect(FelFlame::Entities.respond_to?(:last)).to be true - expect(FelFlame::Entities.respond_to?(:somethingwrong)).to be false + expect(FelECS::Entities.respond_to?(:filter)).to be true + expect(FelECS::Entities.respond_to?(:first)).to be true + expect(FelECS::Entities.respond_to?(:last)).to be true + expect(FelECS::Entities.respond_to?(:somethingwrong)).to be false end it 'dont respond to missing methods' do - expect { FelFlame::Entities.somethingwrong }.to raise_error(NoMethodError) + expect { FelECS::Entities.somethingwrong }.to raise_error(NoMethodError) end it 'won\'t add duplicate entities' do @@ -64,9 +64,9 @@ describe 'Entities' do end it 'can be accessed' do - expect(FelFlame::Entities[0].respond_to?(:components)).to eq(true) - expect(FelFlame::Entities[1].respond_to?(:components)).to eq(true) - expect(FelFlame::Entities[2].respond_to?(:components)).to eq(true) + expect(FelECS::Entities[0].respond_to?(:components)).to eq(true) + expect(FelECS::Entities[1].respond_to?(:components)).to eq(true) + expect(FelECS::Entities[2].respond_to?(:components)).to eq(true) end it 'can have components attached' do @@ -108,7 +108,7 @@ describe 'Entities' do expect(@component_manager.empty?).to be true expect(@ent0.components).to eq({}) expect(@ent2.components).to eq({}) - FelFlame::Entities.reverse_each(&:delete) - expect(FelFlame::Entities.empty?).to be true + FelECS::Entities.reverse_each(&:delete) + expect(FelECS::Entities.empty?).to be true end end diff --git a/spec/order_spec.rb b/spec/order_spec.rb index fd104fc..0d89f15 100644 --- a/spec/order_spec.rb +++ b/spec/order_spec.rb @@ -1,24 +1,24 @@ # frozen_string_literal: true -require_relative '../lib/felflame' +require_relative '../lib/felecs' # class EntitiesTest < Minitest::Test describe 'Order' do before :all do @result = [] - @system0 = FelFlame::Systems.new('System1', priority: 0) do + @system0 = FelECS::Systems.new('System1', priority: 0) do @result.push 0 end - @system2 = FelFlame::Systems.new('System3', priority: 2) do + @system2 = FelECS::Systems.new('System3', priority: 2) do @result.push 2 end - @system1 = FelFlame::Systems.new('System2', priority: 1) do + @system1 = FelECS::Systems.new('System2', priority: 1) do @result.push 1 end - @scene1 = FelFlame::Scenes.new('Scene0', priority: 1) - @scene0 = FelFlame::Scenes.new('Scene0', priority: 0) + @scene1 = FelECS::Scenes.new('Scene0', priority: 1) + @scene0 = FelECS::Scenes.new('Scene0', priority: 0) end before :each do @@ -38,7 +38,7 @@ describe 'Order' do it 'can sort Scenes' do @scene0.add @system0 @scene1.add @system1 - FelFlame::Order.sort( + FelECS::Order.sort( @scene1, @scene0 ) @@ -47,7 +47,7 @@ describe 'Order' do it 'can sort Systems' do @scene0.add @system0, @system1, @system2 - FelFlame::Order.sort( + FelECS::Order.sort( @system2, @system0, @system1 @@ -57,7 +57,7 @@ describe 'Order' do end it 'can handle array' do - FelFlame::Order.sort( + FelECS::Order.sort( @system0, [ @system1, diff --git a/spec/scene_manager_spec.rb b/spec/scene_manager_spec.rb index e1984dc..51d74ef 100644 --- a/spec/scene_manager_spec.rb +++ b/spec/scene_manager_spec.rb @@ -1,28 +1,28 @@ # frozen_string_literal: true -require_relative '../lib/felflame' +require_relative '../lib/felecs' # class EntitiesTest < Minitest::Test describe 'Scenes' do before :all do - @component_manager ||= FelFlame::Components.new('TestScenes', order: []) - @system2 = FelFlame::Systems.new('Test', priority: 2) do + @component_manager ||= FelECS::Components.new('TestScenes', order: []) + @system2 = FelECS::Systems.new('Test', priority: 2) do @component_manager.each do |component| component.order.push 2 end end - @system1 = FelFlame::Systems.new('Mana', priority: 1) do + @system1 = FelECS::Systems.new('Mana', priority: 1) do @component_manager.each do |component| component.order.push 1 end end - @system3 = FelFlame::Systems.new('Spell', priority: 3) do + @system3 = FelECS::Systems.new('Spell', priority: 3) do @component_manager.each do |component| component.order.push 3 end end - @scene = FelFlame::Scenes.new('TestScene') + @scene = FelECS::Scenes.new('TestScene') end before :each do @@ -30,7 +30,7 @@ describe 'Scenes' do end after :each do - FelFlame::Entities.each(&:delete) + FelECS::Entities.each(&:delete) @component_manager.each(&:delete) @scene.clear end diff --git a/spec/stage_manager_spec.rb b/spec/stage_manager_spec.rb index 16f9080..928f4c1 100644 --- a/spec/stage_manager_spec.rb +++ b/spec/stage_manager_spec.rb @@ -1,27 +1,27 @@ # frozen_string_literal: true -require_relative '../lib/felflame' +require_relative '../lib/felecs' # class EntitiesTest < Minitest::Test describe 'Stage' do before :all do - @component_manager ||= FelFlame::Components.new('TestStage', order: []) - @system2 = FelFlame::Systems.new('StageTest', priority: 1) do + @component_manager ||= FelECS::Components.new('TestStage', order: []) + @system2 = FelECS::Systems.new('StageTest', priority: 1) do @component_manager.first.order.push 2 end - @system1 = FelFlame::Systems.new('StageMana', priority: 3) do + @system1 = FelECS::Systems.new('StageMana', priority: 3) do @component_manager.first.order.push 1 end - @system3 = FelFlame::Systems.new('StageSpell', priority: 2) do + @system3 = FelECS::Systems.new('StageSpell', priority: 2) do @scene1.add @system1 @scene2.add @system2 @scene3.add @system3 @component_manager.first.order.push 3 end - @scene1 = FelFlame::Scenes.new('TestStage1', priority: 1) - @scene2 = FelFlame::Scenes.new('TestStage2', priority: 2) - @scene3 = FelFlame::Scenes.new('TestStage3', priority: 3) + @scene1 = FelECS::Scenes.new('TestStage1', priority: 1) + @scene2 = FelECS::Scenes.new('TestStage2', priority: 2) + @scene3 = FelECS::Scenes.new('TestStage3', priority: 3) end before :each do @@ -29,37 +29,37 @@ describe 'Stage' do end after :each do - FelFlame::Entities.reverse_each(&:delete) + FelECS::Entities.reverse_each(&:delete) @component_manager.reverse_each(&:delete) @scene1.clear @scene2.clear @scene3.clear - FelFlame::Stage.clear + FelECS::Stage.clear end it 'can add Scenes' do - FelFlame::Stage.add @scene2, @scene1, @scene3 - expect(FelFlame::Stage.scenes).to eq([@scene1, @scene2, @scene3]) + FelECS::Stage.add @scene2, @scene1, @scene3 + expect(FelECS::Stage.scenes).to eq([@scene1, @scene2, @scene3]) end it 'can remove Scenes' do - FelFlame::Stage.add @scene1, @scene2, @scene3 - FelFlame::Stage.remove @scene1, @scene3 - expect(FelFlame::Stage.scenes).to eq([@scene2]) + FelECS::Stage.add @scene1, @scene2, @scene3 + FelECS::Stage.remove @scene1, @scene3 + expect(FelECS::Stage.scenes).to eq([@scene2]) end it 'can clear Scenes' do - FelFlame::Stage.add @scene1, @scene2, @scene3 - FelFlame::Stage.clear - expect(FelFlame::Stage.scenes).to eq([]) + FelECS::Stage.add @scene1, @scene2, @scene3 + FelECS::Stage.clear + expect(FelECS::Stage.scenes).to eq([]) end it 'can call Scenes in correct order' do - FelFlame::Stage.add @scene2, @scene1, @scene3 + FelECS::Stage.add @scene2, @scene1, @scene3 @scene1.add @system1 @scene2.add @system2 @scene3.add @system3 - FelFlame::Stage.call + FelECS::Stage.call expect(@component_manager.first.order).to eq([1, 2, 3]) end end diff --git a/spec/system_manager_spec.rb b/spec/system_manager_spec.rb index b7177af..3b36d34 100644 --- a/spec/system_manager_spec.rb +++ b/spec/system_manager_spec.rb @@ -1,16 +1,16 @@ # frozen_string_literal: true -require_relative '../lib/felflame' +require_relative '../lib/felecs' describe 'Systems' do before :all do - @component_manager ||= FelFlame::Components.new('TestSystems', health: 10, whatever: 'imp', mana: 10) + @component_manager ||= FelECS::Components.new('TestSystems', health: 10, whatever: 'imp', mana: 10) @@testitr = 999 end before :each do @@testitr += 1 - @system = FelFlame::Systems.new "Test#{@@testitr}" do + @system = FelECS::Systems.new "Test#{@@testitr}" do @component_manager.each do |component| component.health += 5 end @@ -19,13 +19,13 @@ describe 'Systems' do after :each do @component_manager.each(&:delete) - FelFlame::Entities.each(&:delete) - FelFlame::Systems.each(&:clear_triggers) + FelECS::Entities.each(&:delete) + FelECS::Systems.each(&:clear_triggers) end it 'can create a system' do @@testitr += 1 - sys = FelFlame::Systems.new("Test#{@@testitr}") do + sys = FelECS::Systems.new("Test#{@@testitr}") do 'Works' end expect(sys.call).to eq('Works') @@ -39,19 +39,19 @@ describe 'Systems' do end it 'responds to array methods' do - expect(FelFlame::Systems.respond_to?(:[])).to be true - expect(FelFlame::Systems.respond_to?(:each)).to be true - FelFlame::Systems.each do |system| + expect(FelECS::Systems.respond_to?(:[])).to be true + expect(FelECS::Systems.respond_to?(:each)).to be true + FelECS::Systems.each do |system| expect(system.respond_to?(:call)).to be true end - expect(FelFlame::Systems.respond_to?(:filter)).to be true - expect(FelFlame::Systems.respond_to?(:first)).to be true - expect(FelFlame::Systems.respond_to?(:last)).to be true - expect(FelFlame::Systems.respond_to?(:somethingwrong)).to be false + expect(FelECS::Systems.respond_to?(:filter)).to be true + expect(FelECS::Systems.respond_to?(:first)).to be true + expect(FelECS::Systems.respond_to?(:last)).to be true + expect(FelECS::Systems.respond_to?(:somethingwrong)).to be false end it 'dont respond to missing methods' do - expect { FelFlame::Systems.somethingwrong }.to raise_error(NoMethodError) + expect { FelECS::Systems.somethingwrong }.to raise_error(NoMethodError) end it 'can manipulate components' do @@ -92,8 +92,8 @@ describe 'Systems' do @system.trigger_when_added @cmp0 expect(@cmp0.health).to eq(10) expect(@cmp1.health).to eq(20) - @entity0 = FelFlame::Entities.new - @entity1 = FelFlame::Entities.new @cmp0 + @entity0 = FelECS::Entities.new + @entity1 = FelECS::Entities.new @cmp0 expect(@cmp0.health).to eq(15) expect(@cmp1.health).to eq(25) @entity0.add @cmp0 @@ -107,8 +107,8 @@ describe 'Systems' do @system.trigger_when_added @component_manager expect(@cmp1.health).to eq(10) expect(@cmp2.health).to eq(20) - @entity1 = FelFlame::Entities.new - @entity2 = FelFlame::Entities.new @cmp2 + @entity1 = FelECS::Entities.new + @entity2 = FelECS::Entities.new @cmp2 expect(@cmp1.health).to eq(15) expect(@cmp2.health).to eq(25) @system.trigger_when_added @cmp1 @@ -123,8 +123,8 @@ describe 'Systems' do @system.trigger_when_removed @cmp0 expect(@cmp0.health).to eq(10) expect(@cmp1.health).to eq(20) - @entity0 = FelFlame::Entities.new - @entity1 = FelFlame::Entities.new @cmp0 + @entity0 = FelECS::Entities.new + @entity1 = FelECS::Entities.new @cmp0 expect(@cmp0.health).to eq(10) expect(@cmp1.health).to eq(20) @entity1.remove @cmp0 @@ -147,8 +147,8 @@ describe 'Systems' do @system.trigger_when_removed @component_manager expect(@cmp0.health).to eq(10) expect(@cmp1.health).to eq(20) - @entity0 = FelFlame::Entities.new - @entity1 = FelFlame::Entities.new @cmp0 + @entity0 = FelECS::Entities.new + @entity1 = FelECS::Entities.new @cmp0 expect(@cmp0.health).to eq(10) expect(@cmp1.health).to eq(20) @entity1.remove @cmp0 @@ -172,8 +172,8 @@ describe 'Systems' do @system.trigger_when_is_changed @cmp0, :whatever expect(@cmp0.health).to eq(10) expect(@cmp1.health).to eq(20) - @entity0 = FelFlame::Entities.new - @entity1 = FelFlame::Entities.new @cmp0 + @entity0 = FelECS::Entities.new + @entity1 = FelECS::Entities.new @cmp0 expect(@cmp0.health).to eq(10) expect(@cmp1.health).to eq(20) @cmp0.whatever = 'different' @@ -187,7 +187,7 @@ describe 'Systems' do it 'can clear all triggers' do @cmp0 = @component_manager.new health: 10 @cmp1 = @component_manager.new health: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_added @cmp0 @system.trigger_when_added @component_manager @system.trigger_when_removed @cmp0 @@ -208,7 +208,7 @@ describe 'Systems' do it 'can clear individual attr_triggers, without component or manager' do @cmp0 = @component_manager.new health: 10, mana: 10 @cmp1 = @component_manager.new health: 20, mana: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_is_changed @cmp0, :whatever @system.trigger_when_is_changed @component_manager, :whatever @system.trigger_when_is_changed @cmp0, :mana @@ -229,7 +229,7 @@ describe 'Systems' do it 'can clear individual attr_triggers, with component' do @cmp0 = @component_manager.new health: 10, mana: 10 @cmp1 = @component_manager.new health: 20, mana: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_is_changed @cmp0, :whatever @system.trigger_when_is_changed @cmp0, :mana # expect(@system.attr_triggers).to eq({@cmp0 => [:name, :mana]}) @@ -252,7 +252,7 @@ describe 'Systems' do it 'can clear individual attr_triggers, with manager' do @cmp0 = @component_manager.new health: 10, mana: 10 @cmp1 = @component_manager.new health: 20, mana: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_is_changed @component_manager, :whatever @system.trigger_when_is_changed @component_manager, :mana @system.clear_triggers :attr_triggers, :whatever, component_or_manager: @component_manager @@ -271,7 +271,7 @@ describe 'Systems' do it 'can clear all attr_triggers, without component or manager' do @cmp0 = @component_manager.new health: 10, mana: 10 @cmp1 = @component_manager.new health: 20, mana: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_is_changed @component_manager, :whatever @system.trigger_when_is_changed @cmp1, :mana @system.clear_triggers :attr_triggers @@ -290,7 +290,7 @@ describe 'Systems' do it 'can clear all attr_triggers, with component' do @cmp0 = @component_manager.new health: 10, mana: 10 @cmp1 = @component_manager.new health: 20, mana: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_is_changed @component_manager, :whatever @system.trigger_when_is_changed @cmp1, :mana @system.clear_triggers :attr_triggers, component_or_manager: @cmp1 @@ -309,7 +309,7 @@ describe 'Systems' do it 'can clear all attr_triggers, with manager' do @cmp0 = @component_manager.new health: 10, mana: 10 @cmp1 = @component_manager.new health: 20, mana: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_is_changed @component_manager, :whatever @system.trigger_when_is_changed @cmp1, :mana @system.clear_triggers :attr_triggers, component_or_manager: @component_manager @@ -328,7 +328,7 @@ describe 'Systems' do it 'can clear addition_trigger, without component or manager' do @cmp0 = @component_manager.new health: 10 @cmp1 = @component_manager.new health: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_added @cmp0 @system.trigger_when_added @component_manager @system.clear_triggers(:addition_triggers) @@ -343,7 +343,7 @@ describe 'Systems' do it 'can clear addition_trigger, with component' do @cmp0 = @component_manager.new health: 10 @cmp1 = @component_manager.new health: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_added @cmp0 @system.clear_triggers :addition_triggers, component_or_manager: @cmp0 expect(@cmp0.health).to eq(10) @@ -357,7 +357,7 @@ describe 'Systems' do it 'can clear addition_trigger, with manager' do @cmp0 = @component_manager.new health: 10 @cmp1 = @component_manager.new health: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_added @component_manager @system.clear_triggers :addition_triggers, component_or_manager: @component_manager expect(@cmp0.health).to eq(10) @@ -371,7 +371,7 @@ describe 'Systems' do it 'can clear removal_trigger, without component or manager' do @cmp0 = @component_manager.new health: 10 @cmp1 = @component_manager.new health: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_removed @cmp0 @system.trigger_when_removed @component_manager @system.clear_triggers(:removal_triggers) @@ -386,7 +386,7 @@ describe 'Systems' do it 'can clear removal_trigger, with component' do @cmp0 = @component_manager.new health: 10 @cmp1 = @component_manager.new health: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_removed @cmp0 @system.clear_triggers :removal_triggers, component_or_manager: @cmp0 expect(@cmp0.health).to eq(10) @@ -400,7 +400,7 @@ describe 'Systems' do it 'can clear removal_trigger, with manager' do @cmp0 = @component_manager.new health: 10 @cmp1 = @component_manager.new health: 20 - @entity1 = FelFlame::Entities.new + @entity1 = FelECS::Entities.new @system.trigger_when_removed @component_manager @system.clear_triggers :removal_triggers, component_or_manager: @component_manager expect(@cmp0.health).to eq(10) -- cgit v1.2.3