[ARW Game] A timer for making sequences of events


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.

Leave a comment

Log in with itch.io to leave a comment.