[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[pygame] Optimising a tile map renderer
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