Muffel - New Game Maker Syntax - Say Goodbye to Alarms
A downloadable asset pack
Thanks to our Muffel asset, this is now real Game Maker code:
I'm not kidding, that's not pseudocode. I literally wrote that code into the create event of an object to make it spin. Not in the step event and without alarms*.
Isn't it beautiful?
Thanks to new in-line functions in GameMaker 2.3 and macros, we can now start a parallelly** executed code without alarms or events, in a beautiful syntax resembling simple english. We have two features:
- Delayed execution: run code-block after x seconds or frames
- Periodic execution: run code every x seconds or frames forever until you abort it
Let's say when your player is hit, you want him to be invincible for a second, you can do this:
Damn, if this isn't nice, I don't know what is.
Let's be honest, how would you have done this before? You would have either routinely checked if one second has passed in your Step-event or you would have created an alarm, written your code into the alarm event, disabled the alarm etc., just to set one variable to true.
Now you can do all of this inline!
Example usage might be everything involving "do this later" or "do this periodically":
- Create a new enemy every three seconds
- Let the screen shake for 50 frames and then stop
- When enemy is attacked, let him be confused for a few seconds
- Tower Defense: let a building fire only every five seconds
Yes, you can do all of this with alarms and step events too, but it's inconvenient and you lose track of which alarm does what and when, your step event becomes unreadable, etc.
How to install
You need Game Maker 2.3 to use this asset.
Unzip our asset file somewhere.
Open Game Maker. Go to "Tools" in the menu bar and select "Import local package". Now select the "com.ribbyte.muffel" file that was unzipped.
Notes
Read the "README.txt" file for more details, troubleshooting, how to abort the execution blocks, etc.
You might know the Coroutine feature in Unity (Invoke, StartCoroutine, WaitForSeconds or yield), with this asset you can basically solve similar problems in Game Maker.
* Internally, it still uses alarms, but you don't have to deal with alarms, set anything up and create the events etc. You don't even notice it's using alarms inside.
** It's not really parallel (as in multithreading) but it's the simplest description I have to describe the result. Look at this:
What does it print? That's right: "aaa" then "ccc" then "bbb".
Why? Because the "bbb" code is only executed two seconds later, while the main script continues. So it first prints "aaa" then "ccc" and then, two seconds later, it prints "bbb".
Basically, the code in a "execute after" or "execute every" block is executed after your script is finished. So it feels like it runs in parallel (or asynchronously).
Download
Click download now to get access to the following files:
Comments
Log in with itch.io to leave a comment.
This is awesome. I'm afraid to use it in long term projects however. What would you say about how update-friendly it is for the engine?
can't compile for some reason...
okay i found the reason why it didn't work, it was because i added it to the room lol
Hey, first i have to say this tool is really great and easy to use!
I have noticed an issue when exporting to HTML5, when using it in the draw-GUI event it causes a crash/memory leak. I havent tested it thoroughly however.
This is the code i used
( I know this code probably shouldnt be in the draw-GUI event )
this works fine on windows export, but in HTML5 it causes the game to freeze..
This isnt really a problem for me as i can just move the code to the step event, but i thought i could leave a comment anyway 😊
currently running gamemaker IDE v2023.11.1.129, runtime v2023.11.1.160
Doesn't seem to work out of the box for me (version 2023.6.0.89)
Trying to use as intended throws the GM1100 error and I assume it would throw the same error for the second, seconds, frame, and frames macros. Anyone have any thoughts on how to get around this?
I haven't looked at the script yet but this feels like an awesome abstraction. Were you able to figure out the issue by any chance? I'll take a look when I can and see if I have any ideas.
chef's kiss, seriously! this is wonderful, and surprisingly robust too. no memory leaks so far! i second @duygdkid's question however, is it possible to pause and resume these things? i noticed each timer creates an instance too, will this get messy later on?
Great tool, thank you so much for making this.
I have a question. Is it possible to pause and resume an "execute every n" actions? Because I found only the "disable" function in your tool.
ribbyte, can you look at my error log please? 🙏
ERROR in
action number 1
of Alarm Event for alarm 1
for object oPlayer:
Unable to find instance for object index -4
at gml_Script_execute_every_n_frames (line 44) - inst._interval = n
###############################
gml_Script_execute_every_n_frames (line 44)
gml_Script_execute_after_n_frames (line 51) - inst = execute_every_n_frames(n, callback)
gml_Script_execute_after_n (line 113) - execute_after_n_frames(interval, callback);
gml_Object_oPlayer_Alarm_1 (line 5) - execute after 120 frames
What could go wrong? Thanks.
Edit: I solved it, but I still don't know what caused this.
Hmm, did the object get deleted by any chance? I think I have a check if the object that’s executing the code still exists but I may have missed a check somewhere.
Alternatively, how do you create the object? You might have the same problem the other commenter had.
If you still have the old code with the bug, you can send it to me at ribbyteapps@gmail.com
Here it is:
if you still have questions, please ask
It looks like this is the same error Dave encountered in the comment below. I posted the fix there (change instance_create_depth to instance_create_layer or adjust the Muffel script the other way around, refer to the comment below for more details).
I‘m not sure yet how to fix Muffel to allow both of those functions to be used, might have to look into it later.
Very nice idea, but it is very buggy. For example: when I used this in one object, everything works well, then tried it with another object and got this error:
ERROR in
action number 1
of Create Event
for object o_element:
Unable to find instance for object index -4
at gml_Script_execute_every_n_frames (line 44) - inst._interval = n
############################################################################################
gml_Script_execute_every_n_frames (line 44)
gml_Script_execute_after_n_frames (line 51) - inst = execute_every_n_frames(n, callback)
gml_Script_execute_after_n (line 113) - execute_after_n_frames(interval, callback);
gml_Object_o_element_Create_0 (line 3) - execute after 60 frames
gml_Script_instance_create (line 7)
gml_Script_engine_ne (line 120) - ( 0 + _spc + _xplus + (i-1) * ( ( (room_width - _spc*2) / (_noeol-1)) ) ,
gml_Script_scr_new_task (line 27)
gml_Script_anon_anon_gml_Object_o_program_Create_0_1590_gml_Object_o_program_Create_0_1798_anon_gml_Object_o_program_Create_0_1590_gml_Object_o_program_Create_0 (line 53) - scr_new_task();
gml_Object_obj_muffel_Alarm_0 (line 11) - _my_callback(self);
I used very simple line in event create:
execute after 60 frames
audio_play_sound(snd_score,3,0);
done
Thanks for the report!
What I can gather from your error log is that the object which is calling the "execute after 60 frames" was deleted/destroyed in the meantime? I thought I caught all errors of that type, but I might have missed a checked somewhere. I will look into it and update when I find the error.
It would be really helpful if you could share your project with me, so I can debug it faster (you can also create a new project that reproduces the same bug). You can reach me via ribbyteapps at-symbol gmail.com
If you find any more bugs, feel free to report all of them.
I just sent you the file that reproduces this bug. The problem is, I think when you try to use Muffel system in objects that weren't put manually to the room. If the object has some muffel functions and is created by another object, then you will get the error.
Did you have time to look at the example with this error?
For completeness' sake: The bug probably occurs when using "instance_create_depth" which adds a new layer for that specific object and Muffel can't find it (due to limitations of GM). I have not heard back from Dave if this resolved his problem yet, but I would be surprised if not. If anybody else has the same problem, feel free to contact me! Here is the fix if you want to try it for yourself:
Either use "instance_create_layer" instead of "instance_create_depth" in your own script, or do the opposite in the Muffel script (replace "instance_create_layer(0, 0, layer, obj_muffel)" with "instance_create_depth(0, 0, 0, obj_muffel)")
Yep, it works. Instance_create_depth caused the problem. Sorry for not replying.
This is pure Genius! Thanks!
Glad you like it!