Mercurial > pavulon
changeset 18:13da8f9bed5f
further clean up the level rendering
| author | sheep@ghostwheel |
|---|---|
| date | Mon, 06 Jul 2009 13:18:46 +0200 |
| parents | 31c17b907fad |
| children | ec5011a0651d |
| files | qq.py |
| diffstat | 1 files changed, 110 insertions(+), 89 deletions(-) [+] |
line wrap: on
line diff
--- a/qq.py Sun Jul 05 23:32:42 2009 +0200 +++ b/qq.py Mon Jul 06 13:18:46 2009 +0200 @@ -4,7 +4,8 @@ import ConfigParser import pygame -from pygame.locals import * +import pygame.locals as pg +# from pygame.locals import * # Motion offsets for particular directions @@ -14,30 +15,36 @@ class TileCache: - """Load the tilesets lazily.""" + """Load the tilesets lazily into global cache""" - def __init__(self): - self.cache = {} + cache = {} - def __call__(self, filename, width=32, height=None): - if height is None: - height = width - key = (filename, width, height) + def __init__(self, width=32, height=None): + self.width = width + self.height = height or width + + def __getitem__(self, filename): + key = (filename, self.width, self.height) try: return self.cache[key] - except: - pass + except KeyError: + tile_table = self.load_tile_table(filename, self.width, self.height) + self.cache[key] = tile_table + return tile_table + + def load_tile_table(self, filename, width, height): + """Load the image and split into tiles.""" + image = pygame.image.load(filename).convert() image_width, image_height = image.get_size() - tiles = [] - for x in range(0, image_width/width): + tile_table = [] + for tile_x in range(0, image_width/width): line = [] - tiles.append(line) - for y in range(0, image_height/height): - line.append(image.subsurface((x*width, y*height, width, - height))) - self.cache[key] = tiles - return tiles + tile_table.append(line) + for tile_y in range(0, image_height/height): + rect = (tile_x*width, tile_y*height, width, height) + line.append(image.subsurface(rect)) + return tile_table class SortedUpdates(pygame.sprite.RenderUpdates): @@ -54,17 +61,17 @@ class Shadow(pygame.sprite.Sprite): """Sprite for shadows.""" - def __init__(self, sprite): - self.image = tiles("shadow.png", 24, 24)[0][0] + def __init__(self, owner): + self.image = TileCache(24, 24)["shadow.png"][0][0] self.image.set_alpha(64) pygame.sprite.Sprite.__init__(self) self.rect = self.image.get_rect() - self.sprite = sprite + self.owner = owner def update(self): """Move the shadow to the right place.""" - self.rect.midbottom = self.sprite.rect.midbottom + self.rect.midbottom = self.owner.rect.midbottom class Sprite(pygame.sprite.Sprite): @@ -73,13 +80,14 @@ is_player = False def __init__(self, pos=(0, 0), frames=None): - pygame.sprite.Sprite.__init__(self) + super(Sprite, self).__init__() if frames: self.frames = frames self.image = self.frames[0][0] self.rect = self.image.get_rect() self.animation = self.stand_animation() self.pos = pos + self.depth = 0 def _get_pos(self): """Check the current position of the sprite on the map.""" @@ -121,7 +129,7 @@ is_player = True def __init__(self, pos=(1, 1)): - self.frames = tiles("player.png") + self.frames = TileCache()["player.png"] Sprite.__init__(self, pos) self.direction = 2 self.animation = None @@ -150,11 +158,16 @@ except StopIteration: self.animation = None - -class Level: +class Level(object): """Load and store the map of the level, together with all the items.""" def __init__(self, filename="level.map"): + self.tileset = '' + self.map = [] + self.items = {} + self.key = {} + self.width = 0 + self.height = 0 self.load_file(filename) def load_file(self, filename="level.map"): @@ -162,16 +175,13 @@ parser = ConfigParser.ConfigParser() parser.read(filename) - self.items = {} - self.key = {} + self.tileset = parser.get("level", "tileset") self.map = parser.get("level", "map").split("\n") for section in parser.sections(): if len(section) == 1: - value = parser.get(section, "name") - self.key[section] = dict(parser.items(section)) - tile_width, tile_height = 24, 16 - self.tiles = tiles(parser.get("level", "tileset"), - tile_width, tile_height) + # value = parser.get(section, "name") + desc = dict(parser.items(section)) + self.key[section] = desc self.width = len(self.map[0]) self.height = len(self.map) y = 0 @@ -188,55 +198,55 @@ def render(self): """Draw the level on the surface.""" - self.image = pygame.Surface((self.width*tile_width, - self.height*tile_height)) - self.overlays = {} - y = 0 + wall = self.is_wall + tile_width, tile_height = 24, 16 + tiles = TileCache(tile_width, tile_height)[self.tileset] + image = pygame.Surface((self.width*tile_width, self.height*tile_height)) + overlays = {} + map_y = 0 for line in self.map: - x = 0 + map_x = 0 for c in line: - if not self.is_wall(x, y): - try: - tile_x, tile_y = self.key[c]['tile'].split(',') - tile_x = int(tile_x) - tile_y = int(tile_y) - except ValueError, KeyError: - tile_x, tile_y = 0, 3 - self.image.blit(self.tiles[tile_x][tile_y], - (x*tile_width, y*tile_height)) + if wall(map_x, map_y): + if not wall(map_x, map_y+1): + if wall(map_x+1, map_y) and wall(map_x-1, map_y): + tile = 1, 2 + elif wall(map_x+1, map_y): + tile = 0, 2 + elif wall(map_x-1, map_y): + tile = 2, 2 + else: + tile = 3, 2 + else: + if wall(map_x+1, map_y+1) and wall(map_x-1, map_y+1): + tile = 1, 1 + elif wall(map_x+1, map_y+1): + tile = 0, 1 + elif wall(map_x-1, map_y+1): + tile = 2, 1 + else: + tile = 3, 1 + if not wall(map_x, map_y-1): + if wall(map_x+1, map_y) and wall(map_x-1, map_y): + over = 1, 0 + elif wall(map_x+1, map_y): + over = 0, 0 + elif wall(map_x-1, map_y): + over = 2, 0 + else: + over = 3, 0 + overlays[(map_x, map_y)] = tiles[over[0]][over[1]] else: - # wall - if not self.is_wall(x, y+1): - if self.is_wall(x+1, y) and self.is_wall(x-1, y): - tile_image = self.tiles[1][2] - elif self.is_wall(x+1, y): - tile_image = self.tiles[0][2] - elif self.is_wall(x-1, y): - tile_image = self.tiles[2][2] - else: - tile_image = self.tiles[3][2] - else: - if self.is_wall(x+1, y+1) and self.is_wall(x-1, y+1): - tile_image = self.tiles[1][1] - elif self.is_wall(x+1, y+1): - tile_image = self.tiles[0][1] - elif self.is_wall(x-1, y+1): - tile_image = self.tiles[2][1] - else: - tile_image = self.tiles[3][1] - self.image.blit(tile_image, (x*tile_width, y*tile_height)) - if not self.is_wall(x, y-1): - if self.is_wall(x+1, y) and self.is_wall(x-1, y): - overlay_image = self.tiles[1][0] - elif self.is_wall(x+1, y): - overlay_image = self.tiles[0][0] - elif self.is_wall(x-1, y): - overlay_image = self.tiles[2][0] - else: - overlay_image = self.tiles[3][0] - self.overlays[(x, y)] = overlay_image - x += 1 - y += 1 + try: + tile = self.key[c]['tile'].split(',') + tile = int(tile[0]), int(tile[1]) + except (ValueError, KeyError): + tile = 0, 3 + tile_image = tiles[tile[0]][tile[1]] + image.blit(tile_image, (map_x*tile_width, map_y*tile_height)) + map_x += 1 + map_y += 1 + return image, overlays def get_tile(self, x, y): """Tell what's at the specified position of the map.""" @@ -275,10 +285,15 @@ class Game: + """The main game object.""" + def __init__(self): self.screen = pygame.display.get_surface() self.pressed_key = None self.game_over = False + self.shadows = pygame.sprite.RenderUpdates() + self.sprites = SortedUpdates() + self.overlays = pygame.sprite.RenderUpdates() self.use_level(Level()) def use_level(self, level): @@ -293,34 +308,41 @@ sprite = Player(pos) self.player = sprite else: - sprite = Sprite(pos, tiles(tile["sprite"])) + sprite = Sprite(pos, TileCache()[tile["sprite"]]) self.sprites.add(sprite) self.shadows.add(Shadow(sprite)) - for pos, image in level.overlays.iteritems(): + self.background, overlays = self.level.render() + for pos, image in overlays.iteritems(): x, y = pos overlay = pygame.sprite.Sprite(self.overlays) overlay.image = image overlay.rect = image.get_rect().move(x*24, y*16-16) - self.background = self.level.image.copy() def control(self): """Handle the controls of the game.""" keys = pygame.key.get_pressed() + def pressed(key): + """Check if the key is pressed.""" + return self.pressed_key == key or keys[key] + def walk(d): + """Start walking in specified direction.""" + x, y = self.player.pos self.player.direction = d if not self.level.is_blocking(x+DX[d], y+DY[d]): self.player.animation = self.player.walk_animation() - if pressed(K_UP): + + if pressed(pg.K_UP): walk(0) - elif pressed(K_DOWN): + elif pressed(pg.K_DOWN): walk(2) - elif pressed(K_LEFT): + elif pressed(pg.K_LEFT): walk(3) - elif pressed(K_RIGHT): + elif pressed(pg.K_RIGHT): walk(1) self.pressed_key = None @@ -349,9 +371,9 @@ pygame.display.update(dirty) clock.tick(15) for event in pygame.event.get(): - if event.type == QUIT: + if event.type == pg.QUIT: self.game_over = True - elif event.type == KEYDOWN: + elif event.type == pg.KEYDOWN: self.pressed_key = event.key @@ -359,5 +381,4 @@ pygame.init() pygame.display.set_mode((424, 320)) # font = pygame.font.Font("MgOpenModataBold.ttf", 11) - tiles = TileCache() Game().main()
