Best way to speed up this kind of game is only updating the bits of the
screen which change (e.g. dirty sprite list). You might also see speed
improvements from using sprites rather than blitting to a surface, e.g.
one sprite per tile. Makes it a lot easier to implement a dirty sprite
list too (since this is built into some of pygame's sprite group classes).
I wrote the basics of an iso game engine which does basically the same
thing as this (grid of tiles), you might want to have a look for
inspiration :)
http://www.pygame.org/project-pyTile-871-.html
It doesn't have scrolling optimisation (but doing that for a top-down
grid game is easier than for iso, using scrolled offsets to calculate
the number of new sprites to add to the spritegroup). As an example, my
game above gets around 300-400fps, which drops to 20-40fps when you
scroll. This is because when you scroll it's redrawing all tiles on the
screen. Never got around to optimising that.
On 05/03/2010 10:20, Leith wrote:
Hi,
I am trying to make a pygame version of SimCity using the open source
Micropolis engine.
The engine spits out a 2d array of tile indexes that form the world
map.
I am having problems getting it to run fast at decent resolutions...
Here is the code:
class Map:
def __init__(self, engine):
self.engine = engine
tilesFileName = 'images/micropolisEngine/tiles.png'
self.tileSize = micropolisengine.EDITOR_TILE_SIZE
tileSize = self.tileSize
self.tiles = pygame.image.load(tilesFileName).convert()
self.tilesPerRow = self.tiles.get_width() / self.tileSize
self.worldWidth = micropolisengine.WORLD_W
self.worldHeight = micropolisengine.WORLD_H
self.width = self.worldWidth * tileSize
self.height = self.worldHeight * tileSize
def draw(self, surface, view):
engine = self.engine
tileSize = self.tileSize
for y in range(view.top / tileSize, view.bottom / tileSize +
1):
for x in range(view.left / tileSize, view.right / tileSize
+ 1):
tile = engine.getTile(x, y)
if tile == micropolisengine.TILE_INVALID:
break
# FIXME - why is blinking not working?
if engine.blinkFlag and (tile&
micropolisengine.ZONEBIT) and not (tile& micropolisengine.PWRBIT):
index = micropolisengine.LIGHTNINGBOLT
else:
index = tile&
micropolisengine.LOMASK
# FIXME - why do we get these from the sim engine?
if index> 960:
print "Tile (%d, %d) is out of bounds = %d" % (x,
y, tile)
break
if index>= micropolisengine.TILE_COUNT:
break
surface.blit(
self.tiles,
pygame.Rect(
x * tileSize - view.left,
y * tileSize - view.top,
tileSize,
tileSize),
pygame.Rect(
(index % self.tilesPerRow) * tileSize,
(index / self.tilesPerRow) * tileSize,
tileSize,
tileSize))
cProfile shows that the surface.blit and engine.getTiles calls are the
slow ones.
At this stage I can't do too much about getTiles, but I would like to
speed up the blitting.
Also I hope at one stage I can a list of 'dirty' tiles to reduce the
number of tiles to render, but that might take a while.
If it is not possible to do it fast with pygame are there any other
fast 2d python libraries?
I get about 37-40 FPS on my gaming rig at fullscreen 1280*1024:
Windows 7 64bit
ATI Radeon HD 5850
AMD Phenom II X4 @ 3.21GHz
4GB 1600 MHz DDR3