[ARW Game] A timer for making sequences of events

in Game Development2 years ago

Back to A Ruthless World

Been back at working with ARW this week. It has mainly been about cleaning up and making proper implementations of everything that was added during the game jam week.

But there has also been time for adding in more functionality, one new thing in particular turned out quite well.

waitDo.png


waitDo

waitDo is a timer class that is useful when making games and wanting to create a sequence of events. It can also be used to easily make an update loop for something specific and have it nicely contained in that particular area.

Let's take some examples of using waitDo vs the standard javascript timers.

setTimeout(() => console.log("Javascript after 1000ms"), 1000);

// vs

waitDo(1000, () => console.log("waitDo after 1000ms"));

So far near identical. I switched the order to match the naming wait ... do.

setInterval(() => console.log("Javascript repeating every 1000ms"), 1000);

// vs

waitDo(1000, (props) => {
    console.log("waitDo repeating every 1000ms");

    props.repeat = true;
});

Again, near identical. But waitDo is more cumbersome to use it seems.

setTimeout(() => {
    setInterval(() => console.log("Javascript wait 1000ms, then repeat every 500ms"), 500);
}, 1000);


// vs

waitDo(1000, (props) => {
    console.log("waitDo wait 1000ms, then repeat every 500ms");

    props.wait = 500;
    props.repeat = true;
});

Seeing a possible benefit emerge. You will have to start nesting timeout and interval, or start to create your own timer solution for doing more advanced patterns. Let's say you want to do different things at different times. The best solution to move forward with vanilla javascript is to start using requestAnimationFrame.

// Using requestAnimationFrame to do different things and limit how many times to repeat.

// Some variables to keep track.
let wait = 1000;
let repeat = 1500;
let repeatCount = 0;

// A timer that repeats by constantly calling requestAnimationFrame.
const jsTimer = (ms: number) => {
    if (ms >= wait && wait != -1) {
        console.log("Javascript first waited 1000 ms.");

        wait = -1;
    }
    else if (ms >= repeat) {
        console.log("Javascript then repeat 5 times every 500 ms.");

        repeat = ms + 500;

        if (++repeatCount > 4) repeat = -1;
    }

    if (repeat != -1) requestAnimationFrame(jsTimer);
}

// Start the timer.
jsTimer(0);

// vs

waitDo(1000, (props) => {
    if (props.wait == 1000) {
        console.log("waitDo first waited 1000 ms.");

        props.repeat = true;
    }
    else {
        console.log("waitDo then repeat 5 times every 500 ms.");

        props.count = props.count ? ++props.count : 1;

        if (props.count > 4) props.repeat = false;
    }

    props.wait = 500;
});

Here it starts to get interesting. The supplied props object in waitDo can contain any property
you like, making it a breeze to do a counter or to store anything else.

The waitDo callback provides more parameters and properties in the prop object. For example it provides the frame delta and frame time. By making a waitDo with a wait time of 0 you can create an update loop directly where you need it, which in some cases might be a good solution compared to creating new properties or methods to be called in the regular class update.

The final benefit, and the actual key to make this a timer for sequences, is that waitDo takes multiple callbacks. Lets have a final example where it is all put together.

// Not doing a vanilla example.

// vs

waitDo(1000,
    (props) => {
        console.log("Waited 1000ms. Start playing a sound.");

        props.sound = "A sound.";
        props.sound.play();

        props.wait = 250;
    },
    (props, delta) => {
        console.log("Waited 250ms. Fade in an image.");

        props.repeat = true;
        props.wait = 0;

        if (!props.image) {
            props.image = "An image.";
            props.image.alpha = 0;
        }
        else {
            props.image.alpha += 0.01 * delta;

            if (props.image.alpha >= 1) props.repeat = false;
        }
    },
    (props) => {
        console.log("Image fully visible, create a particle effect.");

        props.particle = "A particle.";
        props.particle.emit();

        props.wait = 500;
    },
    (props, delta) => {
        console.log("Waited 500ms. Start fading out image.");

        props.wait = 0;
        props.repeat = true;

        props.image.alpha -= 0.01 * delta;
        
        if (props.image.alpha <= 0) props.repeat = false;
    },  
    (props) => {
        console.log("Image fully hidden. Stop sound.");

        props.sound.stop();

        props.destroyCb = (props) => {
            console.log("waitDos can have a destroy callback that is called when wanted.");

            props.sound.destroy();
            props.particle.destroy();
            props.image.destroy();
        }
    }
);

This and more is possible. The waitDo class and usage examples can be found at GitHub.



Spelmakare is game development using web technologies.

Spelmakare.se
Discord
GitHub
Play ARW
Play Hive P v. S

Sort:  

Congratulations @smjn! You have completed the following achievement on the Hive blockchain and have been rewarded with new badge(s):

You received more than 6000 HP as payout for your posts, comments and curation.
Your next payout target is 7000 HP.
The unit is Hive Power equivalent because post and comment rewards can be split into HP and HBD

You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

Check out the last post from @hivebuzz:

We have finished upgrading our website
Our Hive Power Delegations to the April Power Up Month Winners
Support the HiveBuzz project. Vote for our proposal!