Mercurial > zday-deluxe
changeset 3:1cafd23c69ea default tip
use sprites for creatures
| author | sheep@ghostwheel |
|---|---|
| date | Fri, 24 Oct 2008 17:20:35 +0200 |
| parents | 0b0d0e806f33 |
| children | |
| files | creatures.png creatures.py display.py tiles.png world.py zday.py |
| diffstat | 6 files changed, 178 insertions(+), 105 deletions(-) [+] |
line wrap: on
line diff
--- a/creatures.py Sun Dec 16 14:55:57 2007 +0100 +++ b/creatures.py Fri Oct 24 17:20:35 2008 +0200 @@ -3,11 +3,13 @@ from util import * from light import Light +import pygame + def game_win(disp): disp.clear() disp.pause() sys.exit() - + def game_over(disp): disp.clear() disp.pause() @@ -16,8 +18,8 @@ class ActError(Exception): pass -class Zombie: - def __init__(self, world, pos = None): +class Zombie(object): + def __init__(self, world, pos=None): self.world = world if pos: self.pos = pos @@ -26,13 +28,12 @@ y = random.randrange(1, world.height-2) while world.flags[x][y] & (FLAG_BLOCKED | FLAG_CREATURE): x += 1 - if x>=world.width-1: + if x >= world.width-1: x = 1 y += 1 self.pos = (x, y) self.target = None self.effect = None - world.creatures.append(self) self.world.flags[self.pos[0]][self.pos[1]] |= FLAG_CREATURE self.burning = 0 self.dead = 0 @@ -42,7 +43,7 @@ def trip(self): if not self.burning: self.tripped = 1 - + def untrip(self): if not self.burning: self.tripped = 0 @@ -56,14 +57,10 @@ if self.world.flags[x][y] & FLAG_LETHAL: self.world.add_tile(self.pos, MAP_MACHINE+1) else: - if random.randrange(100)>20: + if random.randrange(100) > 20: self.world.add_tile(self.pos, self.world.corpse) else: self.world.blood(self.pos, 4) - for i in range(len(self.world.creatures)): - if self.world.creatures[i]==self: - del self.world.creatures[i] - break def bleed(self, amount=50): """Fills the map around the creature with blood.""" @@ -73,14 +70,14 @@ x = self.pos[0] + dx y = self.pos[1] + dy splatter = (random.randrange(100)+amount)/50 - self.world.blood((x,y), splatter) + self.world.blood((x, y), splatter) def wound(self, lethality): - if lethality>0: + if lethality > 0: self.effect = EFF_HIT - if random.randrange(100)<lethality: + if random.randrange(100) < lethality: self.kill() - elif lethality>50: + elif lethality > 50: self.trip() def metabolism(self): @@ -92,7 +89,7 @@ self.trip() if self.burning: self.effect = EFF_BURN - if random.randrange(100)>90: + if random.randrange(100) > 90: self.kill() def burn(self): @@ -210,7 +207,7 @@ self.act_go(0, dy) except ActError: pass - + class Hero(Zombie): def __init__(self, world, disp, pos=None): Zombie.__init__(self, world, pos) @@ -225,19 +222,21 @@ self.disp.inv_draw(self.inventory) self.stamina = 100 self.wounds = 0 - self.dead = 0 + self.dead = False self.food = 0 self.aim = None self.hero = 1 + self.command = (None, None) def kill(self): + self.dead = True self.world.msg.write("Aaargh! They got me! Plant an orchid on my grave...") game_over(self.disp) def wound(self, lethality=0): self.effect = EFF_HIT - if self.stamina==0: + if self.stamina == 0: self.kill() if self.wounds<5: self.wounds+=1 @@ -486,82 +485,57 @@ break def act_operate(self): - x, y = self.pos; + x, y = self.pos if self.world.map[x][y] == MAP_ELEV: self.world.new_level() self.disp.world_draw(self.world) def act(self): - x,y = self.pos + x, y = self.pos running = 0 done = 0 -# self.target = None - - if self.target and (not self.world.flags[self.target[0]][self.target[1]] & FLAG_CREATURE or not self.world.flags[self.target[0]][self.target[1]] & FLAG_VISIBLE or - self.target==self.pos): - self.target=None - if self.target==None: + self.target == self.pos): + self.target = None + if self.target is None: for creat in self.world.creatures: - if self!=creat and self.world.flags[creat.pos[0]][creat.pos[1]] & FLAG_VISIBLE and not creat.burning: + if self != creat and self.world.flags[creat.pos[0]][creat.pos[1]] & FLAG_VISIBLE and not creat.burning: if not self.target or distance(self.pos, creat.pos) < distance(self.pos, self.target): self.target = creat.pos - self.disp.light_draw(self.light) - self.disp.draw_stats(self) - while not done: - done = 1 - cmd = None - for creat in self.world.creatures: - self.disp.effect_draw(creat) - creat.effect = None - self.disp.msg_draw(self.world.msg) - self.disp.select(None) - self.disp.refresh() - cmd, param = self.disp.get_command(animate=1) - for creat in self.world.creatures: - self.disp.creat_draw(creat) - self.disp.select(self.target) - while not cmd: - self.disp.msg_draw(self.world.msg) - self.disp.refresh() - cmd, param = self.disp.get_command() - try: - if cmd == 'quit': - sys.exit() - elif cmd == 'refresh': - done = 0 - elif cmd == 'wait': - self.world.msg.write("Yawn...") - elif cmd == 'loot': - self.act_loot() - elif cmd == 'use': - self.act_use(param) - elif cmd == 'shoot': - self.act_shoot() - elif cmd == 'trash': - self.act_trash(param) - elif cmd == 'aim': - self.act_aim() - done = 0 - elif cmd == 'operate': - self.act_operate() - elif cmd == 'run' and param==None: - done = 0 - running = 1 - self.world.msg.write("Where to run?") - elif cmd=='go': - if running: - running = 0 - self.act_run(param[0], param[1]) - else: - self.act_go(param[0], param[1]) - except ActError: - done = 0 - self.disp.scroll_map(self.pos, self.world) - x,y = self.pos - self.light.cast(x, y) - self.world.msg.clear() + cmd, param = self.command + if cmd == 'quit': + sys.exit() + elif cmd == 'refresh': + done = 0 + raise ActError() + elif cmd == 'wait': + self.world.msg.write("Yawn...") + elif cmd == 'loot': + self.act_loot() + elif cmd == 'use': + self.act_use(param) + elif cmd == 'shoot': + self.act_shoot() + elif cmd == 'trash': + self.act_trash(param) + elif cmd == 'aim': + self.act_aim() + done = 0 + raise ActError() + elif cmd == 'operate': + self.act_operate() + elif cmd == 'run' and param is None: + done = 0 + running = 1 + self.world.msg.write("Where to run?") + raise ActError() + elif cmd == 'go': + if running: + running = 0 + self.act_run(param[0], param[1]) + else: + self.act_go(param[0], param[1]) class Inventory: def __init__(self, world):
--- a/display.py Sun Dec 16 14:55:57 2007 +0100 +++ b/display.py Fri Oct 24 17:20:35 2008 +0200 @@ -6,6 +6,43 @@ from prefs import * from data import * +class CreatureSprite(pygame.sprite.DirtySprite): + def __init__(self, disp, creat): + pygame.sprite.DirtySprite.__init__(self) + self.creat = creat + self.disp = disp + self.frame = 0 + self.frames = self.disp.creatures[1] + self.update() + + def update(self): + if self.creat.dead: + self.kill() + return + if self.creat.burning: + self.frames = self.disp.creatures[2] + if self.frame == 0: + self.frame = 1 + else: + self.frame = 0 + self.image = self.frames[self.frame] + x, y = self.creat.pos + self.rect = pygame.rect.Rect(self.disp.xtile*(x-self.disp.xmap), + self.disp.ytile*(y-self.disp.ymap)+self.disp.msgh, 16, 16) + + +class CursorSprite(pygame.sprite.DirtySprite): + def __init__(self, disp): + self.disp = disp + pygame.sprite.DirtySprite.__init__(self) + self.rect = pygame.rect.Rect(0, 0, 16, 16) + self.image = disp.effects[0][0] + + def move(self, x, y): + self.rect.topleft = (x*self.disp.xtile, y*self.disp.ytile+self.disp.msgh) + + def update(self): + pass class DisplayPygame: def __init__(self): @@ -18,25 +55,39 @@ self.msgh = 32 self.xtile = 16 self.ytile = 16 - self.dirty =[] - self.empty = pygame.Surface((self.xtile,self.ytile)) + self.dirty = [] + self.empty = pygame.Surface((self.xtile, self.ytile)) self.empty.fill((0x0f, 0x0f, 0x0f)) - self.fog = pygame.Surface((self.xtile,self.ytile)) + self.fog = pygame.Surface((self.xtile, self.ytile)) self.fog.fill((0x44, 0x00, 0x44)) self.fog.set_alpha(90, RLEACCEL) - self.cursor = pygame.Surface((self.xtile,self.ytile)) + self.cursor = pygame.Surface((self.xtile, self.ytile)) self.cursor.fill((0x00, 0x66, 0x00)) self.cursor.set_alpha(90, RLEACCEL) - self.screen.fill((0x0f, 0x0f, 0x0f)) + self.buffer = pygame.Surface((self.maxmapx*self.xtile, + self.maxmapy*self.ytile), 0, self.screen) + self.buffer.fill((0x0f, 0x0f, 0x0f)) pygame.display.update() - + self.creatures = self._read_frames("creatures.png") self.effects = self._read_frames("effects.png") self.tiles = self._read_frames("tiles.png") - self.cursor = self.effects[1][0] - + + self.sprites = pygame.sprite.RenderUpdates() + self.cursor_sprite = CursorSprite(self) + + + def add_creatures(self, creatures): + for creat in creatures: + self.sprites.add(CreatureSprite(self, creat)) + + def add_hero(self, hero): + hero_sprite = CreatureSprite(self, hero) + hero_sprite.frames = self.creatures[0] + self.sprites.add(hero_sprite) + def _read_frames(self, filename, size=16): - '''Read an image and split it into tiles.''' + """Read an image and split it into tiles.""" image = pygame.image.load(filename).convert() w, h = image.get_size() @@ -61,10 +112,10 @@ ax, ay = x - self.xmap, y - self.ymap if (ax<0) or (ax>=self.maxmapx) or (ay<0) or (ay>=self.maxmapy): return - r = Rect(self.xtile*ax, self.msgh+self.ytile*ay, self.xtile, self.ytile) + r = Rect(self.xtile*ax, self.ytile*ay, self.xtile, self.ytile) if clear: self.screen.fill((0x00, 0x00, 0x00), r) - self.screen.blit(img, r) + self.buffer.blit(img, r) self.dirty.append(r) def tile_draw(self, pos, world): @@ -89,7 +140,7 @@ def world_draw(self, world): r =Rect(0, self.msgh, self.xtile*self.maxmapx, self.ytile*self.maxmapy) self.dirty.append(r) - self.screen.fill((0x00, 0x00, 0x00), Rect(0, self.msgh, self.xtile*self.maxmapx, self.ytile*self.maxmapy)) + self.buffer.fill((0x00, 0x00, 0x00)) for x in range(world.width): for y in range(world.height): self.tile_draw((x, y), world) @@ -120,6 +171,7 @@ self.dirty.append(r) def refresh(self): + self.screen.blit(self.buffer, (0, self.msgh)) pygame.display.update(self.dirty) self.dirty = [] @@ -181,9 +233,12 @@ def select(self, pos): if not pos: +# self.cursor_sprite.kill() return x, y = pos - self._blit_map(x, y, self.cursor, False) + #self._blit_map(x, y, self.cursor, False) + self.cursor_sprite.move(x, y) + self.sprites.add(self.cursor_sprite) def get_command(self, animate=0): shift = 0 @@ -208,3 +263,8 @@ def effect_draw(self, creat): pass + + def clear_func(self, screen, rect): + source = rect.move(0, -self.msgh) + screen.blit(self.buffer, rect, source) +
--- a/world.py Sun Dec 16 14:55:57 2007 +0100 +++ b/world.py Fri Oct 24 17:20:35 2008 +0200 @@ -35,7 +35,8 @@ """Hold all the information about the current state of the game, the map and the creatures.""" - def __init__(self): + def __init__(self, disp): + self.disp = disp self.width, self.height = 64, 64 self.hero = None self.msg = Mesg() @@ -70,10 +71,7 @@ self.erode() else: self.final() - if self.hero: - self.creatures = [self.hero] - else: - self.creatures = [] + self.creatures = [] self.populate() def find_creature(self, pos): @@ -174,7 +172,7 @@ self.add_tile((x, y), self.named_tile("up")) self.flags[x][y] |= FLAG_CREATURE for i in xrange(random.randrange(50+5*self.level, 90+20*self.level)): - Zombie(self) + self.creatures.append(Zombie(self)) def put_doors(self, pos1, pos2, tile):
--- a/zday.py Sun Dec 16 14:55:57 2007 +0100 +++ b/zday.py Fri Oct 24 17:20:35 2008 +0200 @@ -18,17 +18,58 @@ from display import DisplayPygame from world import World -from creatures import Hero +from creatures import Hero, ActError + +from prefs import command_keys + +import pygame def main(): disp = DisplayPygame() - world = World() + world = World(disp) world.hero = Hero(world, disp) disp.world_draw(world) - while 1: + disp.add_creatures(world.creatures) + disp.add_hero(world.hero) + clock = pygame.time.Clock() + while not world.hero.dead: for creat in world.creatures: creat.metabolism() if not creat.dead: creat.act() + world.msg.clear() + disp.light_draw(world.hero.light) + disp.draw_stats(world.hero) + done = False + while not done: + done = True + cmd = None + disp.msg_draw(world.msg) + disp.refresh() + disp.select(world.hero.target) + while cmd is None: + disp.sprites.clear(disp.screen, disp.clear_func) + disp.sprites.update() + pygame.display.update(disp.sprites.draw(disp.screen)) + clock.tick(4) + for event in pygame.event.get(): + if event.type == pygame.QUIT: + world.hero.dead = True + elif event.type == pygame.locals.KEYDOWN: + name = pygame.key.name(event.key) + if len(name) == 1: + mods = event.mod + if mods & pygame.locals.KMOD_LSHIFT or mods & pygame.locals.KMOD_RSHIFT: + name = chr(ord(name)-32) # XXX A hack for uppercase + cmd, param = command_keys.get(name, (None, None)) + world.hero.command = cmd, param + try: + world.hero.act() + except ActError: + done = False + disp.scroll_map(world.hero.pos, world) + world.hero.light.cast(world.hero.pos[0], world.hero.pos[1]) + + main()
