Constant Frame rate and Smooth animation??

Is it possible? I’m having a hell of a time trying to get a constant FPS with Jave2D. Is this possible and are there alternatives? OpenGL?

I’ve searched high and low and it doesn’t seem like anyone has much luck with Jave2D. Is that just how it is?

Also this is for an applet… if that makes a difference.

It seems it is prone to little hiccups now and then.
Just when you think everything is rolling smoothly, a half sec glitch.
Very annoying, for twitch games unacceptable.
more in this thread
http://www.java-gaming.org/index.php/topic,22762.0.html
Seems like lwjgl is the way to go for steady performance

I’ve never worked with OpenGL before is it hard to learn? and in that other thread someone mentioned that if lwjgl is used the applet has to be signed. Why is that?

Will i have to rewrite all of my graphics code?



public class Timer {
	
	private long timeThen;
	
	boolean newVersion = true;
	public Timer() {
		if (System.getProperty("java.version").startsWith("1.4")) newVersion = false;
		if (newVersion) timeThen = System.nanoTime();
		else timeThen = System.currentTimeMillis();
		
	}

	public void sync(int fps) {
		Thread.yield();
		if (newVersion) {
			long gapTo = 1000000000L / fps + timeThen;
			long timeNow = System.nanoTime();
			
			try {
				while (gapTo > timeNow) {
					Thread.sleep((gapTo-timeNow) / 2000000L);
					timeNow = System.nanoTime();
				}
			} catch (Exception e) {}

			timeThen = timeNow;
		} else {
			long gapTo = 1000L / fps + timeThen;
			long timeNow = System.currentTimeMillis();
			
			
			while (gapTo > timeNow){
				try { Thread.sleep(1);
				} catch (InterruptedException e) {}
				timeNow = System.currentTimeMillis();
			}
			
			timeThen = timeNow;
		}
	}

	public static void main(String args[]) {
		int framerate = 1;
		System.out.println("Running Timer Test at: " + framerate + " frame per second, should usually be 60");
		
		//create a new timer before starting main loop
		Timer timer = new Timer();
		
		while (true) {
			//Call sync once every game cycle
			timer.sync(framerate);
			System.out.println("tick");
			
		}
	}

}

I pasted this timer class in another thread but I cant find it. Just look at the “main” method to work out how to use it.

This is probably the best you can do with Java2D, otherwise best to use LWJGL

I use this one, still some vsynch error but work nice for applet

interval=40; 
lastDraw=0;
while(running)
{
 while(System.currentTimeMillis()-lastDraw<interval)
	Thread.sleep(1);
 
 lastDraw=System.currentTimeMillis();
 this.draw();
 
}

Yes, it is possible. At least on my machine (a five year old laptop with graphics that wasn’t good at that time, but hey it runs Heroes of Might and Magic 2).

Can you show us something that is not working?

This is my timer loop (I think it is from Killer game programming, slightly modified). It will give you a constant update pace and as much framerate as you computer can handle (maximum same as update).

while (!end) {
            update();
            paintScreen();

            afterTime = System.nanoTime();
            timeDiff = afterTime - beforeTime;
            sleepTime = period - timeDiff - overSleepTime;

            if (sleepTime > 0) {
                try {
                    Thread.sleep(sleepTime/1000000);
                } catch (InterruptedException e) { }

                overSleepTime = System.nanoTime() - afterTime - sleepTime;
            } else {
                excess -= sleepTime;
                overSleepTime = 0;
                Thread.yield();
            }

            beforeTime = System.nanoTime();

            int skips = 0;
            while (excess > period && skips < 5) {
                excess -= period;
                update();
                skips++;
            }
            excess = excess > period ? 0 : excess;
        }

I also often use constant logic using as much FPS than requiered (up to max FPS) but prefer the following solution wich look less complex and have always worked fine for me.


try
{
  int logicInterval=40;
  long lastLogicTime=System.currentTimeMillis();
  while(this.run)
  {
    long time=System.currentTimeMillis();
	
    int nbLogic=(int)((time-lastLogicTime)/logicInterval);
    for(int n=0;n<nbLogic;n++)
      this.logic();
    lastLogicTime+=nbLogic*logicInterval;
	
    //no need to draw anything if no logic was perfomed (nothing changed => so no visible change)
    if(nbLogic!=0) 
      this.draw(); 
    else
      Thread.sleep(1);
  }
}
catch(InterruptedException ie)
{
  //game thread interrupted
}

with this one logic calls will be perfectly constant while FPS will be adjusted

(as I can remember System.nanoTime may be weird sometime, especially on AMD dual core but never experience such problem)

wow thanks for all the replies. I’m going to give some of your suggestions a try. This is what I was doing…

	public void run()
	{
		long frameTime, renderTime;
		long beforeTime, timeDiff, sleepTime;
		beforeTime = System.nanoTime();
		frameTime = System.nanoTime();

		while(showing)
		{
			update();
			draw();
			controller.paintScreen(buffer);

			timeDiff = System.nanoTime() - beforeTime;
			renderTime = System.nanoTime() - frameTime;
			sleepTime = speed - timeDiff/1000000L;

			if(renderTime >= 1000000000)
			{
				frameTime = System.nanoTime();
				FPS = counter;
				counter = 0;
			}
			else
				counter++;

			if(sleepTime > 0)
			{
				try
				{
					Thread.sleep(sleepTime);
				}
				catch (InterruptedException ex)
				{
					ex.printStackTrace();
				}
			}
			else
				Thread.yield();

			beforeTime = System.nanoTime();
		}
	}

However, I was getting very inconsistent FPS. Also can someone address the LWJGL and signing thing. To sign an applet and use LWJGL do you have to buy an actual certificate?

Ok i have had all i can take of Java2D. Can someone give me a quick tutorial on what LWJGL is/how to implement it? Is it going to be hard to convert my current graphics method to that? All i’m currently using java2D for is to manipulate .gif images.

I’m not going to do more than point you to slick, a 2D game engine that uses lwjgl.
http://slick.cokeandcode.com/

But… I hope you are not painting the images directly from the gifs???
You have to create an image that is the same mode as the screen, paint the gif onto it and then discard the gif.

Some old code I wrote to do this:

            ImageIcon icon = new ImageIcon(path);
            if (icon.getImage() != null && icon.getImage().getHeight(null) > 0) {
                Image temp = icon.getImage();
                BufferedImage dest = GameWindow.createCompatibleImage(temp.getWidth(null), temp.getHeight(null));
                Graphics g = dest.getGraphics();
                g.drawImage(temp, 0, 0, null);
                g.dispose();
            }
            //now, dest have the image you want to use

    public static BufferedImage createCompatibleImage(int width, int height) {
        if (gd == null) {
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            gd = ge.getDefaultScreenDevice();
        }
        return gd.getDefaultConfiguration().createCompatibleImage(width,height,Transparency.TRANSLUCENT);
    }


currently I am loading the gif via this method:

Image city;
city = getImage(getDocumentBase(), "images/city.gif");
		appletTracker.addImage(city,105);

you are saying i should create an image that is 800,600 (my applet size) that is all translucent other than the actual gif???

That seems to me like it would take even longer given that each image is now huge…

is slick easy to use? and can someone please explain to me why using any of these engines (LWJGL, slick, etc…) i need to sign the applet?

It’s because they use native code - dll files (for windows). Slick uses lwjgl under the hood

so what all does signing involve? do i have to pay hundreds of dollar for verisign or thawte??

No since the LWJGL devs kindly sign sign their jars etc with their certificate.

To use non-LWJGL native stuff then yes you need to pay hundreds for a cert.

If you buy a proper certificate to sign your jars then you will get a nicer dialog when your applet is run.

However you don’t need to buy a certificate, you can just sign your own jars using a self signed certificate which is free. However the dialog at run time is not as pretty.

Also as mentioned above LWJGL provides pre-signed jars with a proper certificate so you can just use that.

[quote]you are saying i should create an image that is 800,600 (my applet size) that is all translucent other than the actual gif???
[/quote]
ok, to start from the beginning. Images need to be accelerated for them to be fast. Otherwise, they are slow. :slight_smile:
The method createCompatibleImage creates an accelerated image for you. I will be completely blank and support translucency.
If you load an image that is 32x32 you should create an accelerated image that is 32x32.

If you read my code it is this line: (see that i set the loaded images dimensions as parameters).

                BufferedImage dest = GameWindow.createCompatibleImage(temp.getWidth(null), temp.getHeight(null));

Then paint the loaded image onto the acclerated one.
Discard the loaded image and use the accelerated.

Of course, this does not guarantee that your game will run smooth. It also depends on other things, like you main loop, your AI, physics etc.

Its pretty easy to set up ant to create your certificate and sign all your jars for you.

Ant target for creating certificate. Call this once.

    <target name="Gen key">
        <delete file="yourname.ks"/>
        <genkey alias="YourAlias" keyalg="RSA" storepass="yourpass" keypass="yourkeypass" keystore="yourname.ks" validity="1000" >
            <dname>
                <param name="CN" value="Your Name"/>
                <param name="OU" value="Game Name"/>
                <param name="O" value="Your Organisation Name"/>
                <param name="C" value="Your Country"/>
            </dname>
        </genkey>
    </target>

Then, when you have created your jar. Use this antcall to sign it.

        <signjar keystore="yourname.ks" jar="nameofjar.jar" alias="YourAlias" storepass="yourpass" />

NB:

be carfefull with sleep method like the following :

Thread.sleep(sleepTime);

if you got other thread running Thread.sleep(15) may sleep for 50 ms for example

Thread.sleep(10) does not mean thread will sleep for 10 ms, this a very inacurrate method

and be carefull with System.nanoTime too

[quote]the result of nanoTime is jumping forward and backward in
time, depending on which cpu the thread is currently running
[/quote]

thanks for all the replies yall have been very helpful. last question I think. Does LWJGL have the pitfalls that Java2D has? for instance the inaccuracy of sleep or does it have some other way to increment FPS and UPS? (ie. what is the general game loop look like for LWJGL, is it still update, render, sleep?) Is the difference between LWJGL and java2D a drastic one or am i splitting hairs by moving to it?

oh and thanks markus, I might give that a try and see if it speeds things up.

LWJGL has its own high resolution timer so has much more accurate timing.

You can’t really compare LWJGL with Java2D, you can however compare Slick2D with Java2D and yes the difference is pretty drastic. Also slick provides you with a pretty accurate delta time every frame which can be used for all your game timing, so you don’t need to worry about creating your own timer.