[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Re: Tile scrolling game



Pete Shinners wrote:

I'm currently attempting to write a top down scrolling RPG type game in Pygame, using tiles.

Of course, problems arise with large maps filled with tiles, as the frame rate plummets. I'd like the game to be set on a single island, meaning that the amount of tiles in memory at once is currently huge (for the moment I'm working with 50*50, since that leaves me with a workable framerate of 17). The framerate needn't be too perfect, but obviously it'd be nicer to make it smoother and have bigger islands.

Basically, two questions:
1) What is it that slows down the redraw - attemping 2500 blits per cycle, or attemping 2500 * 40 * 40 (sprites) per cycle? In other words - could I create a bigger (more tiles) island by decreasing the tile size?
2) How easy would it be to implement a system where it only keeps tiles in memory which are, say, within 20 tiles distance from the player?

Alex, the Sprite system won't be that efficient for a tiled background. A tiled background is a more defined set of data that can be more efficiently handled.

Just so you know, when SDL does a blit to a position outside the destination image, it does not actual blitting. Still, rectangle bounds much be checked and doing that a significan number of times will begin to be visible.

If you are doing a vertical scroller, it shouldn't be difficult to isolate the map into smaller sections. The map can likely only scroll in one direction, so once something passes off the bottom it can be discarded. Plus, given the position of the player it should be simple to know which tiles will be visible, and only deal with rendering those.

Fullscreen scrolling is possible with SDL and pygame, and should be able to run at higher framerates than you are seeing. Still, it takes a bit of care to make sure Python doesn't get in the way of these sorts of things, performance wise.

There are two factors affecting the speed here:

Pixel Fill Cost
and
Tile Handling Cost

Since SDL does not draw outside of the screen, Pixel Fill Cost should just depend on the screen area in pixels.

Tile Handling Cost depends on how many tiles you have, and how you draw them (and how they are organized).

For example:
If you have 100x100 tiles in one list, that's 10000 tiles.
tiles_list = [tile('grass') for n in range(10000)]
Drawing them by looping through the list would incur 10000 times the cost of thinking about one tile.
- Less tiles would be faster
- More efficient processing would be faster:

If tiles are arranged in a grid, then if you have 100 lists (one for each row for example)
like this:

rows = [[tile('grass') for x in range(100)] for y in range(100)]

and then when rendering, loop through the rows:

for y in range(100):
row = rows[y]
# Decide if this row can be skipped
...
# Draw this row
...

then you can get a speedup depending on how many rows must be drawn to cover the screen
for example if 10 rows must be drawn to cover the screen, it should be about as fast as 10x100.

If you increase the number of rows (say to 1000) it will get somewhat slower again.
you can fix this by deciding (without iterating through all the rows) which rows need to be drawn before-hand.
Like:

ymin = # decide which row is first (uppermost) on the screen
ymax = # decide which row is last (lowermost) on the screen

You can do this similarly for the columns (xmin, xmax)

and then loop through the tiles that you want to draw
for y in range(ymin, ymax+1):
for x in range(xmin, xmax+1):
# draw tile...

If you have really huge! quantities of tiles and do not need to have them all loaded, you can either set up a system to load rows as needed, or use a grid of tile grids (big chunks) and them load them as needed.