Making a FPS shower? [closed]

2019-02-19 01:44发布

问题:

I am trying to make a string with FPS showing, but, how do I actually get my programs FPS? I want to do it with

g.drawString(getFPS(), 10, 10)

How do I get my FPS?

回答1:

This code does it for me. Put it in your main program loop:

//To Measure FPS
private long now;
private int framesCount = 0;
private int framesCountAvg=0; 
private long framesTimer=0;

//Main Game Loop
    while (isRunning)
    {
        //Record the time before update and draw
        long beforeTime = System.nanoTime();
        //... Update program & draw program...
        // DRAW FPS: 
        now=System.currentTimeMillis(); 
        gEngine.drawFPS(c, framesCountAvg);
        framesCount++; 
        if(now-framesTimer>1000)
        { 
              framesTimer=now; 
              framesCountAvg=framesCount; 
              framesCount=0; 
        }}

that call "gEngine.drawFPS" just tells my main draw method to include the fps at the top of the screen (and c is my Canvas) - you can use a similar method to give your "g" class the correct framesCountAvg data to draw



回答2:

Calculate the time elapsed and 1000/elapsedTime will be your fps.



回答3:

Although this question sounds a little bit vague, I'll still try my best and answer it. As the original post dates back to 2011 then OP will most likely not benefit from my answer. Hopefully it'll provide better footing for those who follow, though (the previous 2 answers seem a bit too messy and laconic).

Here's a code snippet that I've often used for collecting and displaying the frame rate of various Java GUI applications:

public class FrameRateCounter {

    private Map<Long, Long> measurementTimes;


    public FrameRateCounter() {
        measurementTimes = new HashMap<Long, Long>();
    }

    public synchronized void submitReading() {
        long measurementTime = System.nanoTime();
        long invalidationTime = System.nanoTime() + 1000000000;
        measurementTimes.put(measurementTime, invalidationTime);
    }

    public int getFrameRate() {
        performInvalidations();
        return measurementTimes.size();
    }

    private synchronized void performInvalidations() {
        long currentTime = System.nanoTime();
        Iterator<Long> i = measurementTimes.keySet().iterator();
        while(i.hasNext()) {
            long measurementTime = i.next();
            long invalidationTime = measurementTimes.get(measurementTime);
            if(invalidationTime < currentTime) {
                i.remove();
            }
        }
    }
}

The obvious advantages of my approach (with regards to the previous solutions) are:

  1. Separation of concerns - you don't want trivial things like FPS count calculations polluting the 'main loop' of your program. Thus, isolate this logic into a separate component/class.
  2. Independence of the GUI component framework - it is best to steer clear of framework-dependent solutions whenever possible. In the current case this is easy - just avoid referencing things like Graphics or JLabel amongst the calculations and you're good.
  3. All measurements stored in a hashmap - Hashmaps are known for their quick look-up times (the time complexity is nearly O(1)). Thus, doing the necessary comparisons should not have any noticeable impact on the overall performance of your application.
  4. Can be used with multiple javax.Swing.Timers or threads - call submitReading() on the timer/thread whose performance you are trying to assess while running getFrameRate() from another timer/thread to get the result (for example - you could write it to a JLabel, file, etc).

(PS.: Note that with Swing, all painting operations need to be completed on the Event Dispatcher Thread (EDT). Thus, no drawing work should be delegated to other (raw) threads without the use of special commands such as SwingUtilities.invokeLater(..)).

Hope this helps!