From a0f792d8feadf919290b8349dbc0eac143545927 Mon Sep 17 00:00:00 2001 From: _Tradam Date: Mon, 3 Jan 2022 08:26:24 -0500 Subject: Major 4.0 Update (#16) See Changelog --- docs/file.README.html | 212 +++++++++++++++++++++++++++++--------------------- 1 file changed, 125 insertions(+), 87 deletions(-) (limited to 'docs/file.README.html') diff --git a/docs/file.README.html b/docs/file.README.html index b856937..f62e0db 100644 --- a/docs/file.README.html +++ b/docs/file.README.html @@ -57,7 +57,9 @@
-

FelFlame

+

FelFlame

+ +

Maintainability Test Coverage @@ -74,11 +76,12 @@

  • What is FelFlame?
  • What is ECS? - - Components - - Entities - - Systems - - Scenes - - Stage
  • + * Components + * Entities + * Systems + * Scenes + * Stage + * Order
  • Usage
      @@ -87,7 +90,6 @@
    • Contribution
    • @@ -143,7 +149,7 @@
      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. 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. -
      4. Priciple 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.
      5. +
      6. 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.

      What is ECS?

      @@ -169,7 +175,7 @@ ECS stands for Entity, Component, and System.

      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 and a Stage, what is that about?"

      +

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


      @@ -181,13 +187,19 @@ ECS stands for Entity, Component, and System.

      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

      -

      If all of this sounds very confusing, don't worry. A video tutorial series is in the works where I will build a game using this framework and explain every step of the way. You can also read some examples and explanations below.

      +

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

      + +

      Usage

      -

      To use FelFlame simply install the gem using gem install felflame or using bundler bundle add felflame and then require it in your project like so: require 'felflame'. Working outside of the gem for rendering engines that do not support the usage of gems is a planned feature in the works.

      +

      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.

      + +

      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.

      Entities

      @@ -195,32 +207,27 @@ ECS stands for Entity, Component, and System.

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

      -
      @entity = FelFlame::Entities.new
      +
      @entity = FelFlame::Entities.new
       
      -

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

      +

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

      -
      @entity = FelFlame::Entites.new(
      -  FelFlame::Components::Health.new,
      +
      @entity = FelFlame::Entites.new(
      +  FelFlame::Components::Health.new,
         @component,
      -  FelFlame::Components::Armour[7]
      +  FelFlame::Components::EnemyTeam.first
       )
       

      Accessing

      -

      Once components are created we can access them using their ID like so:

      - -
      @entity = FelFlame::Entities[2]
      -
      - -

      Get ID

      - -

      Entity ID's are generated starting from 0 and ascending, unless if there is a missing ID because of a deleted -entity where a new entity will claim that ID. To get the ID of an Entity:

      +

      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.id
      -
      +
      @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
      +

      Adding and Removing Components

      @@ -232,14 +239,18 @@ entity where a new entity will claim that ID. To get the ID of an Entity:

      Accessing Entities' Attached Components

      +

      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:

      -
      @entity.components[@component_manager] # => [@component1, @component2, component3]
      +
      @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.

      @entity.delete
       
      @@ -251,7 +262,7 @@ entity where a new entity will claim that ID. To get the ID of an Entity:

      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)
      +
      @component_manager = FelFlame::Components.new('Stats', :armour, hp: 100)
       

      In this example we created a component manager called "Stats". @@ -265,22 +276,21 @@ When defining attributes symbols should be used.

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

      -
      @component = FelFlame::Components::Stats.new
      +
      @component = FelFlame::Components::Stats.new
       
      -

      Or we can even change the defaults:

      +

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

      -
      @component = FelFlame::Components::Stats.new(armour: 'steel')
      +
      @component = FelFlame::Components::Stats.new(armour: 'steel')
       
      -

      Accessing and Getting ID

      +

      Accessing

      -

      Just like Entities, Components have IDs. -These IDs are only unique within the scope of their respective Component Managers. -Here is how we can get the ID, as well as how to access a Component from its Component Manager.

      +

      You can access components using any array method.

      -
      @component = FelFlame::Components::Stats[2]
      -@component.id # => 2
      +
      @component = FelFlame::Components::Stats[2]
      +@component = FelFlame::Components::Stats.first
      +@component = FelFlame::Components::Stats.each # you can use iterators this way
       

      Accessing Attributes and Changing Them

      @@ -293,30 +303,26 @@ Here are the ways to edit attrubutes, followed by the ways to read them.

      @component.hp # => 95
      -@component.attrs # => {armour: 'Leather', hp: 95}
      +@component.to_h # => {armour: 'Leather', hp: 95}
       

      Deleting Components

      -

      Deleting a Component is the same format 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
       
      -

      Iterating over Components

      - -

      When you make Systems you will want to be able to iterate over all Components of the same Component Manager(for example iterating over all sprites to render them). Here is how we do that:

      - -
      FelFlame::Components::Sprites.each do |component|
      -  #do something with components
      -end
      -
      -

      Accessing Components' attached Entities

      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
       

      Systems

      @@ -325,24 +331,26 @@ Here are the ways to edit attrubutes, followed by the ways to read them.

      We can create Systems like so:

      -
      FelFlame::Systems.new(name: 'Render', priority: 2) do
      +
      FelFlame::Systems.new('Render', priority: 2) do
         # Code and Logic
       end
       

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

      -
      FelFlame::Systems::Render
      +
      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.

      +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.

      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(name: 'Render', priority: 2) do
      -  FelFlame::Components::Sprites.each do |component|
      +
      FelFlame::Systems.new('Render', priority: 2) do
      +  FelFlame::Components::Sprites.each do |component|
           # do something with these components
         end
       end
      @@ -352,7 +360,7 @@ E.g priority 1 will go first, priority 2 will go second, etcetera.  

      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
      +
      FelFlame::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.

      @@ -362,25 +370,25 @@ E.g priority 1 will go first, priority 2 will go second, etcetera.

      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:

      # When this Component is added to an Entity, this System will be called
      -FelFlame::Systems::PassiveRegen.trigger_when_added(@component)
      +FelFlame::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)
      +FelFlame::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)
      +FelFlame::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:

      # 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)
      +FelFlame::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)
      +FelFlame::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)
      +FelFlame::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

      @@ -390,41 +398,41 @@ E.g priority 1 will go first, priority 2 will go second, etcetera.

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

      # clears ALL triggers with this system
      -FelFlame::Systems::PassiveRegen.clear_triggers
      +FelFlame::Systems::PassiveRegen.clear_triggers
       
       # clears ALL triggers with this Component Manager
      -FelFlame::Systems::PassiveRegen.clear_triggers(@component)
      +FelFlame::Systems::PassiveRegen.clear_triggers(@component)
       
       # clear the 'trigger_when_added' for this Component
      -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :added)
      +FelFlame::Systems::PassiveRegen.clear_triggers(@component, :added)
       
       # clear the 'trigger_when_removed' for this Component
      -FelFlame::Systems::PassiveRegen.clear_triggers(@component, :removed)
      +FelFlame::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)
      +FelFlame::Systems::PassiveRegen.clear_triggers(@component, :is_set, :health)
       

      Likewise we can do the same with Component Managers:

      # clears ALL triggers with this Component
      -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager) 
      +FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager) 
       
       # clear the 'trigger_when_added' for this Component Manager
      -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :added) 
      +FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :added) 
       
       # clear the 'trigger_when_removed' for this Component Manager
      -FelFlame::Systems::PassiveRegen.clear_triggers(@component_manager, :removed) 
      +FelFlame::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) 
      +FelFlame::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:

      -
      FelFlame::Systems::PassiveRegen.redefine do
      +
      FelFlame::Systems::PassiveRegen.redefine do
         # Some new logic or code
       end
       
      @@ -435,28 +443,36 @@ E.g priority 1 will go first, priority 2 will go second, etcetera.

      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:

      -
      @scene = FelFlame::Scenes.new('ExampleScene')
      +
      @scene = FelFlame::Scenes.new('ExampleScene', priority: 5)
       

      Accessing

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

      -
      @scene = FelFlame::Scenes::ExampleScene
      +
      @scene = FelFlame::Scenes::ExampleScene
       

      Adding 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)
      +
      FelFlame::Scenes::ExampleScene.add(
      +  FelFlame::Systems::Render,
      +  @system2,
      +  @system3
      +)
       

      Removing Systems

      -

      Removing Systems works simularly:

      +

      Removing Systems works similarly:

      -
      FelFlame::Scenes::ExampleScene.remove(FelFlame::Systems::Render, @system2, @system3)
      +
      FelFlame::Scenes::ExampleScene.remove(
      +  FelFlame::Systems::Render,
      +  @system2,
      +  @system3
      +)
       

      Clearing

      @@ -479,23 +495,45 @@ E.g priority 1 will go first, priority 2 will go second, etcetera.

      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
      +
      FelFlame::Stage.add FelFlame::Scene::ExampleScene
       

      Removing Scenes

      Likewise we can remove Scenes:

      -
      FelFlame::Stage.remove FelFlame::Scene::ExampleScene
      +
      FelFlame::Stage.remove FelFlame::Scene::ExampleScene
       

      Executing

      -

      On each frame of the game we want to execute the Stage once. When the Stage is executed it is progressing your game 1 frame forward. The Stage will make sure for you that all the Systems from all Scenes added will be executed in the correct order according to 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
      +
      + +

      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

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

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

      -
      FelFlame::Stage.call
      +
      FelFlame::Order.sort(
      +  @scene1,
      +  [@scene2_1, @scene2_2],
      +  @scene3
      +) 
       

      Closing Notes

      @@ -512,7 +550,7 @@ E.g priority 1 will go first, priority 2 will go second, etcetera.

-- cgit v1.2.3