Search code examples
javascripttimeframe-rategame-loopdelta

game loop delta time is not working with specified fps


Somehow deltaTime is usually 0.01667s (60fps) even though targetFrameRate is 30 (0.03333s), and yes targetFrameRate is working(adding delay). This makes movement code not work as intended with the specified fps when it is greater than or less than 60, making velocity * deltaTime broken.

Problem: deltaTime is always in 60fps and is not affected by targetFrameRate

Here's my code

// Initializes the game loop
window.onload = () => {
    PlayerLoop.init();
};

// Gets called every frame
function Update ()
{
    console.log(Time.deltaTime);
}

// The specified fps
const targetFrameRate = 30;

// Class that holds time
class Time
{
    static unscaledTime = 0;
    static unscaledDeltaTime = 0;
    static timeScale = 1;
    static frameCount = 0;
    static time = 0;
    static deltaTime = 0;
    static maximumDeltaTime = 0.3333333;
}

// Game loop class
class PlayerLoop
{
    static #accumulator = 0;
    
    static #requestUpdate ()
    {
        requestAnimationFrame(this.#update.bind(this));
    }
    
    static #update ()
    {
        Time.unscaledDeltaTime = (performance.now() / 1000) - Time.unscaledTime;
        Time.unscaledTime += Time.unscaledDeltaTime;
        
        var deltaT = Time.unscaledDeltaTime;
        
        if (deltaT > Time.maximumDeltaTime) deltaT = Time.maximumDeltaTime;
        
        Time.deltaTime = deltaT * Time.timeScale;
        Time.time += Time.deltaTime;
        
        this.#accumulator += Time.deltaTime;
        
        while (this.#accumulator >= 1 / (targetFrameRate))
        {
            Time.frameCount++;
            
            Update();
            
            this.#accumulator -= 1 / (targetFrameRate);
        }
        
        // Render
        
        this.#requestUpdate();
    }
    
    static init ()
    {
        this.#requestUpdate();
    }
}

Solution

  • I've fixed it thanks to Annas

    My code was missing another delta time that will tell when to update the global Time.deltaTime variable

    Here's My New Code

    // Initializes the game loop
    window.onload = () => {
        PlayerLoop.init();
    };
    
    // Gets called every frame
    function Update ()
    {
        console.log(Time.deltaTime);
    }
    
    // The specified fps
    const targetFrameRate = 30;
    
    // Class that holds time
    class Time
    {
        static unscaledTime = 0;
        static unscaledDeltaTime = 0;
        static timeScale = 1;
        static frameCount = 0;
        static time = 0;
        static deltaTime = 0;
        static maximumDeltaTime = 0.3333333;
    }
    
    // Game loop class
    class PlayerLoop
    {
        static #requestUpdate ()
        {
            requestAnimationFrame(this.#update.bind(this));
        }
        
        static #update ()
        {
            // Frame rate - anti delay value
            const slice = (1 / targetFrameRate) - 0.005;
            
            // This is the "other delta time"
            let accumulator = (performance.now() / 1000) - Time.unscaledTime;
            
            while (accumulator >= slice)
            {
                Time.unscaledDeltaTime = (performance.now() / 1000) - Time.unscaledTime;
                Time.unscaledTime += Time.unscaledDeltaTime;
                
                let deltaT = Time.unscaledDeltaTime;
                
                if (deltaT > Time.maximumDeltaTime) deltaT = Time.maximumDeltaTime;
                
                Time.deltaTime = deltaT * Time.timeScale;
                Time.time += Time.deltaTime;
                
                Time.frameCount++;
                
                Update();
                
                accumulator -= slice;
            }
            
            // Render
            
            this.#requestUpdate();
        }
        
        static init ()
        {
            this.#requestUpdate();
        }
    }
    

    I have removed PlayerLoop.#accumulator and added accumulator as the "other delta time". Then I moved all of the Time update code to the inside of the while loop.

    Thank you for everyone who helped