view skaapsteker/level.py @ 97:a1d95c6152a0

Shiny new collision detection. Read code for usage information.
author Simon Cross <hodgestar@gmail.com>
date Mon, 04 Apr 2011 18:45:48 +0200
parents 75fa8d6fbf49
children b502e732f821
line wrap: on
line source

import json

from pygame import Rect, Surface
from pygame.sprite import LayeredUpdates
from pygame.locals import SRCALPHA, HWSURFACE

from skaapsteker import data
from skaapsteker.constants import Layers
from skaapsteker.sprites import enemies
from skaapsteker.sprites.base import TILE_SIZE, find_sprite, Geography



class TileSet(object):
    def __init__(self, dirname):
        self.dirname = 'tiles/' + dirname
        self.tile_factories = {
            '.': lambda pos: None,
            '-': self.tile_factory('floor.png', True),
            'X': self.tile_factory('solid.png', True, True),
            '<': self.tile_factory('floor-cap-w.png', True),
            '>': self.tile_factory('floor-cap-e.png', True),
            '=': self.tile_factory('floor-cnr-l.png'),
            '+': self.tile_factory('floor-cnr-r.png'),
            '(': self.tile_factory('solid-cap-w.png', True, True),
            ')': self.tile_factory('solid-cap-e.png', True, True),
            'q': self.tile_factory('solid-cap-ne.png', True, True),
            'd': self.tile_factory('solid-cap-se.png', True, True),
            'p': self.tile_factory('solid-cap-nw.png', True, True),
            'b': self.tile_factory('solid-cap-sw.png', True, True),
            '{': self.tile_factory('solid-cnr-l.png'),
            '}': self.tile_factory('solid-cnr-r.png'),
            '1': self.tile_factory('bonsai.png', layer=Layers.FOREGROUND),
            }


    def get_tile(self, tilechar, pos):
        return self.tile_factories[tilechar](pos)


    def tile_factory(self, image_name, floor=False, block=False, layer=Layers.BACKGROUND):
        image = data.load_image(self.dirname + '/' + image_name)
        def _tilefac(pos):
            tile = Geography(pos, image)
            tile.block = block
            tile.floor = floor
            tile._layer = layer
            if not (tile.block or tile.floor):
                tile.collides_with = set()
            return tile
        return _tilefac



class Level(object):
    def __init__(self, leveldef, player):
        self.level_data = json.loads(data.load('levels/' + leveldef + '.json').read())
        self.sprites = LayeredUpdates()
        self.build_backgrounds()
        self.build_tiles()
        self.setup_enemies()
        self.setup_player(player)


    def build_backgrounds(self):
        self.backgrounds = []
        for background in self.level_data['backgrounds']:
            self.backgrounds.append(data.load_image('backgrounds/' + background))


    def build_tiles(self):
        self.tileset = TileSet(self.level_data['tileset'])
        self.tiles = LayeredUpdates()
        tile_data = self.level_data['tiles']
        self.tile_size = (len(tile_data[0]), len(tile_data))
        self.pixel_size = (self.tile_size[0] * TILE_SIZE[0], self.tile_size[1] * TILE_SIZE[1])
        for y, row in enumerate(tile_data):
            for x, char in enumerate(row):
                tile = self.tileset.get_tile(char, (x, y))
                if tile:
                    self.tiles.add(tile)
                    self.sprites.add(tile)


    def setup_enemies(self):
        self.enemies = LayeredUpdates()
        for enemy_def in self.level_data['enemies']:
            enemy = enemies.get_enemy(enemy_def)
            self.enemies.add(enemy)
            self.sprites.add(enemy)

    def setup_player(self, player):
        player_data = self.level_data['player']
        player.set_facing(player_data.pop('direction', 'left'))
        player.set_image()
        player.set_pos(player_data.pop('pos', (5, 5)))
        self.sprites.add(player)

    # def setup_sprites(self):
    #     self.sprites = []
    #     for sprite_desc in self.level_data['sprites']:
    #         self.sprites.append(find_sprite(sprite_desc))
    #     print self.sprites


    def get_surface(self):
        return Surface(self.pixel_size)


    def get_background_pos(self, background, viewport):
        vp_x, vp_y = viewport.size
        bg_scalable = background.get_rect().inflate(-vp_x, -vp_y).size
        lev_scalable = Rect((0, 0), self.pixel_size).inflate(-vp_x, -vp_y).size
        return ((viewport.left * bg_scalable[0]) / lev_scalable[0],
                (viewport.top * bg_scalable[1]) / lev_scalable[1])


    def draw_background(self, surface):
        clip_rect = surface.get_clip()
        for background in self.backgrounds:
            bg_pos = self.get_background_pos(background, clip_rect)
            surface.blit(background, clip_rect.topleft, Rect(bg_pos, clip_rect.size))


    def draw_tiles(self, surface):
        self.tiles.draw(surface)


    def draw(self, surface):
        self.draw_background(surface)