Mercurial > skaapsteker
view skaapsteker/sprites/base.py @ 214:6e7faba82c21
Remove debugging pdb.
author | Simon Cross <hodgestar@gmail.com> |
---|---|
date | Thu, 07 Apr 2011 00:36:29 +0200 |
parents | c5c4306593d8 |
children | fcc5eca8eaca |
line wrap: on
line source
"""Basic sprite classes.""" from pygame import Rect import re from skaapsteker.physics import Sprite from skaapsteker.constants import Layers from skaapsteker import data from skaapsteker import dialogue TILE_SIZE = (64, 64) # Collision Layers (values are ids not numbers) PC_LAYER = 0 MONSTER_LAYER = 1 NPC_LAYER = 2 class GameSprite(Sprite): image_dir = 'sprites/' image_file = None def __init__(self, pos, **opts): Sprite.__init__(self) self.image = data.load_image(self.image_dir + self.image_file) self.rect = self.image.get_rect(midbottom=(pos[0]*TILE_SIZE[0]+TILE_SIZE[0]/2, (pos[1]+1)*TILE_SIZE[1])) self.collide_rect = self.rect.move(0, 0) self.setup(**opts) class AnimatedGameSprite(Sprite): # folder for animation files, e.g. sprites/foo image_dir = None # first item is the starting animation animation_regexes = [ # TODO: swap back once we know how to swap ("running", r"^.*_\d+.png$"), ("standing", r"^.*_standing.png$"), ] wants_updates = True def __init__(self, pos, **opts): Sprite.__init__(self) self._animations = dict((k, []) for k, r in self.animation_regexes) self._frame = 0 self._tick = 0 # TODO: hack to show some animation; kill shortly self._animation = self.animation_regexes[0][0] for image in data.get_files(self.image_dir): print image for name, pattern in self.animation_regexes: if re.match(pattern, image): img = data.load_image("%s/%s" % (self.image_dir, image)) collide_rect = img.get_bounding_rect(1).inflate(-2,-2) self._animations[name].append((img, collide_rect)) self.collide_rect = Rect((0, 0), (2, 2)) self.collide_rect.midbottom = (pos[0]*TILE_SIZE[0]+TILE_SIZE[0]/2, (pos[1]+1)*TILE_SIZE[1]) self._update_image() self.setup(**opts) def _update_image(self): images = self._animations[self._animation] if self._frame >= len(images): self._frame = 0 cand_image, cand_collide_rect = images[self._frame] cand_collide_rect = cand_collide_rect.move(0, 0) # copy collide rect before we move it cur_pos = self.collide_rect.midbottom cand_rect = cand_image.get_rect() cand_rect_offset = cand_rect.centerx - cand_collide_rect.centerx, cand_rect.bottom - cand_collide_rect.bottom cand_rect.midbottom = cur_pos[0] + cand_rect_offset[0], cur_pos[1] + cand_rect_offset[1] cand_collide_rect.midbottom = cur_pos if not self.check_collide_rect(cand_collide_rect, cand_rect, cand_image): return self.image = cand_image self.collide_rect = cand_collide_rect self.rect = cand_rect self.rect_offset = cand_rect_offset self.init_pos() def update(self): if self._tick > 10: self._tick = 0 self._frame += 1 self._update_image() self._tick += 1 class Monster(GameSprite): collision_layer = MONSTER_LAYER collides_with = set([PC_LAYER]) debug_color = (240, 120, 120) block = True def __init__(self, pos, **opts): GameSprite.__init__(self, pos, **opts) self.floor_rect = Rect(self.collide_rect.topleft, (self.collide_rect.width, 2)) self._layer = Layers.PLAYER self.health = 10 self.setup(**opts) def collided_player(self, player): print "%s collided with player" % self player.damage(1) def damage(self, damage): print 'Damaged by ', damage self.health -= damage print 'Monster health', self.health if self.health < 0: self.kill() class NPC(AnimatedGameSprite): collision_layer = NPC_LAYER collides_with = set([PC_LAYER]) debug_color = (240, 240, 240) block = False def __init__(self, pos, **opts): AnimatedGameSprite.__init__(self, pos, **opts) self._layer = Layers.PLAYER def setup(self, name, world, dsm): self.dsm = dialogue.DSM(name, world, dsm) def collided_player(self, player): print "%s is ignoring player" % self class Projectile(GameSprite): gravitates = False class Item(GameSprite): mobile = False gravitates = False collision_layer = MONSTER_LAYER collides_with = set([PC_LAYER]) portable = True def __init__(self, pos, **opts): GameSprite.__init__(self, pos, **opts) self._layer = Layers.PLAYER def setup(self, name, world): self.name = name self.world = world def get_debug_color(self): if self.portable: return (240, 0, 240) return (0, 0, 240) def collided_player(self, player): print "Player touched %s" % self player.take_item(self) class Geography(Sprite): mobile = False gravitates = False collides_with = set([PC_LAYER, MONSTER_LAYER, NPC_LAYER]) is_ground = True bounce_factor = (0.0, 0.0) def __init__(self, pos, image): Sprite.__init__(self) self.tile_pos = pos self.image = image self.collide_rect = self.image.get_bounding_rect(1) self.floor_rect = Rect(self.collide_rect.topleft, (self.collide_rect.width, 2)) self.rect = self.image.get_rect() self.rect_offset = self.collide_rect.left - self.rect.left, self.rect.top - self.rect.top self.collide_rect.topleft = pos[0] * TILE_SIZE[0] + self.rect_offset[0], pos[1] * TILE_SIZE[1] + self.rect_offset[1] self.floor_rect.topleft = pos[0] * TILE_SIZE[0] + self.rect_offset[0], pos[1] * TILE_SIZE[1] + self.rect_offset[1] self.rect.topleft = pos[0] * TILE_SIZE[0], pos[1] * TILE_SIZE[1] def get_debug_color(self): if self.floor or self.block: return (240, 240, 0) return (0, 240, 0) def find_sprite(descr, mod_name=None): """Create a sprite object from a dictionary describing it.""" descr = descr.copy() cls_name = descr.pop("type") if mod_name is None: mod_name, cls_name = cls_name.rsplit(".", 1) mod_name = ".".join(["skaapsteker.sprites", mod_name]) mod = __import__(mod_name, fromlist=[cls_name]) cls = getattr(mod, cls_name) return cls(**descr)