bad fps when drawing background tiles

hi,

i’ve started to work on a helicopter game.
currently i’m (once again) struggling with the framerate.
for my previous game i managed to get stable 50fps thanks to woogley’s instructions (see this thread).

for the new game i’m using a different approach.
the background image is created using tiles. i guess i’m doing something wrong again because i don’t get much more than 35 fps.
my question is:
is it only possible to get a good framerate when i draw one single background image or should it be possible to achieve good framerates when i concatenate some tile images (and parts thereof)?

to get a better view of things here’s the game so far:
EscalationChopper

note: the game throws an exception after some time. this is a known bug.

i guess i’m doing something wrong

Likely.

How many tiles are there?

How big are the tiles?

How are they stored? (How many per sheet)

How do you load that file?

How do you draw it? (Draw only those which are on screen)

Have you checked if they get accelerated?

Etc…

How many tiles are there?
about 8x6 or so (don’t know what i configured exactly)

How big are the tiles?
400x400px

How are they stored? (How many per sheet)
i use only one jpg file currently which is loaded and then re-used.

How do you load that file?
according to woogley’s instructions (see thread i mentioned above):


protected static final GraphicsDevice DEVICE = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
protected static final GraphicsConfiguration CONFIG = DEVICE.getDefaultConfiguration();
protected static final DisplayMode DISPLAY = DEVICE.getDisplayMode();

...

protected final BufferedImage getAccImg(String ref, int trans) {
        BufferedImage sourceImage = null;
      try {
            URL url = this.getClass().getClassLoader().getResource(ref);
                  
            if (url == null) {
                    System.out.println("Can't find ref: "+ref);
            }

            // use ImageIO to read the image in
            sourceImage = ImageIO.read( 
                new BufferedInputStream(this.getClass().getClassLoader().getResourceAsStream(ref))); 
            
        } catch (IOException e) {
            System.out.println("Failed to load: "+ref);
            e.printStackTrace();
        }
            
        BufferedImage image = CONFIG.createCompatibleImage(sourceImage.getWidth(),sourceImage.getHeight(),trans);

        image.getGraphics().drawImage(sourceImage,0,0,null);
        return image;
    }

How do you draw it? (Draw only those which are on screen)
yes i only draw the visible parts of the tileset. i calculate the tile parts (if the tile is drawn at the screen edge) or use the whole tile (if drawn in the middle of the screen) and calculate the place on screen where the
(sub)images shall be drawn.

Have you checked if they get accelerated?
i have no idea how to check if an image is accelerated… :-[

i you wanna have a look at the code, here it is:
src.zip

How big are the tiles?
400x400px

How are they stored? (How many per sheet)
i use only one jpg file currently which is loaded and then
re-used.

Meh… sounds bad.

Ok. Try tile sizes of 16x16 to 128x128 (I suggest 32x32).

Each tile sheet shouln’t exceed 2^16 (eg 256x256) pixels. That’s because getSubimage uses the source image under the hood - there is no copying envolved. And if you want to use accel each image needs to be <=256x256… therefore you should stay below that treshold (for now).

How do you draw it? (Draw only those which are on screen)
yes i only draw the visible parts of the tileset. i calculate
the tile parts (if the tile is drawn at the screen edge) or
use the whole tile (if drawn in the middle of the screen)
and calculate the place on screen where the
(sub)images shall be drawn.

Sounds weird. Usually you just draw all tiles which are either fully or partially visible (the build-in clipping cares about the details). The sub rect of your 2d map array (which you need to interate through) can be easily calculated (x-offset, y-offset, tile-height, tile-widht, screen-width, screen-height… it’s easy).

i you wanna have a look at the code

Nah… I don’t wanna :slight_smile:

Each tile sheet shouln’t exceed 2^16 (eg
256x256) pixels. That’s because getSubimage uses
the source image under the hood - there is no copying
envolved. And if you want to use accel each image
needs to be <=256x256… therefore you should stay
below that treshold (for now).
ok, thx for the info. is there any tutorial where i can learn these things (so that i don’t have to ask you guys all the time)?
i’m especially interested in how to check if an image is accelerated or not.

image->getCapabilities->isAccelerated

thx. i currently don’t have 1.5.0 installed. therefore i don’t have that methods available. but i’m downloading it right now…

btw, i managed to get stable 50fps by removing the creation of the subimages like i explained above.
simply drawing the tiles even if they are outside the screen did the job! :slight_smile: thx, oNyx!

50? Mh… fullscreen by chance? At 100hz maybe? If so try using 3 instead of 2 buffers. Doing so can increase the framerate drastically if the drawing of each frame tooks a bit longer than the interval between syncs.

i’m fine with 50fps. this is my target framerate in windowed mode. do i have to change anything in the code when i switch to 3 buffers?

No, you don’t need to change anything… except createBufferStrategy(3) instead of createBufferStrategy(2).

However, if it’s windowed you can leave it at 2 (there won’t be any benefit if you change that to 3).

what are the benefits of using triple-buffering in fullscreen mode? o_O

[quote]what are the benefits of using triple-buffering in fullscreen mode? o_O
[/quote]
Say… the screen refreshes at 100hz.

That means you have 10msec to draw the frame. Ok.

If you take <=10msec per frame you will reach 100fps. Right. But if you need 11msec per frame… the framerate will be magically halfed. Because you miss, hit, miss, hit… and so on.

However, with 3 buffers you can start drawing into the next buffer once you finished the last one. Taking the previous example that would mean that we miss the first frame… are done with it 1msec later… and then we have a whopping 9msecs for drawing most of the next frame. Therefore we can show much more than 50fps. We will still miss some frames, but not half of em.

[There is no vsync in windowed mode - therefore there is no benefit in using more than 2 (front+back) buffers.]