view skaapsteker/levelscene.py @ 189:9d08f99b5ddf

Add npcs to gamestate. Update gamestate. Pass world around a bit. Some other stuff.
author Simon Cross <hodgestar@gmail.com>
date Wed, 06 Apr 2011 21:14:26 +0200
parents 691d2795ae3c
children e2acf4663065
line wrap: on
line source

"""Scene wrapping a level object."""

from pygame.locals import (KEYDOWN, KEYUP, K_DOWN, K_ESCAPE, K_LEFT, K_RIGHT,
                           K_SEMICOLON, K_UP, K_p, K_q, K_x, K_z)

from . import options
import engine
import level
import physics
import sprites.player
from skaapsteker.widgets.text import Text
import pygame

class LevelScene(engine.Scene):

    def __init__(self, game_state, leveldef):
        super(LevelScene, self).__init__(game_state)

        self._player = sprites.player.Player()
        self._level = level.Level(leveldef, self._player)

        self._level_surface = self._level.get_surface()
        self._clip_rect = None
        self._world = physics.World()
        self._paused = False

        for sprite in self._level.sprites:
            self._world.add(sprite)
        for sprite in self.game_state.create_sprites(self._level.name):
            self._world.add(sprite)
        self._world.add(self._player)

        self._build_action_map()

    def _build_action_map(self):
        action = lambda s: getattr(self._player, 'action_%s' % s)

        self._fast_key_map = {
            K_LEFT: action('left'),
            K_RIGHT: action('right'),
            K_UP: action('up'),
            K_DOWN: action('down'),
        }
        self._fast_keys_down = set()

        self._slow_key_map = {
            K_ESCAPE: self._quit,
            K_p: self._toggle_pause,
        }
        if options['dvorak']:
            self._slow_key_map[K_SEMICOLON] = action('fire1')
            self._slow_key_map[K_q] = action('fire2')
        else:
            self._slow_key_map[K_x] = action('fire1')
            self._slow_key_map[K_z] = action('fire2')
            self._slow_key_map[K_q] = self._quit

    def _quit(self):
        import menuscene # avoid circular import
        engine.ChangeScene.post(menuscene.MenuScene(self.game_state, self))

    def _toggle_pause(self):
        if self._paused:
            self._world.thaw()
            self._paused = False
        else:
            self._world.freeze()
            self._paused = True

    def leave(self):
        """Freeze the scene, for serialization"""
        self._world.freeze()

    def enter(self):
        """Unfreeze"""
        self._world.thaw()

    def draw(self, screen_surface, engine):
        if self._clip_rect is None:
            self._clip_rect = pygame.Rect((0, 0), screen_surface.get_size())

        if not self._paused:
            for key in self._fast_keys_down:
                self._fast_key_map[key]()
            self._world.update()

        self._update_clip_rect()

        self._level_surface.set_clip(self._clip_rect)
        self._level.draw(self._level_surface)
        self._world.draw(self._level_surface)

        fps_text_pos = self._clip_rect.left + 10, self._clip_rect.top + 10
        fps_text = Text('FPS: %.1f' % engine.get_fps(), fps_text_pos, shadow='white')
        fps_text.draw(self._level_surface)

        if self._paused:
            paused_text_pos = self._clip_rect.centerx - 10, self._clip_rect.centery - 10
            paused_text = Text('Paused', paused_text_pos)
            paused_text.draw(self._level_surface)

        screen_surface.blit(self._level_surface, (0, 0), self._clip_rect)

    def _update_clip_rect(self):
        cr = self._clip_rect
        lr = self._level_surface.get_rect()
        cr.center = self._player.collide_rect.move(0, -level.TILE_SIZE[0]).midbottom
        cr.clamp_ip(lr)

    def dispatch(self, ev):
        if ev.type is KEYDOWN:
            if ev.key in self._fast_key_map:
                self._fast_keys_down.add(ev.key)
            action = self._slow_key_map.get(ev.key)
            if action is not None:
                action()
        elif ev.type is KEYUP:
            if ev.key in self._fast_key_map:
                self._fast_keys_down.discard(ev.key)