Mercurial > undermine
changeset 17:b69ed0cdaee6
refactor level map
| author | Radomir Dopieralski <sheep-devel@sheep.art.pl> |
|---|---|
| date | Sun, 27 Apr 2014 14:49:31 +0200 |
| parents | 199d98200586 |
| children | fa49938e730f |
| files | undermine/game.py undermine/level.py undermine/sprites.py |
| diffstat | 3 files changed, 151 insertions(+), 107 deletions(-) [+] |
line wrap: on
line diff
--- a/undermine/game.py Sun Apr 27 00:43:19 2014 -0700 +++ b/undermine/game.py Sun Apr 27 14:49:31 2014 +0200 @@ -1,23 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import random import pygame import undermine.display import undermine.resources import undermine.sprites - - -MAP_DIRT, MAP_TUNNEL, MAP_BOULDER, MAP_GEM, MAP_HERO = range(5) -TILES = { - MAP_DIRT: 12, - MAP_TUNNEL: 15, - MAP_BOULDER: 15, - MAP_GEM: 15, - MAP_HERO: 15, -} +import undermine.level class Game(object): @@ -25,117 +15,80 @@ self.fps = fps self.display = undermine.display.Display( (map_size[0] * 64, map_size[1] * 64)) - self.display.background = undermine.resources.load_image('title.png') - self.display.refresh() self.clock = pygame.time.Clock() self.images = undermine.resources.load_atlas('undermine.png', 64) - self.theme = undermine.resources.load_sound('undermine.ogg') - self.eulogy= undermine.resources.load_sound('death.ogg') - self.make_map(map_size) + # self.theme = undermine.resources.load_sound('undermine.ogg') + # self.eulogy= undermine.resources.load_sound('death.ogg') + self.level = undermine.level.Level(map_size) + self.level.generate(self.images) + self.hero = self.level.hero def move(self, dx, dy): x, y = self.hero.pos - if not (0 <= x + dx < len(self.map[0]) and - 0 <= y + dy < len(self.map)): + try: + target = self.level[x + dx, y + dy] + except IndexError: return - if self.map[y + dy][x + dx] == MAP_BOULDER: + if target and target.block: return self.hero.animations.append(self.hero.move_anim(dx, dy)) - self.hero.place((x + dx, y + dy), False) - if self.map[y + dy][x + dx] == MAP_DIRT: - self.dig((x + dx, y + dy)) - elif self.map[y + dy][x + dx] == MAP_GEM: - for boulder in self.boulders: - if boulder.pos == (x + dx, y + dy): - boulder.animations.append(boulder.pick_anim()) - break - self.map[y + dy][x + dx] = MAP_HERO - self.map[y][x] = MAP_TUNNEL + self.dig((x + dx, y + dy)) + if target and target.pick: + target.animations.append(target.pick_anim()) + self.level.shove((x, y), (dx, dy)) def dig(self, (x, y)): - self.display.background.blit(self.images[TILES[MAP_TUNNEL]], - (x * 64, y * 64)) + if not self.level.get_dirt((x, y), False): + return + self.level.set_dirt((x, y), False) + self.display.background.blit(self.images[15], (x * 64, y * 64)) dirt = undermine.sprites.Dirt(self.images) - dirt.place((x, y)) + dirt.pos = x, y self.display.back_sprites.add(dirt) def die(self): self.theme.stop() - self.eulogy.play() + # self.eulogy.play() self.hero.animations.append(self.hero.death_anim()) - def make_map(self, map_size): - self.boulders = pygame.sprite.Group() - squares = [] - self.map = [] - for y in range(map_size[1]): - self.map.append([]) - for x in range(map_size[0]): - self.map[-1].append(0) - squares.append((x, y)) - random.shuffle(squares) - self.hero = undermine.sprites.Hero(self.images) - self.hero.place(squares.pop()) - self.display.sprites.add(self.hero) - self.map[self.hero.pos[1]][self.hero.pos[0]] = MAP_HERO - for i in range(8): - boulder = undermine.sprites.Boulder(self.images[4]) - x, y = squares.pop() - boulder.place((x, y)) - self.display.sprites.add(boulder) - self.boulders.add(boulder) - self.map[y][x] = MAP_BOULDER - for i in range(4): - gem = undermine.sprites.Gem(self.images[8]) - x, y = squares.pop() - gem.place((x, y)) - self.display.sprites.add(gem) - self.boulders.add(gem) - self.map[y][x] = MAP_GEM - def draw_map(self): - for y, row in enumerate(self.map): - for x, tile in enumerate(row): - self.display.background.blit(self.images[TILES[tile]], - (x * 64, y * 64)) + self.level.draw(self.display.background, self.images) + self.display.sprites.add(self.level) def update_boulders(self): - boulders = sorted(self.boulders, key=lambda b: -b.pos[1]) - for boulder in boulders: - if boulder.animations: + for thing in sorted(self.level, key=lambda b: -b.pos[1]): + if not thing.fall: continue - x, y = boulder.pos + if thing.animations: + continue + x, y = thing.pos fell = False - if y + 1 < len(self.map) and self.map[y + 1][x] == MAP_TUNNEL: - boulder.animations.append(boulder.fall_anim()) - self.map[y + 1][x] = self.map[y][x] - self.map[y][x] = MAP_TUNNEL - boulder.place((x, y +1), False) + if not self.level.get_support((x, y + 1)): + thing.animations.append(thing.fall_anim()) + self.level.shove((x, y), (0, 1)) fell = True - elif (y + 1 < len(self.map) and - self.map[y + 1][x] in (MAP_BOULDER, MAP_GEM)): - if (x > 0 and - self.map[y][x - 1] == MAP_TUNNEL and - self.map[y + 1][x - 1] == MAP_TUNNEL): - boulder.animations.append(boulder.roll_anim(-1)) - self.map[y + 1][x - 1] = self.map[y][x] - self.map[y][x] = MAP_TUNNEL - boulder.place((x - 1, y + 1), False) + elif (not self.level.get_dirt((x, y + 1), True) and + self.level[x, y + 1] != self.hero): + if (not self.level.get_support((x - 1, y)) and + not self.level.get_support((x - 1, y + 1))): + thing.animations.append(thing.roll_anim(-1)) + self.level.shove((x, y), (-1, 1)) fell = True - elif (x + 1 < len(self.map[0]) and - self.map[y][x + 1] == MAP_TUNNEL and - self.map[y + 1][x + 1] == MAP_TUNNEL): - boulder.animations.append(boulder.roll_anim(1)) - self.map[y + 1][x + 1] = self.map[y][x] - self.map[y][x] = MAP_TUNNEL - boulder.place((x + 1, y + 1), False) + elif (not self.level.get_support((x + 1, y)) and + not self.level.get_support((x + 1, y + 1))): + thing.animations.append(thing.roll_anim(1)) + self.level.shove((x, y), (1, 1)) fell = True - if (fell and y +2 < len(self.map) and - self.map[y + 2][x] == MAP_HERO): - self.die() + if fell: + self.dig((x, y)) + try: + if self.level[x, y + 2] == self.hero: + self.die() + except IndexError: + pass def run(self): - self.theme.play(loops=-1) + # self.theme.play(loops=-1) self.draw_map() self.display.refresh() while True:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/undermine/level.py Sun Apr 27 14:49:31 2014 +0200 @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import random +import undermine.sprites + + +class Level(object): + def __init__(self, size=(12, 12)): + self.size = size + self.dirt = [[True] * size[0] for y in range(size[1])] + self.things = [[None] * size[0] for y in range(size[1])] + + def get(self, (x, y), default=None): + try: + return self[x, y] + except IndexError: + return default + + def __getitem__(self, (x, y)): + return self.things[y][x] + + def __setitem__(self, (x, y), thing): + self.things[y][x] = thing + if thing: + thing.pos = x, y + + def get_dirt(self, (x, y), default=None): + try: + return self.dirt[y][x] + except IndexError: + return default + + def get_support(self, (x, y)): + return self.get_dirt((x, y), True) or self[x, y] and self[x, y].support + + def set_dirt(self, (x, y), dirt): + try: + self.dirt[y][x] = dirt + except IndexError: + pass + + def shove(self, (x, y), (dx, dy)): + self[x + dx, y + dy] = self[x, y] + self[x, y] = None + + def draw(self, surface, images): + for y, row in enumerate(self.dirt): + for x, dirt in enumerate(row): + image = images[12] if dirt else images[15] + surface.blit(image, (x * 64, y * 64)) + + def __iter__(self): + for row in self.things: + for thing in row: + if thing: + yield thing + + def generate(self, images): + squares = [(x, y) + for y, row in enumerate(self.dirt) + for x, dirt in enumerate(row) + ] + random.shuffle(squares) + self.hero = undermine.sprites.Hero(images) + self[squares.pop()] = self.hero + self.set_dirt(self.hero.pos, False) + for i in range(8): + self[squares.pop()] = undermine.sprites.Boulder(images[4]) + for i in range(4): + self[squares.pop()] = undermine.sprites.Gem(images[8])
--- a/undermine/sprites.py Sun Apr 27 00:43:19 2014 -0700 +++ b/undermine/sprites.py Sun Apr 27 14:49:31 2014 +0200 @@ -4,20 +4,28 @@ import pygame -class Animated(pygame.sprite.Sprite): +class Thing(pygame.sprite.Sprite): + block = False + pick = False + fall = False + support = False + def __init__(self, image): - super(Animated, self).__init__() + super(Thing, self).__init__() self.image = image self.rect = image.get_rect() self.animations = [] - self.pos = 0, 0 + self._pos = None + + @property + def pos(self): + return self._pos - def place(self, (x, y), move=True): - dx = x - self.pos[0] - dy = y - self.pos[1] - self.pos = x, y - if move: - self.rect.move_ip(dx * 64, dy * 64) + @pos.setter + def pos(self, (x, y)): + if self._pos is None: + self.rect.move_ip(x * 64, y * 64) + self._pos = x, y def update(self): animations = [] @@ -32,7 +40,10 @@ -class Hero(Animated): +class Hero(Thing): + block = True + support = True + def __init__(self, images): super(Hero, self).__init__(images[0]) self.images = images @@ -65,7 +76,11 @@ self.kill() -class Boulder(Animated): +class Boulder(Thing): + block = True + fall = True + support = True + def fall_anim(self): for step in [1, 2, 4 , 8, 16, 32, 1]: self.rect.move_ip(0, step) @@ -80,6 +95,11 @@ yield None class Gem(Boulder): + block = False + pick = True + fall = True + support = True + def pick_anim(self): for step in [27, 9, 3, 1]: self.rect.move_ip(0, -step) @@ -90,7 +110,7 @@ self.kill() -class Dirt(Animated): +class Dirt(Thing): def __init__(self, images): super(Dirt, self).__init__(images[8]) self.images = images
