Something like ....
int oldTime = hiresTimer.getTime();
render();
int newTime = hiresTimer.getTime();
int renderTime = newTime-oldTime;
if(renderTime<1000/30)
{
Thread.sleep(1000/30-renderTime);
}
You can make a hi-res timer with 1.4.2 using the "hidden" class sun.misc.Perfpublic class HiResTimer() {
Perf hiResTimer;
long freq;
public HiResTimer() {
hiResTimer = Perf.getPerf();
freq = hiResTimer.highResFrequency();
}
public long currentTimeMillis() {
return hiResTimer.highResCounter() * 1000 / freq;
}
}
Recipee for constant frame rate if you are using threads:
If you are using threads and you will work at a constant frame rate you have first to calculate the time a frame should remain on screen in milliseconds: delayPerFrame = 1000/frameRate.
You have to use the thread's function .sleep(x) and x is delayPerframe - time_you_use_to_draw_frame_stuff.
Of course this time will change while execution, therefore you need a timer. Java's timer is not precise enough for this purpose and the resolution of System.getTimeMillis() is also not high enough. So you have to write a timer on your own.
Idea:
Use a separate Thread with an infinite loop where a long-counter is increased and the thread sleeps for 1 millisecond.
Code:
Public class PreciseTimer implements Runnable{
private Thread preciseTimerThread = new Thread(this, "precise");
private long milliSeconds=0;
private boolean endTimer = false;
public PreciseTimer()
{
preciseTimerThread.start();
}
public void start(){
milliSeconds=0;
}
public long getMilliSeconds(){
if (milliSeconds>maxMilliSeconds){milliSeconds=maxMilliSeconds;}
return (milliSeconds);
}
public void endTimer(){
endTimer=true;
}
public void run(){
while (!endTimer){
milliSeconds+=1;
try{preciseTimerThread.sleep(1);}catch(java.lang.InterruptedException e){}
}
}
}
in your drawing thread you put:
PreciseTimer preciseTimer = new PreciseTimer();
//main loop begins
{
preciseTimer.start()
//draw frame...
try{
'thisthread'.sleep(delayPerFrame-preciseTimer.getMilliSeconds ())
catch(..)...
}
//main loop ends
preciseTimer.endTimer();
You should also check that for sleep(x), x remains positive.
I also used this method in my java game resulting in a constant frame rate. The precise timer-thread will not really affect the performance.
Good luck!
just use maxMilliSeconds to define the maximal value the timer returns. if you use maxMilliSeconds=delayPerFrame, it cannot get negative.
public class PreciseTimer implements Runnable{
private Thread preciseTimerThread = new Thread(this, "precise");
private long milliSeconds=0;
private boolean endTimer = false;
private int maxMilliSeconds=0;
public PreciseTimer()
{
preciseTimerThread.start();
}
public PreciseTimer(int max)
{
maxMilliSeconds=max;
preciseTimerThread.start();
}
public void start(){
milliSeconds=0;
}
public long getMilliSeconds(){
if (milliSeconds>maxMilliSeconds){milliSeconds=maxMilliSeconds;}
return (milliSeconds);
}
public void endTimer(){
endTimer=true;
}
public void run(){
while (!endTimer){
milliSeconds++;
try{preciseTimerThread.sleep(1);}catch(java.lang.InterruptedException e){}
}
}
}
use PreciseTimer preciseTimer = new PreciseTimer(delayPerFrame); to generate new Instance.