A rudimentary entity-component system for GameMaker. Define Components and attach any Component to any Entity to have the Component's code run in the corresponding GM events. https://github.com/JonathanHackerCG/Blursed-ECS
#Blursed ECS (Entity-Component System)
1 messages · Page 1 of 1 (latest)
I am incredibly unconfident in the viability of this concept, especially for a production codebase. It seems useful, but my instincts are tingling.
I would love feedback and discussion on if this is a good/bad idea, and what potential pitfalls there are in my implementation. Or, any alternative solutions that already exist.
I will continue to develop it regardless, for my own use and especially if there is interest from others.
There is the v0.1.0-alpha version, should be fully working, but mostly untested and limited features.
hmm... this could be just a "me" thing, but i'm very much Not A Fan of using macros to create custom syntax
here some if it seems to be for the purpose of ensuring the system is created properly, which is... fine, i guess, but the bulk of it just seems to be for the purpose of... letting the user ignore invoking the constructor themselves?
That is entirely fair. I don't like it either.
In this case yeah it's just for the setup stuff, and might be overkill.
this is 99.99% identical to "function example() constructor {" at the cost of forcing the user to deal with red feather pen on every line, and learning a custom syntax
I agree I am also not a fan of that kind of thing
it is confusing and introduces a learning curve that isn't justified
I was going through hoops to avoid the user needing to define components across more than one file.
But the Component itself is simple and provided by the constructor, so a less macromagic syntax is probably possible.
It is more readable though if they are organized into separate files
and they are more intentional
Yes yes.
I want each Component in a separate file, yes. I don't want to have to also go to the "define_all_components" function and list it in there so it can be defined when the game starts.
This is partly only an issue because I like them having a "namespace" provided by COMPONENT.
Mmmm, actually I think I can do that inside the constructor too. Let me grab lunch then I'll try to rewrite it.
Final syntax might be better as:
(name would have to be a string instead, but can still make a variable out of that internally to avoid lookup after initialization)js with (new Component("example")) { INIT = function() { } //etc }Still in a script?
Or a helper function like:
define_component("example",
function() { /*INIT...*/ },
function() { /*STEP...*/ },
//etc```
that could work jsut as well
I will make adjustments.
Any thoughts about the concept itself, syntax aside?
hmm
Okay syntax looks like this now:```js
with (new Component("example"))
{
INIT = function()
{
my_string = "Hello world!";
is_activated = false;
}
STEP = function()
{
if (!is_activated)
{
show_debug_message(my_string);
is_activated = true;
}
}
DRAW = function()
{
draw_text(x, y, my_string);
}
}``` (Or any sensible variation on it).
I will probably add a helper function too.
I also changed the COMPONENT namespace instance for a macro COMPONENT that references a global variable struct instead.
I have a concern though, is it not possible that depending on the order the scripts are compiled the Component definition might happen before the Component constructor is defined? I seem to remember running into that before, which is part of where those magic macros originated from.
If I'm right, then the only safe way I know without using magic macros is wrapping it up in a second function and manually calling it at the start of the game, like ```js
function init_component_example()
{
with (new Component("example")) { ... }
}
//Then later...
function init_game()
{
init_component_example();
}
This I am trying to avoid, but maybe it's better to have users write their own magic macros if they care. Is there a better solution, or am I imaginging this issue?
Ah wait, I can do the same thing I do for COMPONENT with Component() constructor.
EDIT: No, that just introduces the same bug w/ one more layer.
Can now do this in an initialization function. js define_component("example", function() { my_string = "Hello world!"; is_activated = false; }, function() { if (!is_activated) { show_debug_message(my_string); is_activated = true; } }, function() { draw_text(x, y, my_string); });
Or alternatively, use ECS_DEFINE and ECS_DEFINE_END macros to define the Components within a global script instead. I added an error message in case the user attempts to do an unsafe definition without the macros.
ECS_DEFINE
define_component("example", ...);
ECS_DEFINE_END
But the macros are optional now, and even if you use the macros it's much simpler than before.
I think I like that approach far better
Me too. 👍
Thanks for the feedback.
Here is updated version.
I will update the documentation for new syntax, then I'll continue to work on more features until it's properly completed.
The Blursed ECS is no longer cursed.
I got everything narrowed down to a single constructor, you don't even need to call an initialization script.
Still working out methods and documentation, but a sort-of-final release will be ready soon (this weekend hopefully). Then I will use it for a while in my new project (which is what I made it for) and fix issues for a while until I'm confident it's good.
new Component("SayHello")
.add_event("INIT", function()
{
my_message = "Hello!";
is_activated = false;
})
.add_event("STEP", function()
{
if (!is_activated)
{
show_debug_message(my_message);
is_activated = true;
}
});```
Newest syntax
Alpha v0.3.0 release done with finished definition syntax (which boils down to: use the constructor provided). Also added a few helper functions, most notably component_remove so you can add and remove Components at runtime. README has updated documentation but it's a bit lazy since I wrote it fast.
I will be using this system in my newest project, as a stress test (and because that is the reason I made this in the first place). There will possibly be future updates once I figure out what changes need to be made for that project.