Blursed-ECS is a rudimentary entity-component system framework for GameMaker. This is an architectural pattern where game objects are represented as entities with attached components.
ECS is designed as an alternative (or supplement) to Object-Oriented style inheritance. Instead of deriving behavior from parents, Entities gain behavior from their attached Components. An Entity can contain any number of any Components, or none at all. This approach can be more flexible than inheritance, and resolves issues where some objects need behavior from multiple parents.
However, I am wholly unqualified to explain ECS in detail. For more details, please consult Entity Component System FAQ or Game Programming Patterns - Component.
This codebase is currently in a testing phase. Using this ECS will be less performant than native GameMaker inheritance. I do not currently recommend this system for production code.
- Download the latest release
*.yymps
. - Import the
Blursed ECS
folder. TheBlursed ECS - Example
is optional, if desired.
- To create an Entity, create an object and set
ECS_ENTITY
as its parent. - Add a Component to the Entity with
add_component(component)
. A Component uses the "namespace"COMPONENT.<name>
.
NOTE: Entities inheriting from ECS_ENTITY
must call event_inherited()
in the Create, Step, Draw, and Clean Up events in order to use Components. Alternatively, you may use ECS_call_events()
to specifically call the Component events in the corresponding GML events. This approach does not require ECS_ENTITY
.
A Component is a struct containing a list of events and associated functions.
- The
INIT
,STEP
,DRAW
, andCLEAN_UP
events are supported by default byECS_ENTITY
. - The
INIT
event is special, and will also be called when usingcomponent_add()
. - The
CLEAN_UP
event is special, and will also be called when usingcomponent_remove()
.
You can create a Component with the Component(name)
constructor. For each Component, use add_event()
to add functions to the Component's events. Components are stored globally in a COMPONENT
singleton.
Component.get_id()
Returns a unique numerical ID for this Component. Only useful internally.Component.get_name()
Returns the name of this Component as a string.Component.add_event(event, function)
Adds a function as an event for this Component.Component.get_event(event)
Returns an associated function by event name for this Component.
ECS_init_entity()
Initialize an Entity to provide required ECS variables. Called automatically bycomponent_add()
.ECS_call_events(event)
Calls a specified event (string) for all Components attached to this Entity. Example:ECS_call_events("DRAW")
should be put in the draw event.component_add(component, [call_INIT])
Adds a Component byCOMPONENT.<name>
. By default, also calls theINIT
event for that Component.component_attached(component)
Returns true if a Component is attached.component_remove(component, [call_CLEAN_UP])
Removes a Component byCOMPONENT.<name>
. By default, also calls theCLEAN_UP
event for that Component.component_call_event(component, event)
Manually calls a specific event for a Component. Much slower thanECS_call_events()
.components_count()
Returns the number of Components attached to an Entity.components_list()
Returns an Array of all attached Components (as structs). Only intended for debugging purposes.
This example Component. This Component will result in "Hello world!" printed once per instance of that Entity in the console.
//Script
with (new Component("HelloWorld"))
{
add_event("INIT", function()
{
my_string = "Hello world!";
is_activated = false;
});
add_event("STEP", function()
{
if (!is_activated)
{
show_debug_message(my_string);
is_activated = true;
}
});
}
//Create Event
add_component(COMPONENT.HelloWorld);
The following features are being considered for future development:
- Enforcing the order that Components are executed.
- Accessing all instances with a specific Component.
- Optional reference by string name instead of COMPONENT.name.
- Performance testing and optimizations, if possible.