2

Yesterday I wrote a Thread addressing how my game loop ran (in java) and how it works.

My game loop works completely, and I know why, but now I just wan't to know how to calculate FPS (Frames Per Second) and print it out every second.

I got a response yesterday about this, but he/she explained it in words and I couldn't understand it.

If anyone could help me (with a code example? :D) that would be great.

Here is my game loop:

        while (running) {

        start = System.nanoTime();

        update();
        draw();
        drawToScreen();

        elapsed = System.nanoTime() - start;

        wait = targetTime - elapsed / 1000000;
        if (wait < 0) {
            wait = 5;
        }

        try {
            Thread.sleep(wait);
        } catch (Exception e) {
            Game.logger.log("ERROR! Printing Stacktrace...");

            e.printStackTrace();
        }

    }

ALSO:

In my JFrame when ever I call setName(string) it never works/updates on the Frame - Link me to a thread?

Charles
  • 50,943
  • 13
  • 104
  • 142
SirTrashyton
  • 173
  • 2
  • 3
  • 12

2 Answers2

4

The easiest way to do this is to keep a variable whatTheLastTimeWas stored and doing this where you want to check your frame rate:

double fps = 1000000.0 / (lastTime - (lastTime = System.nanoTime())); //This way, lastTime is assigned and used at the same time.

Alternatively, you can make a FPS counter like so:

class FPSCounter extends Thread{
    private long lastTime;
    private double fps; //could be int or long for integer values

    public void run(){
        while (true){//lazy me, add a condition for an finishable thread
            lastTime = System.nanoTime();
            try{
                Thread.sleep(1000); // longer than one frame
            }
            catch (InterruptedException e){

            }
            fps = 1000000000.0 / (System.nanoTime() - lastTime); //one second(nano) divided by amount of time it takes for one frame to finish
            lastTime = System.nanoTime();
        }
    }
    public double fps(){
        return fps;
    } 
}

Then in your game, have an instance of FPSCounter and call nameOfInstance.interrupt(); when one frame is finished.

Justin
  • 24,288
  • 12
  • 92
  • 142
  • this code would make it 1 fps constantly.. need to get rid of that `Thread.sleep(1000);` lol. – SSpoke Dec 25 '13 at 08:52
  • @SSpoke Actually no it won't. the `Thread.sleep(1000);` is to wait for an interrupt. In the game class, you need an instance of `FPSCounter` and you call `nameOfInstance.interrupt();` when each frame is finished. You should read through [this](http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html). – Justin Dec 25 '13 at 20:08
  • But it looks like that infinite while loop will sleep every 1 second regardless if you call `nameOfInstance.interrupt();` or not. I would think it would be something like this `public void run() { while(true) { if(isInterrupted()) { try { Thread.Sleep(1000); } catch() {} } } }` reading that article it seems you want this thread to control the gameLoop, when this fps thread is paused you want the game loop to pause too? – SSpoke Dec 25 '13 at 22:45
  • @SSpoke No. When this thread is interrupted, the `Thread.Sleep` cancels and it moves onto the `catch(InterruptedException e)`. You should really learn more about threads. – Justin Dec 26 '13 at 01:51
  • Oh it makes sense the interrupt() forces the exception? – SSpoke Dec 26 '13 at 02:00
  • @SSpoke That's the way `interrupt()` works. You should really read the tutorial on threads/concurrency. – Justin Dec 26 '13 at 02:03
  • 2
    Haha. I chucked this right into my game and forgot to even check the code. and then wondered why my game ran at 1 FPS. – Joehot200 Dec 10 '14 at 18:53
  • @Joehot200 I would recommend that you instead use something from [this thread](http://stackoverflow.com/q/87304/1896169), since what I showed here is a very trivial way to do it. – Justin Dec 10 '14 at 19:06
  • @Quincunx That thread has stupid complicated answers which are not worth my time of day working out. I managed to get your code working but modified with a delayed task instead. Thanks! – Joehot200 Dec 10 '14 at 19:46
  • This is really useful if you need it for just debugging. It takes like 20 seconds to put in your code, and works out of the box. – Ajay Apr 23 '17 at 16:32
3

You can combine a simple counter and Timer.scheduleAtFixedRate for this.

Disclaimer: I don't know if this is the best method; it's just easy.

int totalFrameCount = 0;
TimerTask updateFPS = new TimerTask() {
    public void run() {
        // display current totalFrameCount - previous,
        // OR
        // display current totalFrameCount, then set
        totalFrameCount = 0;
    }
}

Timer t = new Timer();
t.scheduleAtFixedRate(updateFPS, 1000, 1000);

while (running) {
    // your code
    totalFrameCount++;
}
Trojan
  • 2,256
  • 28
  • 40
  • As for accessing variables: inside `run()`, you might get an error for changing `totalFrameCount`. If so, put that assignment in another function (`resetFrameCount()` perhaps), and call that function instead of making the assignment directly. I seem to remember that error coming up. – Trojan Dec 25 '13 at 06:55
  • I always felt like putting `static` in front of a global variable would make it thread-safe. – SSpoke Dec 25 '13 at 08:50
  • @SSpoke Do you have a source for that? – Trojan Dec 25 '13 at 08:55
  • Nope I've been using that static variables idea for years and never had problems with 2 threads modifying the same value. Although it says you have to use Atomic for that, if you google it, it will say static variables are extremely unsafe. But who knows where people get that stuff.. I use static methods for factory classes etc.. and those run in multiple threads never had any problems with those either. – SSpoke Dec 25 '13 at 08:58