@CodeBunny
This is because, you usually compute the number of time your game has to wait in one frame. Usually you say:
int frameTime = 1000 / 60;
now acctually, if you divide 1000 by 60, you get 16.66666*, but as it is an int, (or long) frameTime will be set to 16. That means, your game will slightly sleep less, than it acctually should. If you run the game, you will get 63 fps, because he will only calculate the fps, if 1000ms are gone since the last second. That means, if you would take 16 ms per frame for 60 frames, you will have passed 16 * 60 = 960 [ms]. But acctually the fps counter waits for 1000ms, so you need 3 more frames to get above 1000ms: 16 * 63 = 1008.
You can easily solve the problem with "High Resolution" Timers. The standard Java library allows that (via milliseconds AND nanoseconds (See Thread.sleep and System.nanoTime()), just take a look at this:
private class DelayHandler implements UniPrintable {
/* Delay-Handling: */
private HighResTime sleep;
private HighResTime delta;
private HighResTime timeOld;
private HighResTime time;
private HighResTime fpsTime;
private HighResTime realSleepBegin;
private HighResTime realSleepEnd;
private HighResTime realSleep;
/* FPS-Handling: */
public float fps;
private long frames;
private HighResTime fpsTimeOld;
private long up;
public DelayHandler() {
sleep = new HighResTime(0, 0);
delta = new HighResTime(0, 0);
timeOld = new HighResTime(0, 0);
time = new HighResTime(0, 0);
fpsTime = new HighResTime(0, 0);
realSleepBegin = new HighResTime(0, 0);
realSleepEnd = new HighResTime(0, 0);
realSleep = new HighResTime(0, 0);
fps = 0f;
frames = 0;
fpsTimeOld = new HighResTime(0, 0);
up = 60;
setFpsTime(60);
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
private HighResTime getDelta() {
frames++;
time.set();
delta.setSubtract(time, timeOld);
if (frames >= up) {
fps = ((up * 1000f) / (time.time - fpsTimeOld.time));
frames = 0;
UniPrint.printf("%s >> fps: %G\n", getClassName(), fps);
fpsTimeOld.set(time.time, time.timeNano);
}
return delta;
}
/**
* Call this after every frame.
*
* @param fps
* - The wanted FPS to sync to.
* @return whether you should exit the loop or not.
*/
public boolean update(boolean dodelay) {
sleep.setSubtract(fpsTime, getDelta());
sleep.normalizeNano();
if (dodelay) {
try {
realSleepBegin.set();
while (sleep.time > 0) {
Thread.sleep(sleep.time, (int) sleep.timeNano);
realSleepEnd.set();
realSleep.setSubtract(realSleepEnd, realSleepBegin);
sleep.setSubtract(sleep, realSleep);
}
timeOld.set();
return false;
} catch (InterruptedException e) {
UniPrint.printerrf(this, "Error while sleeping!\n");
e.printStackTrace();
return true;
}
}
return false;
}
public void setFpsTime(long fps) {
fpsTime.set(1000L/fps, (1000000000L/fps)%1000000L);
}
/**
* Set how much frames to wait, until the next
* frame rate is printed. Also affects fps
* calculation, because fps are calculated,
* when they are printed.
* @param frames - the frames to wait.
*/
public void setFpsCalcDelay(long frames) {
up = frames;
}
public String getClassName() {
return getClass().getSimpleName();
}
private class HighResTime {
public long timeNano;
public long time;
public HighResTime(long timeNano, long time) {
this.timeNano = timeNano;
this.time = time;
}
public void set() {
timeNano = System.nanoTime();
time = System.currentTimeMillis();
}
public void set(long t, long tn) {
time = t;
timeNano = tn;
}
public void setSubtract(HighResTime t1, HighResTime t2) {
timeNano = t1.timeNano - t2.timeNano;
time = t1.time -t2.time;
}
public void normalizeNano() {
timeNano = timeNano % 1000000L;
timeNano = timeNano < 0 ? timeNano+1000000L : timeNano;
}
}
}
(This is code from my UniverseEngine
)
The Code is not very good written and documented (cause its private), but it should give you an idea
[EDIT: Little corrections...]