Calculate FPS in Java Game [duplicate] - java

This question already has answers here:
Calculating frames per second in a game
(21 answers)
Closed 9 years ago.
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?

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.

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++;
}

Related

How to make fixed timestep in Java

How should we make fixed timestep in Java? I think there are 2 ways:
Synchronised game loop using while.
Asynchronised game loop using Thread.
The most important thing is performance and accuracy. So what's the best way?
This is synchronised game loop:
double timeStep = world.getSettings().getStepFrequency();
long lastTime = System.nanoTime();
while (true) {
long currentTime = System.nanoTime();
double elapsedTime = (currentTime - lastTime) / 1000000000.0;
if (elapsedTime >= timeStep) {
lastTime = currentTime;
world.update(elapsedTime);
}
}
This is asynchronised game loop:
double timeStep = world.getSettings().getStepFrequency();
long lastTime = System.nanoTime();
Thread loop = new Thread() {
public void run() {
while (true) {
long currentTime = System.nanoTime();
double elapsedTime = (currentTime - lastTime) / 1000000000.0;
lastTime = currentTime;
world.update(elapsedTime);
try {
Thread.sleep((long) Math.floor(timeStep * 1000));
} catch (InterruptedException e) {}
}
}
};
loop.start();
The synchronised game loop uses lots of CPU (I think 1 core? that's ~25% for me).
CPU usage of the asynchronised game loop is almost 0%.
Note: The game I want to do is WebSocket based game. The server is for physics, and HTML5's canvas is for rendering.
What way do you prefer? Why? Is there any better way?
There are classes in the Java API to execute a task periodically. Its better to not try to reinvent the wheel and use the Java API. A ScheduledExecutorService seems to be what you need.
This example execute a Runnable periodically:
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(myRunnable, initialDelay, period, TimeUnit.MILLISECONDS);
In your first example, your thread is checking a huge amount of times if elapsedTime >= timeStep is true. It keeps doing the check until it is true, instead of doing this check time after time until it is finally true, the thread could be waiting and the processor could be used for something else.
The second option is better than the first one because the thread waits for the period to the next execution.

How to add time events in libgdx

I wanted to know how can I add time to my events in libgdx. I have a button and when you press it a sprite will appear. I want the sprite to appear for only a short period of time. How can I do this? I used Scene2D to make the sprites as an actor.
I will show you an example in pseudo code.
wait time = 5 second;
current time = get time;
if (current time > wait time) {
// do the following
}
There's two ways to do this. You can either use something similar to your your pseudo code or you can use a timer.
Manual calculation:
private Long lifeTime;
private Long delay = 2000L; //1000 milliseconds per second, so 2 seconds.
public void create () {
lifeTime = System.currentTimeMillis();
}
public void render () {
lifeTime += Gdx.graphics.getDeltaTime();
if (lifetime > delay) {
//Do something
}
}
Using a timer:
private float delay = 2; //In seconds this time
//At some point you set the timer
Timer.schedule(new Task(){
#Override
public void run() {
// Do something
}
}, delay);
Read more here: https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Timer.html

How to create a countdown timer in a Java Applet?

I'm working on a final project for school with a Java applet that counts down from a given interval to zero. When a Rectangle on screen experiences a mouse down event, it is supposed to execute the timer; however this does not occur; the program ends up crashing. I've seen a lot of examples of timers online, but many are using Java's built in timer class, which I am not using. I figured there must be a more basic way to do a simple timer. All variables have been declared at the top of the class.
public boolean mouseDown(Event e, int x, int y)
{
if(start.inside(x,y))
{
timerAct = true;
startTime = System.currentTimeMillis() / 1000;
endTime = startTime + interval;
while (System.currentTimeMillis() / 1000 < endTime) {
while (startTime != System.currentTimeMillis() / 1000) {
startTime += 1;
timeLeft = (endTime - startTime);
}
}
timerAct = false;
}
repaint();
return true;
}
The logic seems to workout okay because this began as System.out.println(), and it worked just fine. Then, it was converted to store the variable timeLeft. In the paint method, I have
g.drawString("Time: " + timeLeft, 420, 180);
to print the the time remaining. I also have the update method; but it doesn't seem to make a difference. And I know the issue isn't because I'm changing a variable. My mouse down method has an if statement with a different rectangle that tracks clicks (not shown), and it updates a counter of clicks on screen in the applet window without any issue. Any help is greatly appreciated.
Check this. It's pretty self explanatory.
Here's how you would code a simple countdown timer. This code needs to be run in a separate thread and not the Event Dispatch thread.
private void countdownTimer(int intervalSecs) {
long endTime = System.currentTimeMillis() + (intervalSecs * 1000L);
while (System.currentTimeMillis() < endTime) {
sleep();
repaint();
}
}
private void sleep() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void repaint() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
panel.repaint();
}
});
}

Why does this Java app run slow on Mac and not PC? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have created an application using Java and it runs smoothly on the Windows platform. However, when it is tested on my Macbook Pro Retina 15' with 4960HQ, the displayed frame rates are considerably lower.
I have coded the program to run animations at a constant 60fps and the console shows that 60fps is being drawn on both Mac and Windows. However, the program on Mac looks like it is running at 6-8fps.
Is there special coding methodology tailored for Mac? Or is java simply not optimized for Mac OSX?
Minimal working sample of code:
long framerate = 1000 / 60;
// time the frame began
long frameStart;
// number of frames counted this second
long frameCount = 0;
// time elapsed during one frame
long elapsedTime;
// accumulates elapsed time over multiple frames
long totalElapsedTime = 0;
// the actual calculated framerate reported
while(true){
frameStart = System.currentTimeMillis();
world.moveBG(3);
// calculate the time it took to render the frame
elapsedTime = System.currentTimeMillis() - frameStart;
// sync the framerate
try {
// make sure framerate milliseconds have passed this frame
if (elapsedTime < framerate) {
Thread.sleep(framerate - elapsedTime);
} else {
// don't starve the garbage collector
Thread.sleep(5);
}
} catch (InterruptedException e) {
break;
}
++frameCount;
totalElapsedTime += (System.currentTimeMillis() - frameStart);
if (totalElapsedTime > 1000) {
reportedFramerate = (long) ((double) frameCount
/ (double) totalElapsedTime * 1000.0);
// show the framerate in the applet status window
System.out.println("fps: " + reportedFramerate);
// repaint();
frameCount = 0;
totalElapsedTime = 0;
}
}
This bit of code handles controlling the fps, it is set to 60fps right now. the world.moveBG(3) moves and image across the screen at speed of 3 pixels per frame (which should not be performance intensive as it is a small image). Mac runs this at an apparent 10fps and windows at a smooth 60. The console on both machines display that 60fps is being drawn.
To clarify, it isn't that the image is moving slower on the screen in Mac than Windows, it is that the movement is extremely choppy on Mac
The next code starts an executor and schedule the tasks to acomplish your framerate.
Running this on Windows for 3 seconds the last trace I have indicates 179 tasks so almost the 60 tasks per second that you want to acomplish.
Try this code and let me know if improves your performance:
package com.nosolojava.test;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
public class FrameRateExecutor {
private final Logger logger = Logger.getLogger(this.getClass().getCanonicalName());
final static long framerate = 1000 / 60;
// number of frames counted this second
AtomicInteger frameCount = new AtomicInteger(0);
ScheduledExecutorService executor;
private volatile AtomicBoolean running = new AtomicBoolean(false);
class Task implements Runnable {
private final long lastTaskTimeStamp;
public Task() {
super();
//get creation time so we can calculate delay after
this.lastTaskTimeStamp = System.currentTimeMillis();
}
public void run() {
// TODO implement logic
logger.log(
Level.INFO,
String.format("Do something, framecount: %02d %d", frameCount.addAndGet(1),
System.currentTimeMillis()));
//calculate when to execute next task and submit
long currentTime = System.currentTimeMillis();
long elapsed = currentTime - lastTaskTimeStamp;
long delay = (framerate - elapsed) +framerate;
logger.log(Level.INFO, String.format("elapsed %04d delay %04d", elapsed, delay));
//check finish condition
if (running.get()) {
executor.schedule(new Task(), delay, TimeUnit.MILLISECONDS);
}
}
};
public void stop() {
running.set(false);
executor.shutdown();
try {
executor.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
logger.log(Level.SEVERE, "Error stopping executor", e);
}
}
public void start() {
//check if is already up
if (this.running.compareAndSet(false, true)) {
//init scheduled executor
executor = new ScheduledThreadPoolExecutor(1);
//start first task
executor.execute(new Task());
}
}
public static void main(String[] args) throws InterruptedException {
FrameRateExecutor frameExecutor = new FrameRateExecutor();
frameExecutor.start();
Thread.sleep(3000);
frameExecutor.stop();
}
}

Slow down the call to a specific function

I have a game loop here, that calls the tick method. Inside the tick method, other tick methods are called. How would I slow down the call to input.tick() without slowing down the whole program? Putting a Thread.sleep(); anywhere in the tick methods slows down the whole program and that is not what I want.
public void run() {
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
int frames = 0;
int ticks = 0;
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
tick();
ticks++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer += 1000;
System.out.println(ticks + " tps, " + frames + " fps");
ticks = 0;
frames = 0;
}
}
stop();
}
public void tick(){
input.tick(); // How do I slow down the call to this?
if(gameState){
player.tick();
player.move();
collision();
treeline.move();
obstacleHole.move();
obstacleWolf.move();
coin.move();
coin.tick();
}
}
It seems you are doing a GUI application and the code you are showing runs on the Event Dispatch Thread. The sleeps make the EDT freeze and be unable to update the GUI. What you must do instead is use the javax.swing.Timer class to postpone the execution of the code.
If you want to tick at regular intervals, then just reschedule the same task again in the handler submitted to Timer.
Use a Thread to call tick() in a deferred way, something like this:
private static final Timer TIMER = new Timer();
// ...
public void tick(){
TIMER.schedule(new TimerTask(){
void run() {
input.tick(); // Your tick method
}
}, 1000 /* delay in milliseconds */)
// ... rest of your method
}
If the input.tick() method collects the input of the player (e.g. key presses) it does no seem appropriate to delay it.
Perhaps you might be interested in implementing a Keyboard Input Polling mechanism. (see here for an example).
This is a usual technique in games so you do not respond to the input of the player in the usual way you would with other GUI applications. Instead you collect all the user input e.g. in a queue and then you poll that queue to read input at your own speed (e.g. 30 times per second).
I hope it helps

Categories

Resources