views:

1295

answers:

7

As the title says, I'm fleshing out a design for a 2D platformer engine. It's still in the design stage, but I'm worried that I'll be running into issues with the renderer, and I want to avoid them if they will be a concern.

I'm using SDL for my base library, and the game will be set up to use a single large array of Uint16 to hold the tiles. These index into a second array of "tile definitions" that are used by all parts of the engine, from collision handling to the graphics routine, which is my biggest concern.

The graphics engine is designed to run at a 640x480 resolution, with 32x32 tiles. There are 21x16 tiles drawn per layer per frame (to handle the extra tile that shows up when scrolling), and there are up to four layers that can be drawn. Layers are simply separate tile arrays, but the tile definition array is common to all four layers.

What I'm worried about is that I want to be able to take advantage of transparencies and animated tiles with this engine, and as I'm not too familiar with designs I'm worried that my current solution is going to be too inefficient to work well.

My target FPS is a flat 60 frames per second, and with all four layers being drawn, I'm looking at 21x16x4x60 = 80,640 separate 32x32px tiles needing to be drawn every second, plus however many odd-sized blits are needed for sprites, and this seems just a little excessive. So, is there a better way to approach rendering the tilemap setup I have? I'm looking towards possibilities of using hardware acceleration to draw the tilemaps, if it will help to improve performance much. I also want to hopefully be able to run this game well on slightly older computers as well.

If I'm looking for too much, then I don't think that reducing the engine's capabilities is out of the question.

A: 

what about decreasing frame rate in to 30fps. i think it good inuff for 2d game

Kombuwa
While this is certainly possible (And I'll keep it in mind), I'd rather optimize my code than reduce the capabilities of the engine.
Sukasa
30 FPS seems like an absolute minimum as the responsiveness is significantly lower, and a 20 ms latency feels pretty much instantaneous compared to 33 ms.
Cecil Has a Name
+3  A: 

I think the thing that will be an issue is the sheer amount of draw calls, rather than the total "fill rate" of all the pixels you are drawing. Remember - that is over 80000 calls per second that you must make. I think your biggest improvement will be to batch these together somehow.

One strategy to reduce the fill-rate of the tiles and layers would be to composite static areas together. For example, if you know an area doesn't need updating, it can be cached. A lot depends of if the layers are scrolled independently (parallax style).

Also, Have a look on Google for "dirty rectangles" and see if any schemes may fit your needs.

Personally, I would just try it and see. This probably won't affect your overall game design, and if you have good separation between logic and presentation, you can optimise the tile drawing til the cows come home.

Justicle
I can't cache the output since the layers are fully independent of each other, but it would likely be possible to cache the output of all the layers (except sprites) before they're all blitted to the final surface and only update, as necessary. Thanks for the idea. Marking dirty won't be too much help, since the engine would mean I'd spend more time finding dirty rectangles than I would just blitting dumbly.
Sukasa
Yep, sure. Just watch your draw call overhead. On a modern GPU, I doubt fill rate will be an issue. I'm not sure how much SDL exposes, but if I had full access to GL, I'd be making some kind of texture atlas that included all the tiles, and then indexing UVs into that from a strip of polys that described a row or column on the final buffer.
Justicle
+1  A: 

I agree with Kombuwa. If this is just a simple tile-based 2D game, you really ought to lower the standards a bit as this is not Crysis. 30FPS is very smooth (research Command & Conquer 3 which is limited to 30FPS). Even still, I had written a remote desktop viewer that ran at 14FPS (1900 x 1200) using GDI+ and it was still pretty smooth. I think that for your 2D game you'll probably be okay, especially using SDL.

David Anderson
Yup, i notice that i can tolerate quite slow frame rates (maybe 15-20) on games like Supreme Commander without much problem.
RCIX
A: 

I think you will be pleasantly surprised by how many of these tiles you can draw a second. Modern graphics hardware can fill a 1600x1200 framebuffer numerous times per frame at 60 fps, so your 640x480 framebuffer will be no problem. Try it and see what you get.

You should definitely take advantage of hardware acceleration. This will give you 1000x performance for very little effort on your part.

If you do find you need to optimise, then the simplest way is to only redraw the areas of the screen that have changed since the last frame. Sounds like you would need to know about any animating tiles, and any tiles that have changed state each frame. Depending on the game, this can be anywhere from no benefit at all, to a massive saving - it really depends on how much of the screen changes each frame.

rikh
A: 

You might consider merging neighbouring tiles with the same texture into a larger polygon with texture tiling (sort of a build process).

Cecil Has a Name
Although this would be a good idea with static tiles, since some of the tiles are non-static, this would mean I'd be constantly rebuilding textures, due to how the animations work in the engine. Otherwise, I'd use this right away.
Sukasa
But wouldn't some be totally static? And even though some might be animated, this wouldn't be a problem if they're meant to be synchronous.
Cecil Has a Name
The animations each run at their own speed. Some tiles animation one step every 8 frames, some every 5 frames, etc.As well, since the actual tilemap can change at a moment's notice, that adds another wrinkle into it.
Sukasa
+2  A: 

Make sure to use alpha transparency only on tiles that actually use alpha, and skip drawing blank tiles. Make sure the tile surface color depth matches the screen color depth when possible (not really an option for tiles with an alpha channel), and store tiles in video memory, so sdl will use hardware acceleration when it can. Color key transparency will be faster than having a full alpha channel, for simple tiles where partial transparency or blending antialiased edges with the background aren't necessary.

On a 500mhz system you'll get about 6.8 cpu cycles per pixel per layer, or 27 per screen pixel, which (I believe) isn't going to be enough if you have full alpha channels on every tile of every layer, but should be fine if you take shortcuts like those mentioned where possible.

David
The only layer where I can guarantee any chance at not having alpha is on the rearmost layer. The other three layers I have no way of predicting which tiles will and which tiles will not use alpha transparency.
Sukasa
+1  A: 

Can you just buffer each complete layer into its view plus an additional tile size for all four ends(if you have vertical scrolling), use the buffer again to create a new buffer minus the first column and drawing on a new end column? This would reduce a lot of needless redrawing.

Additionally, if you want a 60fps, you can look up ways to create frame skip methods for slower systems, skipping every other or every third draw phase.

scott_aw
Thanks for the input, but I ended up switching to openGL 3D acceleration and am now getting over 980 FPS
Sukasa