Mercurial > dw
changeset 1:c8a7aa8fadbb
Initial import
| author | Radomir Dopieralski <moindev@sheep.art.pl> |
|---|---|
| date | Sat, 15 Dec 2007 23:16:54 +0100 |
| parents | 8076aec96236 |
| children | 36b63652966f |
| files | abi2.png avatar.py box.png brain.png cache.py corridor.png floor.png game.py jello.png joe.png level.py main.py map.txt monster.py readme.txt skeleton.png stairs.png util.py |
| diffstat | 18 files changed, 351 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/avatar.py Sat Dec 15 23:16:54 2007 +0100 @@ -0,0 +1,42 @@ +import pygame +from pygame.locals import * + +from util import * + +class Avatar(pygame.sprite.Sprite): + + 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] + + 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 + else: + self.image = self.frames[0][2] + self.z = self.y*16-12 + self.rect = Rect(self.x*24, self.z, 24, 24) + + def walk(self, direction): + self.facing = direction + self.x += delta_x[self.facing] + self.y += delta_y[self.facing]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cache.py Sat Dec 15 23:16:54 2007 +0100 @@ -0,0 +1,21 @@ +import pygame +from pygame.locals import * + +class Cache: + def __init__(self): + self.images = {} + + def get_image(self, filename=None): + '''Return an image from specified file.''' + + if not filename in self.images: + try: + self.images[filename] = pygame.image.load(filename).convert() + except: + return None + return self.images[filename] + + def get_object(self, url): + '''Return an object identified by specified url''' + + return None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/game.py Sat Dec 15 23:16:54 2007 +0100 @@ -0,0 +1,48 @@ +import pygame +from pygame.locals import * + +from level import Level +from avatar import Avatar + +class Game: + def __init__(self): + # Init + pygame.init() + self.screen = pygame.display.set_mode((480, 320)) + self.clock = pygame.time.Clock() + + # Prapare the map + self.level = Level(self.screen, 'map.txt') + + def main_loop(self): + self.level.refresh(self.screen) + av = self.level.player + key_pressed = None + while 1: + # Update the screen + self.level.update(self.screen) + self.clock.tick(15) + # Process input + for event in pygame.event.get(): + if event.type==QUIT: + return + elif event.type==KEYDOWN: + key_pressed = event.key + if av.frame==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)): + av.walk(1) + elif ((keys[K_DOWN] or key_pressed==K_DOWN) and + not self.level.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)): + av.walk(4) + elif ((keys[K_RIGHT] or key_pressed==K_RIGHT) and + not self.level.is_blocked(av.x+1, av.y)): + av.walk(2) + elif key_pressed == K_ESCAPE: + return + key_pressed = None +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level.py Sat Dec 15 23:16:54 2007 +0100 @@ -0,0 +1,90 @@ +import re + +import pygame +from pygame.locals import * + +from monster import Monster +from avatar import Avatar +from cache import Cache +from util import * + +class MapFileError: + pass + +class Level: + def __init__(self, screen, filename): + self.animations = SortedUpdates() + self.avatar = Avatar(0, 0) + self.background = pygame.Surface(screen.get_size()) + self.read_map(filename) + self.cache = Cache() + self.create_map() + + def create_map(self): + '''Create background and animations.''' + + self.background.fill( (0, 0, 0) ) + x =0 + y =0 + for line in self.map: + for tile in line: + urls = self.map_key[tile] + if urls: + image = self.cache.get_image(urls[0]) + if image: + self.background.blit(image , (x*24, y*16)) + for url in urls[1:]: + if url=='joe.png': + self.player = Avatar(x, y) + self.animations.add(self.player) + else: + self.animations.add(Monster(x, y, url)) + x += 1 + x = 0 + y += 1 + + def read_map(self, filename): + '''Read the map from a file.''' + + 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 refresh(self, screen): + '''Redraw the whole level''' + + screen.blit(self.background, (0, 0) ) + pygame.display.update() + + def update(self, screen): + '''Redraw and update all the animated parts''' + + self.animations.clear(screen, self.background) + self.animations.update() + dirty = self.animations.draw(screen) + pygame.display.update(dirty)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.py Sat Dec 15 23:16:54 2007 +0100 @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +''' +Summary: +-------- + This is a mockup test for some animated sprites. + The map is read from the file "map.txt", the graphics + is taken from attached image files. The rest is + hardcoded in the program. + + This is a python program, it requires the python + interpreter (available at http://python.org) and + the PyGame python library (available at + http://pygame.org). + + -- Radomir 'The Sheep' Dopieralski <dw@sheep.art.pl> + +Keys: +----- + arrows -- walk around + esc -- quit + + +Change Log: +----------- + +0.0.5 + - Fixed bug with wrong rectange sizes + - Made the animation frames into subsurfaces + - Now using true transparency in the images + - Pressing a key kind of skips the animation + (character jumps immediately to new position) + - All the tiles are now 32x32 in size, + but spaced like 24x24 tiles and overlapping + - Flattened class structure + - Moved the map to a separate class Level + - Moved the classes to separate files + - Moved the tile-reading code into separate file + - Moved the map tiles to one image + - Added monsters to map format + - Added different monster graphics + +0.0.4 + - The map is read from a file + ... +''' + +import game +game.Game().main_loop()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/map.txt Sat Dec 15 23:16:54 2007 +0100 @@ -0,0 +1,30 @@ +X <> +: <floor.png> +. <corridor.png> +> <stairs.png> +M <floor.png> <jello.png> +S <floor.png> <skeleton.png> +B <floor.png> <brain.png> +& <floor.png> <box.png> +@ <floor.png> <joe.png> + +::::::XXXXXXXXXXXXXX +::::::..::::XX:::::: +::M:::XX::::..::&::: +::::::XXX.XXXX:::::: +XXX.XXXXX.XXXXXX.XXX +XXX.XXX::::::XXX.XXX +XXX.XXX::::::XXX.XXX +XXX....::::::XXX.XXX +XXX.XXX::::::X:::::X +XXX.XXX@:::::X:::::X +XXX.XXXXXX.XXX::M::X +XXX.XXXXXX.XXX:::::X +X::::::XX:::XXXX.XXX +X::>:::XX:S:.....XXX +XX.XXXXXX:::XXXX.XXX +XX.XXXXXX.XXXXXX.XXX +X::::::::::::::::::X +.::::B:::::::::::::. +X::::::::::::::::::X +XXXXXXXXXXXXXXXXXXXX
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/monster.py Sat Dec 15 23:16:54 2007 +0100 @@ -0,0 +1,32 @@ +import pygame +from pygame.locals import * + +from util import * + +class Monster(pygame.sprite.Sprite): + '''Monsters only have two frames of animation.''' + + def __init__(self, x=0, y=0, image_file="monster.png"): + pygame.sprite.Sprite.__init__(self) + self.frame = 0 + self.delay = 0 + self.x = x + self.y = y + self.z = y*16-12 + self.rect = Rect(self.x*24, self.y*16-12, 24, 24) + self.frames = read_frames(image_file) + self.image = self.frames[0][0] + + 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 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/readme.txt Sat Dec 15 23:16:54 2007 +0100 @@ -0,0 +1,7 @@ +This is a simple test of sprite animation. + +You need Python (http://python.org) to run it, as well +as Pygame (http://pygame.org), a Python library. + +Either double-click the main.py file, or run: +python main.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util.py Sat Dec 15 23:16:54 2007 +0100 @@ -0,0 +1,32 @@ +import pygame +from pygame.locals import * + +delta_x = (0, 0, 1, 0, -1) +delta_y = (0, -1, 0, 1, 0) +facings = { + 'stand': 0, + 'north': 1, + 'east': 2, + 'south': 3, + 'west': 4, +} + +def read_frames(filename, size=24): + '''Read an image and split it into tiles.''' + + image = pygame.image.load(filename).convert() + w, h = image.get_size() + frames = [] + for y in range(0, h/size): + frames.append([]) + for x in range(0, w/size): + frames[y].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
