Coroutines, by extending GML's syntax

Juju

Member
This'll be a brief post, library is here: https://github.com/JujuAdams/Coroutines

About a week ago in bed I sketched out a function-based system to create a very simple virtual machine that executes (standard) GML functions in a coroutine pattern; that is, each coroutine instance is a virtual machine and can be paused/resumed at will. After working on it for a little while, trying it out in practice, I realised that it would be clumsy to use by typing out functions for every chunk of code so I developed a macro system that expands standard GML syntax into something that can express this sort of flow:

Code:
function ShootFireball(_x, _y, _targetX, _targetY)
{
    CO_PARAMS.x = _x;
    CO_PARAMS.y = _y;
    CO_PARAMS.targetX = _targetX;
    CO_PARAMS.targetY = _targetY;
 
    return CO_BEGIN
        fireball = instance_create_depth(x, y, 0, oFireball);
        fireball.vspeed = -5;

        //Wait until the fireball has risen above its origin by 30 pixels
        AWAIT fireball.y <= fireball.ystart - 30 THEN

        //Then shoot the fireball at the target!
        fireball.direction = point_direction(x, y, targetX, targetY);
        fireball.speed = 11;
    CO_END
}
Code:
function FetchScores(_leaderboard)
{
    CO_PARAMS.leaderboardID = _leaderboard;
 
    return CO_BEGIN
        show_debug_message("Starting leaderboard pull");
        handle = steam_download_scores(leaderboardID, 1, 10);

        ASYNC_AWAIT_STEAM
            if (async_load < 0)
            {
                show_debug_message("Leaderboard request timed out");
            }
            else if (async_load[? "id"] == handle)
            {
               show_debug_message("Leaderboard data received");
                global.scores = array_resize(0);

                var _list = map[? "entries"];
                var _i = 0;
                repeat(ds_list_size(_list))
                {
                    var _data = _list[| _i];
                    array_push(global.scores, {name : _data[? "name"], score : _data[? "score"], rank : _data[? "rank"]});
                    _i++;
                }

                ASYNC_COMPLETE
            }
        TIMEOUT 10000 THEN

        show_debug_message("Leaderboard pull complete");
    CO_END
}
There's a bunch of stuff that can be done with coroutines, not least cutscenes and animations. Documentation is here: https://github.com/JujuAdams/Coroutines/wiki

Enjoy
 

Juju

Member
Now in stable release (https://github.com/JujuAdams/Coroutines/releases/) with some extras added:

- Adds syntax checker to help guide you with coroutines
- FOREACH can now iterate over instances of objects, much like GameMaker's native with() loops
- Adds CONTINUE command to help with loop writing
- DELAY can now operate in per-frame or per-millisecond modes
- Adds macro to control behaviour of orphaned coroutines
- Lots of bug fixes
 
Last edited:
Top