changeset 4:25d8760afb12

Added scrolling, refactored animation
author Radomir Dopieralski <moindev@sheep.art.pl>
date Sun, 16 Dec 2007 20:37:54 +0100
parents e496526e2432
children 6bfd708ce750
files avatar.py brain.png game.py jello.png level.py map.txt mesg.py monster.py skeleton.png util.py
diffstat 10 files changed, 95 insertions(+), 121 deletions(-) [+]
line wrap: on
line diff
--- a/avatar.py	Sun Dec 16 00:06:04 2007 +0100
+++ b/avatar.py	Sun Dec 16 20:37:54 2007 +0100
@@ -1,42 +1,33 @@
 import pygame
 from pygame.locals import *
 
+from monster import Monster
 from util import *
 
-class Avatar(pygame.sprite.Sprite):
+class Avatar(Monster):
 
     def __init__(self, x=0, y=0, image_file="abi2.png"):
         '''Create the avatar. Each one is likely to have different graphics.'''
-
-        pygame.sprite.Sprite.__init__(self)
-        # The starting values
-        self.x = x
-        self.y = y
-        self.z = y*16-12
-        self.rect = Rect(self.x*24, self.z, 24, 24)
-        self.frame = 0
         self.facing = 0
-        self.frames = read_frames(image_file, 24)
-        self.image = self.frames[0][2]
-   
+        self.step = 0
+        Monster.__init__(self, x, y, image_file)
+      
     def update(self):
-        '''Actually animate the avatar'''
-
-        if self.facing:
-            self.image = self.frames[self.frame/2][self.facing-1]
-            self.z = self.y*16-12+self.frame*delta_y[self.facing]*2-delta_y[self.facing]*16
-            x = self.x*24+self.frame*delta_x[self.facing]*3-delta_x[self.facing]*24
-            self.rect = Rect(x, self.z, 24, 24)
-            self.frame += 1
-            if self.frame>=len(self.frames)*2:
-                self.frame = 0
-                self.facing = 0
+        if self.step>0:
+            self.rect.move_ip(delta_x[self.facing]*3, delta_y[self.facing]*2)
+            self.z += delta_y[self.facing]*2
+            self.step -= 1
         else:
-            self.image = self.frames[0][2]
-            self.z = self.y*16-12
-            self.rect = Rect(self.x*24, self.z, 24, 24)
+            self.facing = 3
+            self.step = 0
+            self.frame = 0
+#            self.z = self.y*16-12
+#            self.rect.topleft = (self.x*24, self.z)
+        self.anim = self.frames[self.facing-1]
+        self.animate(1)
 
     def walk(self, direction):
         self.facing = direction
+        self.step = 8
         self.x += delta_x[self.facing]
         self.y += delta_y[self.facing]
Binary file brain.png has changed
--- a/game.py	Sun Dec 16 00:06:04 2007 +0100
+++ b/game.py	Sun Dec 16 20:37:54 2007 +0100
@@ -9,11 +9,11 @@
     def __init__(self):
         # Init
         pygame.init()
-        self.screen = pygame.display.set_mode((480, 320))
+        self.screen = pygame.display.set_mode((480, 480))
         self.clock = pygame.time.Clock()
 
         # Prapare the map 
-        self.level = Level(self.screen, 'map.txt')
+        self.level = Level('map.txt')
 
     def main_loop(self):
         self.level.refresh(self.screen)
@@ -29,22 +29,23 @@
                     return
                 elif event.type==KEYDOWN:
                     key_pressed = event.key
-            if av.frame==0:
+            if av.step==0:
                 keys = pygame.key.get_pressed()
                 if ((keys[K_UP] or key_pressed==K_UP) and 
-                    not self.level.is_blocked(av.x, av.y-1)):
+                    not self.level.map.is_blocked(av.x, av.y-1)):
                     av.walk(1)
                 elif ((keys[K_DOWN] or key_pressed==K_DOWN) and
-                    not self.level.is_blocked(av.x, av.y+1)):
+                    not self.level.map.is_blocked(av.x, av.y+1)):
                     av.walk(3)
                 elif ((keys[K_LEFT] or key_pressed==K_LEFT) and
-                    not self.level.is_blocked(av.x-1, av.y)):
+                    not self.level.map.is_blocked(av.x-1, av.y)):
                     av.walk(4)
                 elif ((keys[K_RIGHT] or key_pressed==K_RIGHT) and
-                    not self.level.is_blocked(av.x+1, av.y)):
+                    not self.level.map.is_blocked(av.x+1, av.y)):
                     av.walk(2)
                 elif key_pressed==K_SPACE:
-                    self.level.animations.add(Mesg(av.x, av.y))
+                    self.level.scroll(10, 10)
+                    self.level.refresh(self.screen)
                 elif key_pressed==K_ESCAPE:
                     return
                 key_pressed = None
Binary file jello.png has changed
--- a/level.py	Sun Dec 16 00:06:04 2007 +0100
+++ b/level.py	Sun Dec 16 20:37:54 2007 +0100
@@ -1,5 +1,3 @@
-import re
-
 import pygame
 from pygame.locals import *
 
@@ -7,85 +5,75 @@
 from avatar import Avatar
 from cache import Cache
 from util import *
-
+from sprites import SortedUpdates
+from map import Map
 
 class MapFileError:
     pass
 
 class Level:
-    def __init__(self, screen, filename):
+    def __init__(self, filename):
         self.animations = SortedUpdates()
-        self.avatar = Avatar(0, 0)
-        self.background = pygame.Surface(screen.get_size())
-        self.read_map(filename)
+        self.scrollpos = [-48,-32]
+        self.map = Map(filename)
         self.cache = Cache()
-        self.create_map()
+        self.background = self.create_map(self.map)
+
     
-    def create_map(self):
+    def create_map(self, m):
         '''Create background and animations.'''
-
-        self.background.fill( (0, 0, 0) )
+        
+        background = pygame.Surface((self.map.w*24+96, self.map.h*16+64))
+        background.fill( (0, 0, 0) )
         x =0
         y =0
-        for line in self.map:
+        for line in m:
             for tile in line:
-                urls = self.map_key[tile]
+                urls = m.map_key[tile]
                 if urls:
                     image = self.cache.get_image(urls[0])
                     if image:
-                        self.background.blit(image , (x*24, y*16))
+                        background.blit(image , (x*24+48, y*16+32))
                     for url in urls[1:]:
                         if url=='joe.png':
                             self.player = Avatar(x, y)
-                            self.animations.add(self.player)
+                            self.add_sprite(self.player)
                         else:
-                            self.animations.add(Monster(x, y, url))
+                            self.add_sprite(Monster(x, y, url))
                 x += 1
             x = 0
             y += 1
-
-    def read_map(self, filename):
-        '''Read the map from a file.'''
+        return background
+    
+    def add_sprite(self, sprite):
+        self.animations.add(sprite)
+        sprite.rect.move_ip(self.scrollpos[0], self.scrollpos[1])
 
-        self.map = []
-        self.blocking = []
-        self.map_key = {}
-        for line in file(filename).readlines():
-            m = re.match('^(?P<key>.)\s+<(?P<urls>.*)>\s*$', line)
-            if m:
-                urls = re.split('>\s*<', m.group('urls'))
-                self.map_key[m.group('key')] = urls
-            elif re.match('^\s*$', line):
-                pass # Ignore empty lines
-            else:
-                map_line = []
-                block_line = []
-                for char in line:
-                    if char in self.map_key:
-                        map_line.append(char)
-                        if char=='X':
-                            block_line.append(True)
-                        else:
-                            block_line.append(False)
-                self.map.append(map_line)
-                self.blocking.append(block_line)
-
-    def is_blocked(self, x, y):
-        try:
-            return self.blocking[y][x]
-        except:
-            return True
+    def scroll(self, dx, dy):
+        self.scrollpos[0] += dx
+        self.scrollpos[1] += dy
+        for sprite in self.animations:
+            sprite.rect.move_ip(dx, dy)
 
     def refresh(self, screen):
         '''Redraw the whole level'''
 
-        screen.blit(self.background, (0, 0) )
+        screen.blit(self.background, self.scrollpos)
+        self.animations.draw(screen)
+
         pygame.display.update()
 
+
+    def clear_func(self, screen, rect):
+        source = rect.move(-self.scrollpos[0], -self.scrollpos[1])
+        source = source.clip(self.background.get_clip())
+        patch = self.background.subsurface(source)
+        screen.blit(patch, rect)
+
     def update(self, screen):
         '''Redraw and update all the animated parts'''
 
-        self.animations.clear(screen, self.background)
+        self.animations.clear(screen, self.clear_func)
         self.animations.update()
         dirty = self.animations.draw(screen)
         pygame.display.update(dirty)
--- a/map.txt	Sun Dec 16 00:06:04 2007 +0100
+++ b/map.txt	Sun Dec 16 20:37:54 2007 +0100
@@ -5,6 +5,7 @@
 M <floor.png> <jello.png>
 S <floor.png> <skeleton.png>
 B <floor.png> <brain.png>
+Z <floor.png> <zombie.png>
 & <floor.png> <box.png>
 @ <floor.png> <joe.png>
 
@@ -15,7 +16,7 @@
 XXX.XXXXX.XXXXXX.XXX
 XXX.XXX::::::XXX.XXX
 XXX.XXX::::::XXX.XXX
-XXX....::::::XXX.XXX
+XXX....::::Z:XXX.XXX
 XXX.XXX::::::X:::::X
 XXX.XXX@:::::X:::::X
 XXX.XXXXXX.XXX::M::X
--- a/mesg.py	Sun Dec 16 00:06:04 2007 +0100
+++ b/mesg.py	Sun Dec 16 20:37:54 2007 +0100
@@ -8,29 +8,28 @@
 from util import *
 
 
-
 class Mesg(pygame.sprite.Sprite):
     """Messages float up and disappear."""
     
-    def __init__(self, x=0, y=0, text="Hello!"):
+    def __init__(self, x=0, y=0, text="Hello!", color=(255, 255, 255)):
         pygame.sprite.Sprite.__init__(self)
         self.x = x
         self.y = y
-        self.z = y*16-11
-        self.h = 0
+        self.z = y*16-8
         self.dh = 8
-        self.rect = Rect(self.x*24, self.y*16-8-self.h, 24, 24)
-        self.image = font.render(text, True, (255,255,255)).convert_alpha()
+        self.image = font.render(text, True, color).convert_alpha()
+        self.rect = Rect(0,0, self.image.get_width(), self.image.get_height())
+        self.rect.center = (self.x*24+12+48, self.y*16-8+32)
 
     def update(self):
-        self.h += self.dh
+        if self.dh is None:
+            self.kill()
+            return
         self.dh -= 1
-        self.rect = Rect(self.x*24, self.y*16-8-self.h, 24, 24)
-        if self.dh==0:
-            self.kill()
+        self.rect.move_ip(0, -self.dh)
         if self.dh<-2:
-            self.dh = 0
+            self.dh = None
 
 
 pygame.font.init()
-font = pygame.font.SysFont("Sans", 12, bold=True)
+font = pygame.font.SysFont("Sans", 15, bold=True)
--- a/monster.py	Sun Dec 16 00:06:04 2007 +0100
+++ b/monster.py	Sun Dec 16 20:37:54 2007 +0100
@@ -13,20 +13,22 @@
         self.x = x
         self.y = y
         self.z = y*16-12
-        self.rect = Rect(self.x*24, self.y*16-12, 24, 24)
+        self.rect = Rect(self.x*24+48, self.z+32, 24, 24)
         self.frames = read_frames(image_file)
-        self.image = self.frames[0][0]
+        self.anim = self.frames[0]
+        self.update()
+        
+    def animate(self, delay=0):
+        '''Change the frame of animation'''
+        
+        if self.delay>=delay:
+            self.delay = 0
+            self.frame += 1
+            if self.frame>=len(self.anim):
+                self.frame = 0
+        else:
+            self.delay += 1
+            self.image = self.anim[self.frame]
 
     def update(self):
-        '''Change the frame of animation'''
-
-        self.image = self.frames[0][self.frame]
-        # Ok, this ain't nice :)
-        if self.delay>=3:
-            self.frame += 1
-            if self.frame>=len(self.frames[0]):
-                self.frame = 0
-            self.delay = 0
-        else:
-            self.delay += 1
-
+        self.animate(3)
Binary file skeleton.png has changed
--- a/util.py	Sun Dec 16 00:06:04 2007 +0100
+++ b/util.py	Sun Dec 16 20:37:54 2007 +0100
@@ -17,16 +17,8 @@
     image = pygame.image.load(filename).convert()
     w, h = image.get_size()
     frames = []
-    for y in range(0, h/size):
+    for x in range(0, w/size):
         frames.append([])
-        for x in range(0, w/size):
-            frames[y].append(image.subsurface((x*size, y*size, size, size)))
+        for y in range(0, h/size):
+            frames[x].append(image.subsurface((x*size, y*size, size, size)))
     return frames
-
-
-class SortedUpdates(pygame.sprite.RenderUpdates):
-    def z_compare(self, a, b): return a.z-b.z
-    def sprites(self):
-        l = self.spritedict.keys()
-        l.sort(self.z_compare)
-        return l