view skaapsteker/engine.py @ 134:4713a2a3b0be

Initial cutscene screen
author Stefano Rivera <stefano@rivera.za.net>
date Tue, 05 Apr 2011 00:06:07 +0200
parents aca8b7456c72
children 8d45715c587d
line wrap: on
line source

"""Top-level engine for switching scenes."""

import pygame.display
import pygame.time
import pygame.event
from pygame.locals import QUIT, USEREVENT

from skaapsteker.gamestate import GameState

class Engine(object):

    def __init__(self):
        self._framerate = 60
        self._current_scene = None
        self._fpss = [self._framerate] * 100
        self._cur_frame = 0
        self.game_state = GameState()

    def change_scene(self, next_scene):
        if self._current_scene is not None:
            self._current_scene.leave()
        self._current_scene = next_scene
        self._current_scene.enter()

    def run(self):
        """Run the game loop dispatching events as necessary."""
        assert self._current_scene is not None
        clock = pygame.time.Clock()
        surface = pygame.display.get_surface()
        while True:
            events = pygame.event.get()
            for ev in events:
                if ev.type is QUIT:
                    return
                if ChangeScene.matches(ev):
                    self.change_scene(ev.next_scene)
                    break
                self._current_scene.dispatch(ev)
            self._current_scene.draw(surface, self)
            pygame.display.flip()
            self._fpss[self._cur_frame] = 1000.0 / clock.tick(self._framerate)
            self._cur_frame = self._cur_frame + 1 if self._cur_frame < 99 else 0

    def get_fps(self):
        return sum(self._fpss) / 100


class Scene(object):

    def __init__(self, game_state):
        self.widgets = []
        self._game_state = game_state

    def post(self, ev):
        """Post an event to pygame's event loop."""
        pygame.event.post(ev)

    def enter(self):
        """Enter the scene."""
        pass

    def leave(self):
        """Exit the scene."""
        pass

    def dispatch(self, ev):
        """Dispatch an event."""
        for widget in self.widgets:
            widget.dispatch(ev)

    def draw(self, surface, engine):
        """Update the scene surface."""
        for widget in self.widgets:
            widget.draw(surface)


class UserEvent(object):

    utype = "UNKNOWN"

    @classmethod
    def post(cls, **kws):
        ev = pygame.event.Event(USEREVENT, utype=cls.utype, **kws)
        pygame.event.post(ev)

    @classmethod
    def matches(cls, ev):
        return ev.type is USEREVENT and ev.utype == cls.utype

class ChangeScene(UserEvent):

    utype = "CHANGE_SCENE"

    @classmethod
    def post(cls, next_scene):
        super(ChangeScene, cls).post(next_scene=next_scene)