changeset 17:e768ce31a8d3

Spawning animations, animation queue
author Radomir Dopieralski <sheep-devel@sheep.art.pl>
date Thu, 15 Mar 2012 10:32:37 +0100
parents e5e4eb7b9443
children 03aeafa63f0b
files jelly/__init__.py jelly/display.py jelly/jelly.png jelly/level.py jelly/mobs.py jelly/rooms_level.py jelly/sprites.py
diffstat 7 files changed, 96 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/jelly/__init__.py	Thu Mar 15 09:06:48 2012 +0100
+++ b/jelly/__init__.py	Thu Mar 15 10:32:37 2012 +0100
@@ -31,21 +31,17 @@
                         event.key == pg.K_ESCAPE):
                     self.game_over = True
             try:
-                pc_animation = self.display.mob_sprites[id(self.pc)].animation
+                pc_animation = self.display.mob_sprites[id(self.pc)].animations
             except KeyError:
                 pc_animation = None
                 self.display.events(self.level.events)
                 self.level.events = []
-            if pc_animation is None:
+            if not pc_animation:
                 if self.pc.control(self.level):
-                    for mob in self.level.mobs:
+                    for mob in list(self.level.mobs):
                         if mob == self.pc:
                             continue
                         mob.control(self.level)
-                else:
-                    for mob in self.level.mobs:
-                        if mob == self.pc:
-                            continue
                 self.display.events(self.level.events)
                 self.level.events = []
 
--- a/jelly/display.py	Thu Mar 15 09:06:48 2012 +0100
+++ b/jelly/display.py	Thu Mar 15 10:32:37 2012 +0100
@@ -159,14 +159,17 @@
         sprite.set_animation(sprite.attack_animation(direction))
 
     def on_mob_death(self, mob):
-        sprite = self.mob_sprites[id(mob)]
+        try:
+            sprite = self.mob_sprites[id(mob)]
+        except KeyError:
+            return
         sprite.set_animation(sprite.death_animation())
 
     def on_mob_open(self, mob):
         sprite = self.mob_sprites[id(mob)]
         sprite.set_animation(sprite.open_animation())
 
-    def on_mob_create(self, mob):
+    def on_mob_spawn(self, mob, spawner):
         sprite = mob.Sprite(self.tiles, mob.pos, mob.animation)
         self.sprites.add(sprite)
         self.mob_sprites[id(mob)] = sprite
@@ -176,6 +179,10 @@
             light = sprites.Vision(sprite, 64)
             self.lights.add(light)
             self.mob_lights[id(mob)] = light
+        if spawner is not None:
+            sprite = self.mob_sprites[id(spawner)]
+            sprite.set_animation(sprite.spawner_animation())
+
 
 
 def load_tiles(filename, width, height):
Binary file jelly/jelly.png has changed
--- a/jelly/level.py	Thu Mar 15 09:06:48 2012 +0100
+++ b/jelly/level.py	Thu Mar 15 10:32:37 2012 +0100
@@ -57,9 +57,9 @@
         self.events.append(('mob_walk', mob, direction))
         self.events.append(('mob_dust', mob, 1, -4))
 
-    def create(self, mob):
+    def spawn(self, mob, spawner=None):
         self.mobs.append(mob)
-        self.events.append(('mob_create', mob))
+        self.events.append(('mob_spawn', mob, spawner))
 
     def kill(self, mob):
         self.mobs.remove(mob)
--- a/jelly/mobs.py	Thu Mar 15 09:06:48 2012 +0100
+++ b/jelly/mobs.py	Thu Mar 15 10:32:37 2012 +0100
@@ -19,6 +19,16 @@
 }
 
 
+def one_in(prob):
+    def decorator(func):
+        def wrapped(*args, **kwargs):
+            if random.randint(0, prob) != 0:
+                return False
+            return func(*args, **kwargs)
+        return wrapped
+    return decorator
+
+
 def sleep_behavior(mob, level):
     if mob.status.get('asleep', True):
         return True
@@ -62,6 +72,20 @@
     return False
 
 
+def spawn_behavior(mob, level):
+    x, y = mob.pos
+    possible = [d for d in [0, 2, 4, 6, 1, 3, 5, 7]
+                if not level.is_blocked((x + DX[d], y + DY[d]))]
+    if not possible:
+        return False
+    direction = random.choice(possible)
+    MobClass = random.choice([BlueJelly, PurpleJelly, PinkJelly, RedJelly])
+    pos = (x + DX[direction], y + DY[direction])
+    spawnee = MobClass(pos)
+    level.spawn(spawnee, mob)
+    return True
+
+
 def coward_behavior(mob, level):
     x, y = mob.pos
     def coward_fitness(choices):
@@ -116,29 +140,29 @@
 class PurpleJelly(Mob):
     name = 'purple jelly'
     color = 1
-    animation = [46, 46, 47, 47, 47, 47]
+    animation = [46, 46, 46, 47, 47, 47, 47]
     behaviors = [attack_behavior, sleep_behavior, wander_behavior]
 
 
 class RedJelly(Mob):
     name = 'red jelly'
     color = 3
-    animation = [66, 66, 67, 67, 67, 67]
+    animation = [66, 66, 67, 67, 67]
     behaviors = [attack_behavior, aggressive_behavior]
 
 
 class BlueJelly(Mob):
     name = 'blue jelly'
     color = 0
-    animation = [36, 36, 37, 37, 37, 37]
+    animation = [36, 36, 36, 37, 37, 37, 37, 37]
     behaviors = [slow_behavior, attack_behavior, wander_behavior]
 
 
 class BlackJelly(Mob):
     name = 'black jelly'
     color = 4
-    animation = [76, 76, 77, 77, 77, 77]
-    behaviors = [wander_behavior]
+    animation = [76, 76, 76, 77, 77, 77]
+    behaviors = [one_in(5)(spawn_behavior), wander_behavior]
 
 
 class Crate(Mob):
--- a/jelly/rooms_level.py	Thu Mar 15 09:06:48 2012 +0100
+++ b/jelly/rooms_level.py	Thu Mar 15 10:32:37 2012 +0100
@@ -49,15 +49,15 @@
                     mobs.BlackJelly,
                     mobs.Crate,
                 ])
-                self.create(MobClass((r(x, x + w), r(y, y + h))))
+                self.spawn(MobClass((r(x, x + w), r(y, y + h))))
         self[r(x, x+w), r(y, y+h)] = 5
 
         (x, y), (w, h) = random.choice(rooms)
         pc_pos = (r(x, x+w), r(y, y+h))
 
-        self.create(mobs.Ladder(pc_pos))
+        self.spawn(mobs.Ladder(pc_pos))
         self.pc.place(pc_pos)
-        self.create(self.pc)
+        self.spawn(self.pc)
 
         self.rooms = rooms
 
--- a/jelly/sprites.py	Thu Mar 15 09:06:48 2012 +0100
+++ b/jelly/sprites.py	Thu Mar 15 10:32:37 2012 +0100
@@ -45,18 +45,18 @@
         self.image = self.frames[0]
         self.rect = self.image.get_rect()
         self.frame = random.randint(0, len(self.steps))
-        self.rect.move_ip(4 + 20 * x, 12 * y)
+        self.rect.topleft = (4 + 20 * x, 12 * y)
         self.depth = self.rect.bottom
-        self.animation = None
+        self.animations = [self.spawn_animation()]
 
     def update(self):
         self.frame = (self.frame + 1) % len(self.steps)
         self.image = self.frames[self.steps[self.frame]]
-        if self.animation:
+        if self.animations:
             try:
-                self.animation.next()
+                self.animations[0].next()
             except StopIteration:
-                self.animation = None
+                del self.animations[0]
 
     def walk_animation(self, direction):
         for frame in range(4):
@@ -78,6 +78,45 @@
             self.image.set_alpha(192-step*32)
         self.kill()
 
+    def spawn_animation(self):
+        self.rect.move_ip(0, -12)
+        for step in xrange(4):
+            self.image = self.image.copy()
+            self.image.set_alpha(0)
+            yield None
+        for step in xrange(4):
+            self.image = self.image.copy()
+            self.image.set_alpha(step * 48)
+            yield None
+        self.rect.move_ip(0, 2)
+        yield None
+        self.rect.move_ip(0, 4)
+        yield None
+        self.rect.move_ip(0, 6)
+
+
+    def spawner_animation(self):
+        yield None
+        self.rect.move_ip(0, -5)
+        yield None
+        self.rect.move_ip(0, 3)
+        yield None
+        self.rect.move_ip(0, 3)
+        yield None
+        self.rect.move_ip(0, 3)
+        yield None
+        self.rect.move_ip(0, -4)
+        yield None
+        self.rect.move_ip(0, -5)
+        yield None
+        self.rect.move_ip(0, 3)
+        yield None
+        self.rect.move_ip(0, 3)
+        yield None
+        self.rect.move_ip(0, 3)
+        yield None
+        self.rect.move_ip(0, -4)
+
     def open_animation(self):
         self.depth -= 2
         for step in range(2):
@@ -112,11 +151,8 @@
         self.depth = self.rect.bottom
 
     def set_animation(self, animation):
-        self.animation = animation
-        try:
-            self.animation.next()
-        except StopIteration:
-            self.animation = None
+        self.animations.append(animation)
+        self.update()
 
 
 class PlayerSprite(MobSprite):
@@ -125,18 +161,18 @@
         self.direction = 0
         self.frames = frames
         self.image = self.frames[0]
-        self.animation = self.stand_animation(self.direction)
+        self.animations = [self.stand_animation(self.direction)]
         self.rect = self.image.get_rect()
         self.rect.move_ip(4 + 20 * x, 12 * y)
         self.depth = self.rect.bottom
         self.frame = 0
 
     def update(self):
-        if self.animation:
+        if self.animations:
             try:
-                self.animation.next()
+                self.animations[0].next()
             except StopIteration:
-                self.animation = None
+                del self.animations[0]
 
     def walk_animation(self, direction):
         frames = [