It's a bit more complicated than just what you propose (which is invalid syntax).
The code needs to open the file, then iterate over the rows and columns of map data. Then, for each type of letter it finds, render some kind of tile-based representation - here I've just used red and green blocks. An alternate version could just as easily render bitmaps.
The first thing you need to do is open the file and read the text into a list of strings - one for each line:
map_data = open( map_filename, "rt" ).readlines()
One caveat to this method, is that each line still has its end-of-line on the end. And it would be better to handle errors (like the file being missing), rather than crashing.
Then we create a Surface
, which is just an off-screen image. It needs to be as big as the map is, times the size of the tiles. Since this is created inside the TileMap
class, this gets stored in TileMap.image
(i.e: self.image
).
Next the code iterates through each line, and then each letter drawing a rectangle. The code just uses the constant TILE_SIZE
for this. You need to decide if this is going to work with coloured squares, or bitmaps, etc. - but obviously all your tiles need to use the same size.
# iterate over the map data, drawing the tiles to the surface
x_cursor = 0 # tile position
y_cursor = 0
for map_line in map_data: # for each row of tiles
x_cursor = 0
for map_symbol in map_line: # for each tile in the row
tile_rect = pygame.Rect( x_cursor, y_cursor, TileMap.TILE_SIZE, TileMap.TILE_SIZE )
if ( map_symbol == '.' ):
pygame.draw.rect( self.image, RED, tile_rect )
elif ( map_symbol == '1' ):
pygame.draw.rect( self.image, GREEN, tile_rect )
else:
pass # ignore
etc.
x_cursor += TileMap.TILE_SIZE
y_cursor += TileMap.TILE_SIZE
Note that we make an x_cursor
and y_cursor
. This is the top-left corner of the map-tile about to be drawn. As we step through each character, we update this to the next position on the map.
At each point, the map has a TILE_SIZE by TILE_SIZE (16x16) "cell" into which we draw a coloured square, depending on the type of map item.
At the end of the operation, we have loaded in all the map tiles, and draw the map to an off-screen Surface
(self.image
), which can be draw to the screen quickly and easily.
The TileMap class, simply wraps all this together.
Reference Code:
import pygame
WINDOW_WIDTH = 800
WINDOW_HEIGHT= 600
SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE
#define colours
BLACK = (0,0,0)
RED = ( 200, 0, 0 )
GREEN = (0,255,0)
### Class to render map-data to a surface image
class TileMap:
TILE_SIZE=16 # size of map elements
def __init__( self, map_filename ):
""" Load in the map data, generating a tiled-image """
map_data = open( map_filename, "rt" ).readlines() # Load in map data TODO: handle errors
map_width = len( map_data[0] ) - 1
map_length = len( map_data )
# Create an image to hold all the map tiles
self.image = pygame.Surface( ( map_width * TileMap.TILE_SIZE, map_length * TileMap.TILE_SIZE ) )
self.rect = self.image.get_rect()
# iterate over the map data, drawing the tiles to the surface
x_cursor = 0 # tile position
y_cursor = 0
for map_line in map_data: # for each row of tiles
x_cursor = 0
for map_symbol in map_line: # for each tile in the row
tile_rect = pygame.Rect( x_cursor, y_cursor, TileMap.TILE_SIZE, TileMap.TILE_SIZE )
if ( map_symbol == '.' ):
pygame.draw.rect( self.image, RED, tile_rect )
elif ( map_symbol == '1' ):
pygame.draw.rect( self.image, GREEN, tile_rect )
else:
pass # ignore
etc.
x_cursor += TileMap.TILE_SIZE
y_cursor += TileMap.TILE_SIZE
def draw( self, surface, position=(0,0) ):
""" Draw the map onto the given surface """
self.rect.topleft = position
surface.blit( self.image, self.rect )
### initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), SURFACE )
pygame.display.set_caption("Render Tile Map")
### Load the map
tile_map = TileMap( "map1.txt" )
### Main Loop
clock = pygame.time.Clock()
done = False
while not done:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
# Update the window, but not more than 60fps
window.fill( BLACK )
# Draw the map to the window
tile_map.draw( window )
pygame.display.flip()
clock.tick_busy_loop(60)
pygame.quit()