changeset 16:4223254474e1

Add some docstrings.
author sheep@ghostwheel
date Sun, 05 Jul 2009 23:19:43 +0200
parents d8731b40e57e
children 31c17b907fad
files level.map qq.py
diffstat 2 files changed, 101 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/level.map	Thu Aug 28 14:07:12 2008 +0200
+++ b/level.map	Sun Jul 05 23:19:43 2009 +0200
@@ -18,41 +18,37 @@
 
 [#]
 name = wall
-tile = 0, 0
-pass = false
 wall = true
+block = true
 
 [.]
 name = floor
-pass = true
 tile = 0, 3
 
 [@]
 name = player
-pass = true
 tile = 0, 3
 player = true
 sprite = player.png
 
 [s]
 name = skeleton
-pass = false
 tile = 0, 3
 sprite = skeleton.png
+block = true
 
 [>]
 name = stairs
-pass = true
 tile = 3, 3
 
 [b]
 name = crate
-pass = false
 tile = 0, 3
 sprite = crate.png
+block = true
 
 [h]
 name = house
 tile = 0, 3
-pass = false
 sprite = house.png
+block = true
--- a/qq.py	Thu Aug 28 14:07:12 2008 +0200
+++ b/qq.py	Sun Jul 05 23:19:43 2009 +0200
@@ -14,6 +14,8 @@
 
 
 class TileCache:
+    """Load the tilesets lazily."""
+
     def __init__(self):
         self.cache = {}
 
@@ -38,13 +40,19 @@
         return tiles
 
 class SortedUpdates(pygame.sprite.RenderUpdates):
+    """A sprite group that sorts them by depth."""
+
     def sprites(self):
+        """The list of sprites in the group."""
+
         sprites = self.spritedict.keys()
         sprites.sort(lambda a, b: a.depth - b.depth)
         return sprites
 
 
 class Shadow(pygame.sprite.Sprite):
+    """Sprite for shadows."""
+
     def __init__(self, sprite):
         self.image = tiles("shadow.png", 24, 24)[0][0]
         self.image.set_alpha(64)
@@ -53,10 +61,14 @@
         self.sprite = sprite
 
     def update(self):
+        """Move the shadow to the right place."""
+
         self.rect.midbottom = self.sprite.rect.midbottom
 
 
 class Sprite(pygame.sprite.Sprite):
+    """Sprite for animated items and base class for Player."""
+
     is_player = False
 
     def __init__(self, pos=(0, 0), frames=None):
@@ -69,17 +81,27 @@
         self.pos = pos
 
     def _get_pos(self):
+        """Check the current position of the sprite on the map."""
+
         return (self.rect.midbottom[0]-12)/24, (self.rect.midbottom[1]-16)/16
+
     def _set_pos(self, pos):
+        """Set the position of the sprite on the map."""
+
         self.rect.midbottom = pos[0]*24+12, pos[1]*16+16
         self.depth = self.rect.midbottom[1]
+
     pos = property(_get_pos, _set_pos)
 
     def move(self, dx, dy):
+        """Change the position of the sprite on screen."""
+
         self.rect.move_ip(dx, dy)
         self.depth = self.rect.midbottom[1]
 
     def stand_animation(self):
+        """The default animation."""
+
         while True:
             for frame in self.frames[0]:
                 self.image = frame
@@ -87,11 +109,14 @@
                 yield None
 
     def update(self):
+        """Run the current animation."""
+
         self.animation.next()
 
 
 class Player(Sprite):
     """ Display and animate the player character."""
+
     is_player = True
 
     def __init__(self, pos=(1, 1)):
@@ -104,6 +129,8 @@
         self.rect.move_ip((0, 1))
 
     def walk_animation(self):
+        """Animation for the player walking."""
+
         for frame in range(4):
             self.image = self.frames[self.direction][frame]
             yield None
@@ -112,6 +139,8 @@
             self.move(3*DX[self.direction], 2*DY[self.direction])
 
     def update(self):
+        """Run the current animation or just stand there if no animation set."""
+
         if self.animation is None:
             self.image = self.frames[self.direction][0]
         else:
@@ -123,8 +152,13 @@
 
 class Level:
     """ Load and store the map of the level, together with all the items."""
+
     def __init__(self, filename="level.map"):
+        self.load_file(filename)
+
+    def load_file(self, filename="level.map"):
         """ Load the level from specified file."""
+
         parser = ConfigParser.ConfigParser()
         parser.read(filename)
         self.items = {}
@@ -136,16 +170,17 @@
                 self.key[section] = dict(parser.items(section))
         tile_width, tile_height = 24, 16
         self.tiles = tiles(parser.get("level", "tileset"),
-                                tile_width, tile_height)
-        width = len(self.map[0])
-        height = len(self.map)
-        self.image = pygame.Surface((width*tile_width, height*tile_height))
+                           tile_width, tile_height)
+        self.width = len(self.map[0])
+        self.height = len(self.map)
+        self.image = pygame.Surface((self.width*tile_width,
+                                     self.height*tile_height))
         self.overlays = {}
         y = 0
         for line in self.map:
             x = 0
             for c in line:
-                if not self.key[c].get('wall', None):
+                if not self.is_wall(x, y):
                     # floor
                     if 'sprite' in self.key[c]:
                         self.items[(x, y)] = self.key[c]
@@ -159,47 +194,71 @@
                                     (x*tile_width, y*tile_height))
                 else:
                     # wall
-                    if self(x, y+1):
-                        if self(x+1, y) and self(x-1, y):
-                            tile_image = self.tiles[3][2]
-                        elif self(x+1, y):
-                            tile_image = self.tiles[2][2]
-                        elif self(x-1, y):
+                    if not self.is_wall(x, y+1):
+                        if self.is_wall(x+1, y) and self.is_wall(x-1, y):
+                            tile_image = self.tiles[1][2]
+                        elif self.is_wall(x+1, y):
                             tile_image = self.tiles[0][2]
+                        elif self.is_wall(x-1, y):
+                            tile_image = self.tiles[2][2]
                         else:
-                            tile_image = self.tiles[1][2]
+                            tile_image = self.tiles[3][2]
                     else:
-                        if self(x+1, y+1) and self(x-1, y+1):
-                            tile_image = self.tiles[3][1]
-                        elif self(x+1, y+1):
+                        if self.is_wall(x+1, y+1) and self.is_wall(x-1, y+1):
+                            tile_image = self.tiles[1][1]
+                        elif self.is_wall(x+1, y+1):
+                            tile_image = self.tiles[0][1]
+                        elif self.is_wall(x-1, y+1):
                             tile_image = self.tiles[2][1]
-                        elif self(x-1, y+1):
-                            tile_image = self.tiles[0][1]
                         else:
-                            tile_image = self.tiles[1][1]
+                            tile_image = self.tiles[3][1]
                     self.image.blit(tile_image, (x*tile_width, y*tile_height))
-                    if self(x, y-1):
-                        if self(x+1, y) and self(x-1, y):
-                            overlay_image = self.tiles[3][0]
-                        elif self(x+1, y):
+                    if not self.is_wall(x, y-1):
+                        if self.is_wall(x+1, y) and self.is_wall(x-1, y):
+                            overlay_image = self.tiles[1][0]
+                        elif self.is_wall(x+1, y):
+                            overlay_image = self.tiles[0][0]
+                        elif self.is_wall(x-1, y):
                             overlay_image = self.tiles[2][0]
-                        elif self(x-1, y):
-                            overlay_image = self.tiles[0][0]
                         else:
-                            overlay_image = self.tiles[1][0]
+                            overlay_image = self.tiles[3][0]
                         self.overlays[(x, y)] = overlay_image
                 x += 1
             y += 1
 
-    def __call__(self, x, y):
-        """ Tell what is at this position on the map."""
+    def get_tile(self, x, y):
+        """Tell what's at the specified position of the map."""
+
+        try:
+            char = self.map[y][x]
+        except IndexError:
+            return {}
         try:
-            return self.key[self.map[y][x]]['pass'] in ('true', 'yes', 'True', 'Yes', '1', 'on', 'On')
-        except (IndexError, AttributeError):
-            return None
+            return self.key[char]
+        except KeyError:
+            return {}
+
+    def get_bool(self, x, y, name):
+        """Tell if the specified flag is set for position on the map."""
+
+        value = self.get_tile(x, y).get(name)
+        return value in ('true', 'yes', 'True', 'Yes', '1', 'on', 'On')
+
+    def is_wall(self, x, y):
+        """Is there a wall?"""
+
+        return self.get_bool(x, y, 'wall')
+
+    def is_blocking(self, x, y):
+        """Is this place blocking movement?"""
+
+        if not 0 <= x < self.width or not 0 <= y < self.height:
+            return True
+        return self.get_bool(x, y, 'block')
 
     def draw(self, surface):
         """ Draw the map on the provided surface."""
+
         surface.blit(self.image, (0, 0))
 
 
@@ -211,6 +270,8 @@
         self.use_level(Level())
 
     def use_level(self, level):
+        """Set the level as the current one."""
+
         self.shadows = pygame.sprite.RenderUpdates()
         self.sprites = SortedUpdates()
         self.overlays = pygame.sprite.RenderUpdates()
@@ -231,13 +292,15 @@
         self.background = self.level.image.copy()
 
     def control(self):
+        """Handle the controls of the game."""
+
         keys = pygame.key.get_pressed()
         def pressed(key):
             return self.pressed_key == key or keys[key]
         def walk(d):
             x, y = self.player.pos
             self.player.direction = d
-            if self.level(x+DX[d], y+DY[d]):
+            if not self.level.is_blocking(x+DX[d], y+DY[d]):
                 self.player.animation = self.player.walk_animation()
         if pressed(K_UP):
             walk(0)
@@ -250,6 +313,8 @@
         self.pressed_key = None
 
     def main(self):
+        """Run the main loop."""
+
         clock = pygame.time.Clock()
         self.screen.blit(self.background, (0, 0))
         self.overlays.draw(self.screen)
@@ -280,7 +345,7 @@
 
 if __name__ == "__main__":
     pygame.init()
-    pygame.display.set_mode((424, 400))
+    pygame.display.set_mode((424, 320))
     font = pygame.font.Font("MgOpenModataBold.ttf", 11)
     tiles = TileCache()
     Game().main()