0
\$\begingroup\$

I making a game and I want to call a function that runs every random second to spawn something every time. I've seen some posts that said to use the setInterval() function to keep track of the time but I don't know where to implement it because I'm using the requestAnimationFrame() to loop the game. I also tried to implement it in the update function of the classes but it doesn't seem to work.

This is my main with the loop

import Game from '/src/game.js';

let canvas = document.getElementById('main');
let ctx = canvas.getContext('2d');

const WIDTH_SCREEN = 800;
const HEIGTH_SCREEN = 600;

let game = new Game(WIDTH_SCREEN, HEIGTH_SCREEN);   
game.start();

function loop() {
    ctx.clearRect(0, 0, WIDTH_SCREEN, HEIGTH_SCREEN);

    game.update(ctx);

    requestAnimationFrame(loop);
}

window.addEventListener("keydown", (event) => game.controller.keyListener(event));
window.addEventListener("keyup", (event) => game.controller.keyListener(event));
requestAnimationFrame(loop);
\$\endgroup\$
  • \$\begingroup\$ What is the goal? Execute every n ms, throughout lifetime? Have you tried to put it next to other game/window setup code? \$\endgroup\$ – wondra Aug 13 '20 at 21:21
  • 1
    \$\begingroup\$ I recommend separating the game logic from the rendering logic, it's bad practice to keep them together \$\endgroup\$ – Ameer Aug 14 '20 at 0:27
  • \$\begingroup\$ What you could do is in your game class add a property called tickNum or something, and set it equal to a random number between m and n. Then every time the game loop is called subtract one from that property and if it equals 0 spawn a new object and add another random value to the tickNum property. \$\endgroup\$ – Ameer Aug 14 '20 at 0:30
  • \$\begingroup\$ That worked perfectly thank you. \$\endgroup\$ – Nicolas Pizzarelli Aug 16 '20 at 13:52
0
\$\begingroup\$

I don't know JavaScript, but why not implement something like this?

var lastCalled = 0;

function loop() {
  // do some staff
  if (((currentTimeMillis - lastCalled) / 1000) >= n) {
    // time to call your function
    // ...
    lastCalled = currentTimeMillis;
  }
}

But in this way your function might not be called exactly once per n seconds.

\$\endgroup\$
0
\$\begingroup\$

You can pass an optional time parameter to your window.requestAnimationFrame() callback (loop() in this case), and it will pass in the current amount of time (in milliseconds) since the first frame. You can create a timer object to take advantage of that:

const Timer = (event, interval = 0) => {
    let last = 0;
    let total = 0;
    return {
        set interval(newInterval)
        {
            interval = newInterval;
        },
        update(time = 0) {
            total += time - last;
            if (total >= interval) {
                event(this);
                total = 0;
            }
            last = time;
        }
    };
};

Now you can do this:

const fooLogger = Timer((timer) => {
    console.log('foo!');
    timer.interval = 1000 + Math.floor(Math.random()) * 1000;
}, 1500);
function loop(time) {
    requestAnimationFrame(loop);
    fooLogger.update(time);
}
requestAnimationFrame(loop);

And this should log "foo!" every 1 - 2 seconds. Update: The question specified a variable interval, that has been added.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.