[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.