Mercurial > pygame-tutorial
view 003/006.py @ 12:9dc97f88e274 default tip
Added CC0 license
| author | Radomir Dopieralski <sheep-devel@sheep.art.pl> |
|---|---|
| date | Sun, 08 Jul 2012 19:56:38 +0200 |
| parents | 2a0f43c87b80 |
| children |
line wrap: on
line source
#!/usr/bin/env python # -*- coding: utf-8 -*- import pygame import pygame.locals as pg from pytmx import tmxloader FACING = { (0, -1): 0, (-1, 0): 1, (0, 1): 2, (1, 0): 3, } def load_sheet(filename, width=32, height=None): if height is None: height = width image = pygame.image.load(filename) image = image.convert() image.set_colorkey((0xff, 0, 0xff)) w, h = image.get_size() images = [] for x in xrange(w // width): for y in xrange(h // height): rect = pygame.rect.Rect(x * width, y * height, width, height) images.append(image.subsurface(rect)) return images class ShadowSprite(pygame.sprite.Sprite): def __init__(self, sprite): super(ShadowSprite, self).__init__() self.spritesheet = load_sheet('effects.png', 32) self.image = self.spritesheet[0] self.rect = self.image.get_rect() self.image.set_alpha(0.6 * 255) self.sprite = sprite self.rect.midbottom = self.sprite.rect.midbottom def update(self): self.rect.midbottom = self.sprite.rect.midbottom class HeroSprite(pygame.sprite.Sprite): def __init__(self, (x, y)): super(HeroSprite, self).__init__() self.spritesheet = load_sheet('spritesheet.png', 64) self.facing = 2 self.image = self.spritesheet[self.facing] self.rect = self.image.get_rect() self.rect.midbottom = (x * 32 + 16, y * 32 + 32) self.animations = [] def move(self, (dx, dy)): self.facing = FACING[dx, dy] self.animations.append(self.animation_walk((dx, dy))) def animation_walk(self, (dx, dy)): for step in xrange(8): self.image = self.spritesheet[self.facing + step * 4 + 4] self.rect.move_ip(dx * 4, dy * 4) yield def animation_stand(self): self.image = self.spritesheet[self.facing] return yield def update(self): if not self.animations: self.animations.append(self.animation_stand()) while self.animations: try: self.animations[0].next() return except StopIteration: self.animations.pop(0) class Level(object): def __init__(self, filename): self.tiled_map = tmxloader.load_pygame(filename) self.hero_position = 1, 1 def render(self, screen): w = self.tiled_map.tilewidth h = self.tiled_map.tileheight get_image = self.tiled_map.getTileImage for l, layer in enumerate(self.tiled_map.tilelayers): for y in xrange(self.tiled_map.height): for x in xrange(self.tiled_map.width): image = get_image(x, y, l) if image: screen.blit(image, (x * w, y * h)) x, y = self.hero_position def get_properties(self, (x, y)): properties = {} for l, layer in enumerate(self.tiled_map.tilelayers): properties.update(self.tiled_map.getTileProperties((x, y, l)) or {}) return properties def is_blocked(self, (x, y)): return self.get_properties((x, y)).get('block') def move_hero(self, (dx, dy)): x, y = self.hero_position if not self.is_blocked((x + dx, y + dy)): self.hero_position = x + dx, y + dy return True return False class Game(object): def __init__(self): pygame.display.init() pygame.font.init() self.screen = pygame.display.set_mode((800, 600)) self.screen.fill((0x66, 0x66, 0x66)) self.keys = { pg.K_UP: (self.move_hero, (0, -1)), pg.K_DOWN: (self.move_hero, (0, 1)), pg.K_LEFT: (self.move_hero, (-1, 0)), pg.K_RIGHT: (self.move_hero, (1, 0)), pg.K_ESCAPE: (self.quit,), } self.shadow_sprites = pygame.sprite.RenderUpdates() self.sprites = pygame.sprite.RenderUpdates() self.key = None def load_level(self, filename): self.level = Level(filename) self.hero_sprite = HeroSprite(self.level.hero_position) self.sprites.add(self.hero_sprite) self.shadow_sprites.add(ShadowSprite(self.hero_sprite)) self.background = self.screen.copy() self.level.render(self.background) self.screen.blit(self.background, (0, 0)) self.sprites.draw(self.screen) pygame.display.update() def quit(self): self.game_over = True def move_hero(self, direction): if self.level.move_hero(direction): self.hero_sprite.move(direction) def control(self): for event in pygame.event.get(): if event.type == pg.QUIT: self.quit() elif event.type == pg.KEYDOWN: self.key = event.key if not self.hero_sprite.animations: keys = pygame.key.get_pressed() for key, action in self.keys.iteritems(): if keys[key] or self.key == key: action[0](*action[1:]) break self.key = None def display(self): self.sprites.clear(self.screen, self.background) self.shadow_sprites.clear(self.screen, self.background) self.sprites.update() self.shadow_sprites.update() dirty = [] dirty.extend(self.shadow_sprites.draw(self.screen)) dirty.extend(self.sprites.draw(self.screen)) pygame.display.update(dirty) def run(self): self.clock = pygame.time.Clock() self.game_over = False while not self.game_over: self.display() self.control() self.clock.tick(30) if __name__ == '__main__': game = Game() game.load_level('level.tmx') game.run()
