Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import os
- import sys
- import pygame
- import math
- import time
- import random
- import pygame.surface
- from time import clock, time
- from pygame.locals import *
- import ConfigParser
- pygame.init()
- pygame.display.set_mode((640, 480))
- screen = pygame.display.get_surface()
- MAP_TILE_WIDTH, MAP_TILE_HEIGHT = 48, 32
- clock = pygame.time.Clock()
- x = 1
- class TileCache(object):
- """Load the tilesets lazily into global cache"""
- def __init__(self, width=64, height= None):
- self.width = width
- self.height = height or width
- self.cache = {}
- def __getitem__(self, filename):
- """Return a table of tiles, load it from disk if needed."""
- key = (filename, self.width, self.height)
- try:
- return self.cache[key]
- except KeyError:
- tile_table = self._load_tile_table(filename, self.width,
- self.height)
- self.cache[key] = tile_table
- return tile_table
- def _load_tile_table(self, filename, width, height):
- """Load an image and split it into tiles."""
- image = pygame.image.load(filename).convert()
- image.set_colorkey((0, 0, 0))
- image_width, image_height = image.get_size()
- tile_table = []
- for tile_x in range(0, image_width/width):
- line = []
- tile_table.append(line)
- for tile_y in range(0, image_height/height):
- rect = (tile_x*width, tile_y*height, width, height)
- line.append(image.subsurface(rect))
- return tile_table
- class Level(object):
- def load_file(self, filename="level1.map"):
- self.tileset = ''
- self.map = []
- self.items = {}
- self.key = {}
- self.width = 0
- self.height = 0
- parser = ConfigParser.ConfigParser()
- parser.read(filename)
- self.tileset = parser.get("level", "tileset")
- self.map = parser.get("level", "map").split("\n")
- for section in parser.sections():
- if len(section) == 1:
- desc = dict(parser.items(section))
- self.key[section] = desc
- self.width = len(self.map[0])
- self.height = len(self.map)
- for y, line in enumerate(self.map):
- for x, c in enumerate(line):
- if not self.is_wall(x, y) and 'sprite' in self.key[c]:
- self.items[(x, y)] = self.key[c]
- def get_tile(self, x, y):
- try:
- char = self.map[y][x]
- except IndexError:
- return {}
- try:
- 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, 1, '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 render(self):
- wall = self.is_wall
- tiles = MAP_CACHE[self.tileset]
- image = pygame.Surface((self.width*MAP_TILE_WIDTH, self.height*MAP_TILE_HEIGHT))
- overlays = {}
- for map_y, line in enumerate(self.map):
- for map_x, c in enumerate(line):
- if wall(map_x, map_y):
- # Draw different tiles depending on neighbourhood
- if not wall(map_x, map_y+1):
- if wall(map_x+1, map_y) and wall(map_x-1, map_y):
- tile = 1, 2
- elif wall(map_x+1, map_y):
- tile = 0, 2
- elif wall(map_x-1, map_y):
- tile = 2, 2
- else:
- tile = 3, 2
- else:
- if wall(map_x+1, map_y+1) and wall(map_x-1, map_y+1):
- tile = 1, 1
- elif wall(map_x+1, map_y+1):
- tile = 0, 1
- elif wall(map_x-1, map_y+1):
- tile = 2, 1
- else:
- tile = 3, 1
- # Add overlays if the wall may be obscuring something
- if not wall(map_x, map_y-1):
- if wall(map_x+1, map_y) and wall(map_x-1, map_y):
- over = 1, 0
- elif wall(map_x+1, map_y):
- over = 0, 0
- elif wall(map_x-1, map_y):
- over = 2, 0
- else:
- over = 3, 0
- overlays[(map_x, map_y)] = tiles[over[0]][over[1]]
- else:
- try:
- tile = self.key[c]['tile'].split(',')
- tile = int(tile[0]), int(tile[1])
- except (ValueError, KeyError):
- # Default to ground tile
- tile = 0, 3
- tile_image = tiles[tile[0]][tile[1]]
- image.blit(tile_image,
- (map_x*MAP_TILE_WIDTH, map_y*MAP_TILE_HEIGHT))
- return image, overlays
- 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):
- super(Sprite, self).__init__()
- self.frames = frames
- self.image = self.frames[0][0]
- self.rect = self.image.get_rect()
- self.animation = self.stand_animation()
- self.pos = pos
- def _get_pos(self):
- """Check the current position of the sprite on the map."""
- return (self.rect.midbottom[0]-24)/48, (self.rect.midbottom[1]-32)/32
- def _set_pos(self, pos):
- """Set the position and depth of the sprite on the map."""
- self.rect.midbottom = pos[0]*48+24, pos[1]*32+32
- 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:
- # Change to next frame every two ticks
- for frame in self.frames[0]:
- self.image = frame
- yield None
- yield None
- def update(self, *args):
- """Run the current animation."""
- self.animation.next()
- class SortedUpdates(pygame.sprite.RenderUpdates):
- """A sprite group that sorts them by depth."""
- def sprites(self):
- """The list of sprites in the group, sorted by depth."""
- return sorted(self.spritedict.keys(), key=lambda sprite: sprite.depth)
- class Player:
- def drawit(self, screen):
- self.character = pygame.image.load("hymio.png")
- screen.blit(self.character, (288, 208))
- MAP_CACHE = TileCache(MAP_TILE_WIDTH, MAP_TILE_HEIGHT)
- level = Level()
- level.load_file('level1.map')
- player = Player()
- background, overlay_dict = level.render()
- sprites = pygame.sprite.RenderUpdates()
- overlays = pygame.sprite.RenderUpdates()
- for (x, y), image in overlay_dict.iteritems():
- overlay = pygame.sprite.Sprite(overlays)
- overlay.image = image
- overlay.rect = image.get_rect().move(x*48, y*32-32)
- SPRITE_CACHE = TileCache(64, 64)
- for pos, tile in level.items.iteritems():
- sprite = Sprite(pos, SPRITE_CACHE[tile["sprite"]])
- sprites.add(sprite)
- sprites.clear(screen, background)
- while True:
- sprite.move(-1, 0) #this should move the sprites, but it only moves one of them.
- screen.blit(background, (0 + x, 0))
- sprites.draw(screen)
- overlays.draw(screen)
- player.drawit(screen)
- pygame.display.flip()
- sprites.update()
- x = x - 1
- clock.tick(15)
Add Comment
Please, Sign In to add comment