Calculating frames per second in a game

后端 未结 19 640
天命终不由人
天命终不由人 2020-12-04 05:10

What\'s a good algorithm for calculating frames per second in a game? I want to show it as a number in the corner of the screen. If I just look at how long it took to render

相关标签:
19条回答
  • 2020-12-04 05:53

    Set counter to zero. Each time you draw a frame increment the counter. After each second print the counter. lather, rinse, repeat. If yo want extra credit, keep a running counter and divide by the total number of seconds for a running average.

    0 讨论(0)
  • 2020-12-04 05:54

    This is what I have used in many games.

    #define MAXSAMPLES 100
    int tickindex=0;
    int ticksum=0;
    int ticklist[MAXSAMPLES];
    
    /* need to zero out the ticklist array before starting */
    /* average will ramp up until the buffer is full */
    /* returns average ticks per frame over the MAXSAMPLES last frames */
    
    double CalcAverageTick(int newtick)
    {
        ticksum-=ticklist[tickindex];  /* subtract value falling off */
        ticksum+=newtick;              /* add new value */
        ticklist[tickindex]=newtick;   /* save new value so it can be subtracted later */
        if(++tickindex==MAXSAMPLES)    /* inc buffer index */
            tickindex=0;
    
        /* return average */
        return((double)ticksum/MAXSAMPLES);
    }
    
    0 讨论(0)
  • 2020-12-04 05:55

    Well, certainly

    frames / sec = 1 / (sec / frame)
    

    But, as you point out, there's a lot of variation in the time it takes to render a single frame, and from a UI perspective updating the fps value at the frame rate is not usable at all (unless the number is very stable).

    What you want is probably a moving average or some sort of binning / resetting counter.

    For example, you could maintain a queue data structure which held the rendering times for each of the last 30, 60, 100, or what-have-you frames (you could even design it so the limit was adjustable at run-time). To determine a decent fps approximation you can determine the average fps from all the rendering times in the queue:

    fps = # of rendering times in queue / total rendering time
    

    When you finish rendering a new frame you enqueue a new rendering time and dequeue an old rendering time. Alternately, you could dequeue only when the total of the rendering times exceeded some preset value (e.g. 1 sec). You can maintain the "last fps value" and a last updated timestamp so you can trigger when to update the fps figure, if you so desire. Though with a moving average if you have consistent formatting, printing the "instantaneous average" fps on each frame would probably be ok.

    Another method would be to have a resetting counter. Maintain a precise (millisecond) timestamp, a frame counter, and an fps value. When you finish rendering a frame, increment the counter. When the counter hits a pre-set limit (e.g. 100 frames) or when the time since the timestamp has passed some pre-set value (e.g. 1 sec), calculate the fps:

    fps = # frames / (current time - start time)
    

    Then reset the counter to 0 and set the timestamp to the current time.

    0 讨论(0)
  • 2020-12-04 05:55

    Here's a complete example, using Python (but easily adapted to any language). It uses the smoothing equation in Martin's answer, so almost no memory overhead, and I chose values that worked for me (feel free to play around with the constants to adapt to your use case).

    import time
    
    SMOOTHING_FACTOR = 0.99
    MAX_FPS = 10000
    avg_fps = -1
    last_tick = time.time()
    
    while True:
        # <Do your rendering work here...>
    
        current_tick = time.time()
        # Ensure we don't get crazy large frame rates, by capping to MAX_FPS
        current_fps = 1.0 / max(current_tick - last_tick, 1.0/MAX_FPS)
        last_tick = current_tick
        if avg_fps < 0:
            avg_fps = current_fps
        else:
            avg_fps = (avg_fps * SMOOTHING_FACTOR) + (current_fps * (1-SMOOTHING_FACTOR))
        print(avg_fps)
    
    0 讨论(0)
  • 2020-12-04 05:55
    qx.Class.define('FpsCounter', {
        extend: qx.core.Object
    
        ,properties: {
        }
    
        ,events: {
        }
    
        ,construct: function(){
            this.base(arguments);
            this.restart();
        }
    
        ,statics: {
        }
    
        ,members: {        
            restart: function(){
                this.__frames = [];
            }
    
    
    
            ,addFrame: function(){
                this.__frames.push(new Date());
            }
    
    
    
            ,getFps: function(averageFrames){
                debugger;
                if(!averageFrames){
                    averageFrames = 2;
                }
                var time = 0;
                var l = this.__frames.length;
                var i = averageFrames;
                while(i > 0){
                    if(l - i - 1 >= 0){
                        time += this.__frames[l - i] - this.__frames[l - i - 1];
                    }
                    i--;
                }
                var fps = averageFrames / time * 1000;
                return fps;
            }
        }
    
    });
    
    0 讨论(0)
  • 2020-12-04 05:57

    In Typescript, I use this algorithm to calculate framerate and frametime averages:

    let getTime = () => {
        return new Date().getTime();
    } 
    
    let frames: any[] = [];
    let previousTime = getTime();
    let framerate:number = 0;
    let frametime:number = 0;
    
    let updateStats = (samples:number=60) => {
        samples = Math.max(samples, 1) >> 0;
    
        if (frames.length === samples) {
            let currentTime: number = getTime() - previousTime;
    
            frametime = currentTime / samples;
            framerate = 1000 * samples / currentTime;
    
            previousTime = getTime();
    
            frames = [];
        }
    
        frames.push(1);
    }
    

    usage:

    statsUpdate();
    
    // Print
    stats.innerHTML = Math.round(framerate) + ' FPS ' + frametime.toFixed(2) + ' ms';
    

    Tip: If samples is 1, the result is real-time framerate and frametime.

    0 讨论(0)
提交回复
热议问题