Company logo
  • Jobs
  • Bootcamp
  • About Us
  • For professionals
    • Home
    • Jobs
    • Courses
    • Questions
    • Teachers
    • Bootcamp
  • For business
    • Home
    • Our process
    • Plans
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Calculator

0

100
Views
Javascript simple game loop - how to interval?

I have a simple game loop that goes like this:

function update(progress){
    //do something each second

    //do something else twice per second

    //do something else each two seconds
}

function draw() {
  //code here...
}

function gameLoop(timestamp) {

  update(progress)
  draw()
  
  var progress = (timestamp - lastRender)
  lastRender = timestamp

  window.requestAnimationFrame(gameLoop)
}

var lastRender = 0
window.requestAnimationFrame(gameLoop)

How can I make sure to execute some actions into the update function each helf second, second, or two seconds?

Thank you

7 months ago · Juan Pablo Isaza
3 answers
Answer question

0

If you want to define the interval, you'll need to use setInterval. requestAnimationFrame will only update based on the refresh rate of the screen so you cannot define your own interval with this. setInterval has lots of downsides though, so it is recommended to sync up the interval with the refresh rate using something like this:

let doUpdate = false
setInterval(() => doUpdate = true), 1000)
const render = () => {
  if (doUpdate) {
    // your code
    doUpdate = false
  }
}
window.requestAnimationFrame(render)
7 months ago · Juan Pablo Isaza Report

0

If you want to perform an action periodically when using game loop based on delta time, the basic idea is for you to keep a counter of the elapsed time. For each iteration, you then add the time difference until it reaches the intended period.

Applied to your code, it would look something like this:

let oneSecondCounter = 0
let twoSecondCounter = 0
function update(progress){
    oneSecondCounter += progress
    if (oneSecondCounter >= 1000) {
        // Code here will be executed every 1000ms
        oneSecondCounter = 0
    }

    twoSecondCounter += progress
    if (twoSecondCounter >= 2000) {
        // Code here will be executed every 2000ms
        twoSecondCounter = 0
    }
}

function draw() {}

function gameLoop(timestamp) {
  var progress = (timestamp - lastRender)

  update(progress)
  draw()

  lastRender = timestamp

  window.requestAnimationFrame(gameLoop)
}

var lastRender = performance.now()
window.requestAnimationFrame(gameLoop)

However, this means you have to make a counter variable for every periodic action you want to perform. Instead of creating a separate variable, we can bundle the counter together with the function using a closure. The closure lets each function to have their own independent counter.

The closure that we are going to use looks like this:

function initPeriodicFunction(fn, runEvery) {
    let counter = 0
    return function (deltaTime) {
        counter += deltaTime
        if (counter >= runEvery) {
            fn()
            counter = 0
        }
    }
}

Now, instead of having to create a counter variable for each action, we can just pass a function to the initPeriodicFunction and get a new function which will run only periodically.

//  You can use an arrow function
const runEverySecond = initPeriodicFunction(() => console.log('One second'), 1000)

//  Or you can pass a function
function runThis() {
    console.log('Two seconds')
}
const runEveryTwoSeconds = initPeriodicFunction(runThis, 2000)

function update(progress){
    runEverySecond(progress)
    runEveryTwoSeconds(progress)
}

Depending on your use case, the method above might be enough. If you're going to perform a more accurate tasks (e.g. physics engine), it would be better to separate the frame rate from the update rate. This is similar to how Unity's FixedUpdate works.

Imagine you want to perform a physics update every 100ms. If somehow the update call was delayed, for example 600ms after the last update, instead of performing a single update, we perform 6 updates, each with 100ms chunk. This results in more precise step-by-step calculation.

To perform this kind of fixed update, the initialization function need to be modified as follows:

function initPeriodicFunction(fn, runEvery) {
    let counter = 0
    return function (deltaTime) {
        counter += deltaTime
        while (counter >= runEvery) {
            fn()
            counter -= runEvery
        }
    }
}

Now, the function will be run either once or multiple times depending on how long has elapsed since the last update call.

7 months ago · Juan Pablo Isaza Report

0

setInterval(function {
  //code that happends every second goes here
}, 1000);

use setInterval().

This creates a timer and will call the function every x seconds.

7 months ago · Juan Pablo Isaza Report
Answer question
Find remote jobs