comparison skaapsteker/sprites/base.py @ 622:da331c80ec08

Clean up sprite inheritance hierarchy a bit.
author Jeremy Thurgood <firxen@gmail.com>
date Sat, 07 May 2011 13:42:27 +0200
parents 851c8726696c
children 65881746dc20
comparison
equal deleted inserted replaced
621:851c8726696c 622:da331c80ec08
32 32
33 33
34 class GameSprite(Sprite): 34 class GameSprite(Sprite):
35 image_dir = 'sprites/' 35 image_dir = 'sprites/'
36 image_file = None 36 image_file = None
37 sprite_layer = None
37 38
38 def __init__(self, pos, **opts): 39 def __init__(self, pos, **opts):
39 Sprite.__init__(self) 40 Sprite.__init__(self)
40 self._starting_tile_pos = pos 41 if self.sprite_layer is not None:
42 # pygame's Sprite class clobbers self._layer in __init__(), so we need to thwart it.
43 self._layer = self.sprite_layer
44 self.setup_image_data(pos)
41 self.setup(**opts) 45 self.setup(**opts)
42 self.setup_image_data(pos)
43 46
44 def setup(self): 47 def setup(self):
45 pass 48 pass
49
50 def get_tile_pos(self):
51 return cdiv(self.rect.center, TILE_SIZE)
46 52
47 def setup_image_data(self, pos): 53 def setup_image_data(self, pos):
48 self.image = data.load_image(self.image_dir + self.image_file) 54 self.image = data.load_image(self.image_dir + self.image_file)
49 self.rect = self.image.get_rect(midbottom=tile_midbottom(pos)) 55 self.rect = self.image.get_rect(midbottom=tile_midbottom(pos))
50 self.collide_rect = self.rect.move(0, 0) 56 self.collide_rect = self.rect.move(0, 0)
51 57
52 58
53 class AnimatedGameSprite(Sprite): 59 class AnimatedGameSprite(GameSprite):
54 # folder for animation files, e.g. sprites/foo
55 image_dir = None
56
57 # first item is the starting animation 60 # first item is the starting animation
58 animation_regexes = [ 61 animation_regexes = (
59 # TODO: swap back once we know how to swap 62 # TODO: swap back once we know how to swap
60 ("running", r"^.*_\d+.png$"), 63 ("running", r"^.*_\d+.png$"),
61 ("standing", r"^.*_standing.png$"), 64 ("standing", r"^.*_standing.png$"),
62 ("attacking", r"^.*_attacking.png$"), 65 ("attacking", r"^.*_attacking.png$"),
63 ] 66 )
64 67
65 wants_updates = True 68 wants_updates = True
66
67 frame_pause = 0.1 # default time between animation frames 69 frame_pause = 0.1 # default time between animation frames
68 70 facings = None
69 facings = {} 71
70 72
71 def __init__(self, pos, **opts): 73 def setup_image_data(self, pos):
72 Sprite.__init__(self)
73 self._animations = dict((k, []) for k, r in self.animation_regexes) 74 self._animations = dict((k, []) for k, r in self.animation_regexes)
74 self._frame = 0 75 self._frame = 0
75 self._last_time = 0 76 self._last_time = 0
76 self._animation = self.animation_regexes[0][0] 77 self._animation = self.animation_regexes[0][0]
77 if self.facings and self._animation in self.facings: 78 if self.facings and self._animation in self.facings:
101 if isinstance(pos, pygame.Rect): 102 if isinstance(pos, pygame.Rect):
102 self.collide_rect.midbottom = pos.midbottom 103 self.collide_rect.midbottom = pos.midbottom
103 else: 104 else:
104 self.collide_rect.midbottom = tile_midbottom(pos) 105 self.collide_rect.midbottom = tile_midbottom(pos)
105 self._update_image() 106 self._update_image()
106 self.setup(**opts) 107
107
108 def setup(self):
109 pass
110 108
111 def _update_image(self, force=False): 109 def _update_image(self, force=False):
112 if self.facing: 110 if self.facing:
113 images = self._animations[self._animation][self.facing] 111 images = self._animations[self._animation][self.facing]
114 else: 112 else:
147 self._last_time = time.time() 145 self._last_time = time.time()
148 146
149 147
150 class Monster(AnimatedGameSprite): 148 class Monster(AnimatedGameSprite):
151 149
150 sprite_layer = Layers.PLAYER
152 collision_layer = MONSTER_LAYER 151 collision_layer = MONSTER_LAYER
153 collides_with = set([PC_LAYER, PROJECTILE_LAYER]) 152 collides_with = set([PC_LAYER, PROJECTILE_LAYER])
154 153
155 debug_color = (240, 120, 120) 154 debug_color = (240, 120, 120)
156 155
157 block = True 156 block = True
158 157
159 attack_frame = None # Mark a spefici frame in the animatio n as when the attack lands 158 attack_frame = None # Mark a speficic frame in the animation as when the attack lands
160 attack_damage = 1 159 attack_damage = 1
161 160
162 def __init__(self, pos, **opts): 161 def __init__(self, pos, **opts):
163 AnimatedGameSprite.__init__(self, pos, **opts) 162 AnimatedGameSprite.__init__(self, pos, **opts)
164 self.floor_rect = Rect(self.collide_rect.topleft, (self.collide_rect.width, 2)) 163 self.floor_rect = Rect(self.collide_rect.topleft, (self.collide_rect.width, 2))
165 self._layer = Layers.PLAYER
166 self.health = 10 164 self.health = 10
167 self._done_attack = False 165 self._done_attack = False
168 self.setup(**opts) 166 self.setup(**opts)
169 167
170 def setup(self, fishmonger_count=False): 168 def setup(self, fishmonger_count=False):
271 if self.collide_rect.centerx > floor.collide_rect.centerx: 269 if self.collide_rect.centerx > floor.collide_rect.centerx:
272 self.change_facing() 270 self.change_facing()
273 271
274 class NPC(AnimatedGameSprite): 272 class NPC(AnimatedGameSprite):
275 273
274 sprite_layer = Layers.PLAYER
276 collision_layer = NPC_LAYER 275 collision_layer = NPC_LAYER
277 collides_with = set([]) 276 collides_with = set([])
278 277
279 debug_color = (240, 240, 240) 278 debug_color = (240, 240, 240)
280 bounce_factor = (0, 0) # NPC's don't bounce by default 279 bounce_factor = (0, 0) # NPC's don't bounce by default
281 gravitates = False 280 gravitates = False
282 281
283 block = False 282 block = False
284 actionable = True 283 actionable = True
285
286 def __init__(self, pos, **opts):
287 AnimatedGameSprite.__init__(self, pos, **opts)
288 self._layer = Layers.PLAYER
289 284
290 def setup(self, name, world, dsm, state, facing=None): 285 def setup(self, name, world, dsm, state, facing=None):
291 self.name = name 286 self.name = name
292 self.world = world 287 self.world = world
293 self.dsm = dialogue.DSM(name, world, dsm, state) 288 self.dsm = dialogue.DSM(name, world, dsm, state)
373 mobile = False 368 mobile = False
374 gravitates = False 369 gravitates = False
375 actionable = True 370 actionable = True
376 liftable = True 371 liftable = True
377 372
373 sprite_layer = Layers.PLAYER
378 collision_layer = NPC_LAYER 374 collision_layer = NPC_LAYER
379 375
380 debug_color = (240, 0, 240) 376 debug_color = (240, 0, 240)
381
382 def __init__(self, pos, **opts):
383 GameSprite.__init__(self, pos, **opts)
384 self._layer = Layers.PLAYER
385 377
386 378
387 def setup(self, name, world): 379 def setup(self, name, world):
388 self.name = name 380 self.name = name
389 self.world = world 381 self.world = world
482 mobile = False 474 mobile = False
483 gravitates = False 475 gravitates = False
484 actionable = False 476 actionable = False
485 liftable = False 477 liftable = False
486 image_dir = 'sprites/skulls/' 478 image_dir = 'sprites/skulls/'
479 sprite_layer = Layers.BEHIND
487 debug_color = (255, 255, 0) 480 debug_color = (255, 255, 0)
481
488 482
489 def __init__(self, pos, player=False, **opts): 483 def __init__(self, pos, player=False, **opts):
490 self._pos = pos 484 self._pos = pos
491 if player: 485 if player:
492 self.image_file = 'kitsune.png' 486 self.image_file = 'kitsune.png'
493 else: 487 else:
494 self.image_file = 'monster.png' 488 self.image_file = 'monster.png'
495 GameSprite.__init__(self, pos, **opts) 489 super(Skeleton, self).__init__(pos, **opts)
496 self._layer = Layers.BEHIND
497 490
498 def setup_image_data(self, pos): 491 def setup_image_data(self, pos):
499 GameSprite.setup_image_data(self, pos) 492 GameSprite.setup_image_data(self, pos)
500 # Pixel based rect, not tile: 493 # Pixel based rect, not tile:
501 self.rect = self.image.get_rect(midbottom=self._pos) 494 self.rect = self.image.get_rect(midbottom=self._pos)