getting very high FPS with standard Java 2D

I don’t know if this has been posted before, but I get some questions from my friends how I get such high frame rates on my 2D java games. This is the class I use:

/*

  • SpriteManager.java
  • Created on April 28, 2006, 11:28 AM
  • To change this template, choose Tools | Options and locate the template under
  • the Source Creation and Management node. Right-click the template and choose
  • Open. You can then make changes to the template in the Source Editor.
    */

package bomberdolf;

import java.awt.;
import java.awt.image.
;

import java.io.IOException;
import java.net.URL;
import java.util.HashMap;

import javax.imageio.ImageIO;
/**
*

  • @author Cyclonis Delta
    */
    public class SpriteManager {

    private static SpriteManager instance = new SpriteManager();
    private HashMap sprites = new HashMap();

    public static SpriteManager get() {
    return instance;
    }

    public Sprite getSprite(String ref) {
    if (sprites.get(ref) != null) return (Sprite)sprites.get(ref);

     BufferedImage sourceImage = null;
     try {
         URL url = new URL("file:"+System.getProperty("user.dir")+"/gfx/"+ref);
         if (url == null) {
             fail("Can't find ref: "+ref);
         }
         sourceImage = ImageIO.read(url);
     }
     catch (IOException ex) {
         System.out.println("could not read url");
     }
     
     GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    

    Image image = gc.createCompatibleImage(sourceImage.getWidth(),sourceImage.getHeight(),Transparency.BITMASK);

     image.getGraphics().drawImage(sourceImage,0,0,null);        
    
     Sprite sprite = new Sprite(image);
     sprites.put(ref,sprite);
    

    return sprite;
    }

     private void fail(String message) {
     System.err.println(message);
     System.exit(0);
    

    }

}

/*

  • Sprite.java
  • Created on August 21, 2006, 10:31 PM
  • To change this template, choose Tools | Options and locate the template under
  • the Source Creation and Management node. Right-click the template and choose
  • Open. You can then make changes to the template in the Source Editor.
    */

package bomberdolf;

import java.awt.*;

/**
*

  • @author Cyclonis Delta
    */
    public class Sprite {

    Image img;

    /** Creates a new instance of Sprite */
    public Sprite(Image image) {
    img = image;
    }

    public void drawMe(Graphics2D gfx, int x, int y) {
    gfx.drawImage(img, x, y, null);
    }

}

And in any method that you want to draw a particular sprite you simply call:

SpriteManager.get().getSprite(currentImg).drawMe(gfx, (int)x+15, (int)y);

in which the currentImg is simply a string with the path to your gif image.

I hope it works for you. I got FPS sometimes as high as 400, although they usually hang around at say 200-300

When I use java2D my fps is also that high, but it will go down down quickly as you draw more stuff. When i enable openGL pipelines they can be as high as 600-1600 , just depends.

If I’m using Thread.sleep(1) I get about 550 frames per second, without it I get like 2500 - 5000 fps (starts dropping the more I draw, especially anything other than PNG images). Obviously, I’m not actually getting 5000 fps - it’s only as high as the refresh rate. So it’s really the UPS im getting so high.

I actually dont use a sleep at all, i think sleeps are evil. Am I wrong? If the animations are synced with any framerate, there should be no sleeping :slight_smile:

Ideally, using vsync is the best way. Unfortunately, there is no guarantee this will work, so you’ll always need to throttle using sleep as a fallback.

just a word about Thread.sleep meth: it isn’t synch’ed with any object monitor so you won’ be able to make the required lap of time with it. Hence you better use wait(long) to do that what you want in a loop. :stuck_out_tongue:

hmm… if you don’t use sleep then you leave very little cpu time for other stuff. For example, if you have another thread for networking or such, it may not respond cleanly or your render thread will have a glitch when it does. Same thing applies for EDT thread responsible for keyboard input (if you use swing). Also without sleep or any timeout from constant rendering and calculations I assume other applications will be highly unresponsive, so for example you couldn’t listen mp3s in your favorite player and play the game at the same time.

If modern operating systems weren’t based upon preemptive multitasking, that might be the case.

I do not use sleep for the timing. I only use it to prevent the CPU from capping to 100%. That’s not a problem on my PC, however, since I have dual core (unless I have a game with multi threading and no sleep).

So should I just use sleep(1) or what? Because i hate loosing frames, even if it doesnt matter, but i have not made a cpu intensive game yet.
I seem to multi task with uncapped frames with no problem, but its early on in development.

If your game is using vertical-sync, you shouldn’t have the need to sleep. But if your just using say nanoTime() for limiting your frames per second but your running your render loop (drawing not updating) as often as possible, you’ll need to sleep for at least 1 millisecond or else you’ll cap the CPU to 100%. If you can find an alternative way to prevent your render loop from running as often as possible (like the technique vertical-sync uses but not being in fullscreen), you won’t have a need for sleep also.

The operating system will still give cpu time to other processes too. I read once in a book that sleep can be required for some garbage collection and Java background processing. When your main thread takes all the time, any Java deamon and other threads cant process. But this information is based on Java 1.4. Dont know if it is true and if it is still relevant.

On the other side, the eye can see fluid motion at about 22 fps. I dont know the refresh rates of monitors, 60 HZ to 75 HZ is usual, Im not sure if it is the “fps” of the monitor.

Whatever, anything more than 30 or maybe 50 fps is just not visible to the human eye. Computing 100 frames or more would be a waste of processing. A sleep call gives other Threads room to work and doesnt do damage to your game, as long as the fps are steady above 30.

-JAW

24fps is for human eye, but due to how monitors work 40-100 fps is needed. Best to vsync it (fps equal to monitor refresh rate). I would aim for 100 and not beyond.

Let me start by saying the following. You don’t need to sleep, but you do need to sleep. Basically you run an iteration of your game/rendering loop and then rest until the next frame begins. You do not do this by a particular time, instead you do something like this:

while ( looping ){
   waitVBL();        // wait for the screens vertical blank
   updateScreenOutput();
   doProcessing();
}

My waitVBL method goes through my own synchronization mechanism since I need a set UPS rate.

That’s pretty much how it should be done. Like I said above, I do my own vertical syncing.

Yes, that’s part of how my method works.

You can also Object.wait();

See my method above; in fact here is an example …

package javaThreadSynchronization;

public class WaitVBLSynchronization implements Runnable {
	public boolean running = true; 
	public Object waitingObject=null;
	public static void main ( String argv [] ) throws InterruptedException {
		WaitVBLSynchronization sync = new WaitVBLSynchronization();
		for ( int i = 0; i < 6; i ++ ) {
			sync.waitVBL();
			System.out.println(i);
		}
		sync.running = false;
	}
	public WaitVBLSynchronization (){
		Thread t = new Thread(this);
		t.start();
		
		// this high priority is valid because of how little the thread does
		t.setPriority(Thread.MAX_PRIORITY);
	}
	
	public void waitVBL () throws InterruptedException{
		waitingObject =  new Object();
		synchronized ( waitingObject ) {
			
			waitingObject.wait();
			waitingObject = null;
		}
	}
	
	public void run() {
		while ( running ){
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) { }
			
			if ( waitingObject != null ) {
				synchronized (waitingObject){
					waitingObject.notify();
				}
			}
		}
	}
	
}