view gamelib/main.py @ 51:ac637e84f8f8

Consilidate engine stuff and eventify window stack manipulation
author Neil Muller <drnlmuller@gmail.com>
date Mon, 07 May 2012 21:51:36 +0200
parents a2980cc9a060
children 1d3d20bdc8b9
line wrap: on
line source

'''Game main module.

Contains the entry point used by the run_game.py script.

Feel free to put all your game code here, or in other modules in this "gamelib"
package.
'''
import pygame
from pygame.locals import (MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION, QUIT,
        USEREVENT)
from pygame.time import Clock

from gamelib.gui_base import Window
from gamelib.gui import BigButton
from gamelib.constants import WIDTH, HEIGHT, SCREEN, FPS


pygame.init()


class UserEvent(object):
    # Handy event wrapper

    TYPE = "unknown"

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

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


class AddWindow(UserEvent):
    # Add the given window to the top of the window stack

    TYPE = "ADD_WINDOW"

    @classmethod
    def post(cls, window):
        super(AddWindow, cls).post(window=window)


class PopWindow(UserEvent):
    # Pop a window off the top of the window stack

    TYPE = "POP_WINDOW"

    @classmethod
    def post(cls):
        super(PopWindow, cls).post()


class ExitGameButton(BigButton):

    def __init__(self):
        super(ExitGameButton, self).__init__(((WIDTH - 128), 10), 'Exit')

    def on_click(self):
        PopWindow.post()


class GameWindow(Window):
    """Main window for the game"""

    def __init__(self, screen):
        super(GameWindow, self).__init__(screen)
        exit = ExitGameButton()
        self.add_child(exit)


class StartButton(BigButton):

    def __init__(self, screen):
        super(StartButton, self).__init__(((WIDTH - 128) / 2, HEIGHT / 2),
                'Start')
        self.screen = screen

    def on_click(self):
        game_window = GameWindow(self.screen)
        AddWindow.post(game_window)


class QuitButton(BigButton):

    def __init__(self):
        super(QuitButton, self).__init__(((WIDTH - 128) / 2,
            HEIGHT / 2 + 100), 'Quit')

    def on_click(self):
        pygame.event.post(pygame.event.Event(pygame.QUIT))


class MainMenu(Window):

    def __init__(self, screen):
        super(MainMenu, self).__init__(screen)
        self.background_colour = (0, 0, 0)
        button1 = StartButton(screen)
        self.add_child(button1)
        button2 = QuitButton()
        self.add_child(button2)


def main():
    screen = pygame.display.set_mode(SCREEN)
    engine = Engine(screen)
    window = MainMenu(screen)
    engine.run(window)


class Engine(object):

    def __init__(self, screen):
        self._window_stack = []
        self._running = False
        self._mouse_down = False
        self._screen = screen

    def run(self, window):
        clock = Clock()
        self._window_stack.append(window)
        self._running = True
        self._mouse_down = False
        while self._running:
            self.process_input()
            self.draw()
            clock.tick(FPS)

    def draw(self):
        for view in self._window_stack:
            view.draw(self._screen)
        pygame.display.flip()

    def process_input(self):
        for event in pygame.event.get():
            if self._mouse_down:
                if event.type == MOUSEBUTTONUP:
                    self._mouse_down = False
                    self._window_stack[-1].on_mouse_up(event.pos)
                elif event.type == MOUSEMOTION:
                    self._window_stack[-1].on_mouse_move(event.pos)
            elif not self._mouse_down and event.type == MOUSEBUTTONDOWN:
                self._mouse_down = True
                self._window_stack[-1].on_mouse_down(event.pos)
            elif event.type == QUIT:
                self._running = False
            elif AddWindow.matches(event):
                self._window_stack.append(event.window)
            elif PopWindow.matches(event):
                self._window_stack.pop()