Drawing the background kills my perfomance

(Using J2D).

I’m creating a vertical scrolling shoot-em-up. I’m currently drawing the background by iterating a 2d array (actually a List of Lists) of 32 x 32 images and drawing them onto a Canvas using drawImage. This is horrifically slow. Profiling shows the time is spent in the drawImage() method.

I think my approach is flawed. Would I be better off concatenating my tiles into one image and drawing that? Or some other approach?

thanks, Don

Be sure to only draw those tiles which actually end up on the screen. Eg for 640x480 you have to draw 21*16 (336) 32x32 tiles.

Bigger tiles like say 64x64 would be a tad faster, because there is less overhead.

If you use getSubImage or if you use that drawImage method with 2 clip rects be sure that the original image doesnt exceed 2^16 (eg 256x256) pixels.

Additionally you can experiment with those java2d switches.

(Using an OpenGL binding would give you a bigger speed improvement tho.)

You could also still load 32x32 size images, but pre-render them onto larger tiles before a level starts. So when you are drawing a level, you only have 256x256 of 512x512 size images. Then you only have to draw 4-6 images at a time.

Also, as oNyx said, use OpenGL would be a lot faster.

Please fill in all the usual details… JDK version? OS? Video card? Driver version? Are you really drawing directly to a Canvas, or are you using a BufferStrategy? Have you tried using the OpenGL-based pipeline:
http://java.sun.com/j2se/1.5.0/docs/guide/2d/flags.html#opengl
http://today.java.net/cs/user/print/a/147

Chris

Use a GraphicsConfiguration Object to createCompatilbeImage(x,y);

Render your images onto these and draw these images onto the screen.

Greg

If your tiles are NOT animated, I suggest that before a level starts, you draw your tile images to a BufferedImage then draw that image to the screen after the level has been started. This eliminates the overhead of a loop. Like oNyx mentioned, if your screen is 640x480 and 32x32 tiles, that’s 336 images to be drawn every loop. But if you pre-render your tiles onto a bigger BufferedImage, it will probally increase performance.

Hmyea… using a bunch of 256x256 images under the hood (and only overdrawing specific regions of those images on demand) would surely improve things (I think it should be easily about twice as fast [guesstimate based on windows java2d performace]). However, its pretty complicated stuff.

While prerendering images may increase performance, this can result in huge memory usage, particularly if there’s a large number of different tile types (lots of diversity -> you can’t reuse graphics). I’m writing a game with a quite large map and - IIRC - 32x32 graphical tiles, and of course it takes ages to render. One solution is to only render those tiles that have not been disturbed since last frame. I.e. when the player scrolls there’s a lot of repainting, but when the camera sits still everything runs at arbitrarily high fps.

A further improvement is to use two buffers such that terrain is drawn onto one whereas everything that moves is drawn onto the other. Then you’ll have to draw both buffers every frame, but it can make terrain repaints unnecessary. This, by the way, is not quite “double buffering”.

Uhm… with “a bunch of 256x256 images” I ment just enough of em to fill the screen (hence that overdrawing on demand thing). So, memory wouldnt be really an issue… the code would just be pretty scary :slight_smile:

Say its 640x480 and 32x32 tiles with 256x256 “proxy buffers”. You would need 3x2 of those buffers, which you’re always drawing… and in the worst case you have to draw 21+16 tiles onto the buffers before drawing em.

edit: Yes, that worst case thingy is based on the assumption that you scroll less than the tile width or height per frame :wink: