FPS difference

Hello there! I’m new here, and also in java world.

I’m currently working on a tile-based game. The problem is: When i make a runnable jar file and open it in my computer, i have 55-60 FPS, but if one of my friends open it, the FPS don’t pass 18. I have to mention that my PC is slower (in hardware) than theirs.

Here is my Core class:


package com.game;

import java.awt.*;
import com.game.gui.*;

public abstract class Core implements Runnable {
	private boolean running;
	public static GameScreen screen;
	public boolean paused;
	public int fps;
	boolean game_is_running = true;
	long startTime, currTime;
	
	public void run() {
		init();
		gameLoop();
		startTime = System.currentTimeMillis();
		currTime = System.currentTimeMillis();
	}
	public void init() {
		screen = new GameScreen();
		running = true;
	}
	
	public void gameLoop() {
		int TICKS_PER_SECOND = 60;
	    int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
	    int MAX_FRAMESKIP = 10;
		
		long next_game_tick = currTime-startTime;
		int loops;
		
		fps = 0;
	    int frames = 0;
	    long totalTime = 0;
	    long curTime = System.currentTimeMillis();
	    long lastTime = curTime;
		
		while(running) {
			lastTime = curTime;
			curTime = System.currentTimeMillis();
			totalTime += curTime - lastTime;
			if( totalTime > 1000 ) {
				totalTime -= 1000;
				fps = frames;
				frames = 0;
			} 
			frames++;
			
			currTime = System.currentTimeMillis();
			
		    loops = 0;		    
		    while( currTime - startTime > next_game_tick && loops < MAX_FRAMESKIP) {
		    	update(); //updates entity position
		    	
	            next_game_tick += SKIP_TICKS;
	            loops++;
	        }
		    Graphics2D g = screen.getGraphics();
		    render(g);
		    g.dispose();
			screen.update();
		}
	}

	public abstract void render(Graphics2D g);
	public void update() {}
}

Your game loop runs without sleeping, so I blame the accuracy of System.currentTimeMillis. Use System.nanoTime() instead.

However, it’s generally not a good idea to let the game loop run as fast as possible, since this will take up 100% of the CPU.

Also, what OS are you and your friend using?

I’ve never used System.nanoTime() before, so is this the only change that i should make (change everywhere System.currentTimeMillis() with System.nanoTime()) ? How to calculate the fps with nano?

I use Windows 7 and they use Win7, WinXP and WinVista.

Maybe the hardware graphics acceleration is enabled on your computer but not on your friend’s

I don’t think so… Also, i have notebook, if this is relevant.

This is my Screen class:


package com.game.gui;
import java.awt.Canvas;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;

public class GameScreen extends JFrame {
	private static final long serialVersionUID = 1L;
	final int SCREEN_WIDTH = 512, SCREEN_HEIGHT = 512;
	public Canvas canvas;
	public BufferStrategy buffer;
	
	public GameScreen() {
		this.setResizable(false);
		this.setIgnoreRepaint(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		canvas = new Canvas();
		canvas.setIgnoreRepaint( true );
		canvas.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
		
		this.add(canvas);
	    this.pack();
	    this.setVisible(true);
	    this.setLocationRelativeTo(null);
	    
	    canvas.createBufferStrategy(3);
	}
	
	public Graphics2D getGraphics() {
		buffer = canvas.getBufferStrategy();
		return (Graphics2D) buffer.getDrawGraphics();
	}
	
	public void update() {
		if(canvas != null) {
			buffer = canvas.getBufferStrategy();
			if(!buffer.contentsLost())
				buffer.show();
		}
	}
}

Cold anyone recommend me a good game loop? Because i think this is the problem. Thanks!

Hey! :slight_smile:

Here´s a great tutorial about game loops, I hope it helps :slight_smile:

On far sight, somebody can’t keep their OS clean. So many background services running and eat CPU. Maybe your friends too.

Ok, thanks for the advices. But is really needed to use interpolation? I think are too many things to change just for some miliseconds…

EDIT: Any tip for me about how to reduce the cpu usage in MY game loop?

Unfortunately, all proposed solutions in the ‘game loop thread’ are flawed. :emo:

I advise you to take a look at my game-loop code that is included in LWJGL. It works properly and takes into account a lot of factors that influence both the CPU usage and the smoothness of the FPS.

Usage:


while(true) {
   this.render();
   Sync.sync(60);
}

If you want to include fixed interval update ticks:


long nanosInSecond = 1000L*1000L*1000L;
long updateFrequency = 100;
long updateInterval = nanosInSecond / updateFrequency;
long nextUpdateTick = System.nanoTime();

while(true) {
   for(long now = System.nanoTime(); now > nextUpdateTick; nextUpdateTick += updateInterval) {
      this.update();
   }

   this.render();
   Sync.sync(60);
}

Riven, the enemy of all current and future 120Hz monitor owners. No, thanks, I think I’ll go with interpolation for my game. At least your new sync() a big improvement to the old Display.sync().

Since you wrote this, can we use it separate from LWJGL without having to meet the licensing conditions of LWJGL? Or at least adapt parts of it? I just don’t want to do this part of the license x)

It’s quite rare that you find somebody who has beef with modified BSD.

I don’t have a beef, I’m just lazy ;D

kappa/kappaOne modified the structure of the code a bit, so it’s not 100% mine.

If anyone wants to use this without LWJGL, just replace

	private static long getTime() {
		//return (Sys.getTime() * NANOS_IN_SECOND) / Sys.getTimerResolution();
		return System.nanoTime();
	}

and remove the imports. I don’t know what this means in terms of licensing or legalities, I’m just showing you how to use it without the LWJGL dependencies.

Thanks to everyone for answer. I resolved the problem. My game is getting shape… I hope in a week or two, it will be done.

maybe this kind of loop will help (inded feel free to replace currentTimeMillis by nonoTime…)

EDIT: after reading it dos not seems to be as good :confused:

this one seems better, it will do a fixed step logic/physic and will render only if at least one logic update has been performed (and then max FPS will be also limited to update logic rate but will run logic the same even on computer with very low FPS and will only consume requiered CPU on fastest computer):

mainLoop()
{
time=getTime(); //System.currentTimeMillis or other method
int elapsedTime=(time-lastTime);
int nbLogic=elapsedTime/20;
int interpolateMs=elapsedTime%20;

if(nbLogic!=0)
{
  for(int n=0;n<nbLogic;n++)
   doLogicFor20ms();
  //interpolateMs can be used to extrapolate rendering...
  drawAllObjectsOnScreen(interpolateMs);
}
else
 Thread.sleep(1);

lastTime+=20*nbLogic;
}