Drawing an Image is sloooow...

Hi, wonder if anyone got some advice for me.
We are writing a classic 2D top-down view car battle game, like Tank War or wathever but with cars (if you were there back in the days, perhaps you have played Battle Cars :slight_smile: ).

To display the world, we use a tile-based map. Since the map can be much larger than the screen, only a part of the map is rendered at a time. The rendered part is stored in a class called DirectImage, which has a rectangular display area. When the screen scrolls, the display area is moved acordingly. The image is thus slightly larger than the display area.
The class DirectImage implements the ImageProducer interface.
So when I want the image to be drawn to the screen we call:

protected void paintComponent(Graphics gr)
{
//long startTime = System.currentTimeMillis();
bitImg.flush();
gr.drawImage(bitImg,0,0,null);
//long stopTime = System.currentTimeMillis();
//System.out.println("Time elapsed in piantComponent: " + (stopTime - startTime));

}

The startProduction method in DirectImage looks like:

public void startProduction (ImageConsumer ic) {
addConsumer(ic);
if( !visiblePixelsValid )
validatePixels();
if (consumer!=null) {
consumer.setPixels(0, 0, visibleRectangle.width, visibleRectangle.height, model, visiblePixels, 0, visibleRectangle.width); consumer.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
}

}

The problem is that the drawImage method seems to take very long time to complete in one out of every two times its called. It alternates between taking like 10 ms to taking up to 80 ms.
Does anyone has any suggestions on what I can do, cause this makes the scrolling look very unsmooth.
My measures suggests that it is the call to consumer.setPixels(…) that takes up most of the time.

If you need to see more of the sourcecode, just let me know OK?

Regards,
Anders

The answer is simple. Don’t use an ImageProducer/Consumer. The Java API is very slow at direct pixel blitting. If you want it fast, break up your background into managable image tiles, load them using Toolkit.getImage(), and only paint the tiles that are visible. This will take advantage of “Automatic Images” (basically VolatileImages, but with transparency) and speed up your code by 100x or better.

and if you absolutely must have per-pixel access,
BufferedImage/DataBufferInt is faster than ImageProducer/Consumer.

The only reason you would use your current method, is if you are limited to java1.1.

And if you are limited to the 1.1 api, dont expect anything to be fast :confused:

Thanks a lot guys, I’ve ditched the ImageProducer/Consumer thing and the scrolling is really smooth now! :slight_smile:

Regards,
Anders

Another few things you might wand to concider is 1) If you’re using a frame as your window, use full screen exclusive mode with larger dimensions such as 640x480. (for this you must be using 1.4.0 and up.) 2) If you’re going with VolatileImage which is extremely powerful, use framerate sync so that the animation is constant (especially with VolatileImage). Here is the code in the run method of a thread:
public vod run(){
frame_Start = 0;
elapsed_Time = 0;
Thread t = Thread.currentThread();
while(t == paint_Timer){
frame_Start = System.currentTimeMillis();
repaint();
elapsed_Time = System.currentTimeMillis() - frame_Start;
try{
if(elapsed_Time < frame_Rate)
paint_Timer.sleep(frame_Rate - elapsed_Time);
else
paint_Timer.sleep(3);
}catch(InterruptedException e) {break;}
}
}