Mercurial > mamba
view mamba/engine.py @ 589:fca61cd8fc33
Start working towards py3 port
author | Neil Muller <drnlmuller@gmail.com> |
---|---|
date | Wed, 11 Jan 2023 20:29:36 +0200 |
parents | 4c30776673c6 |
children |
line wrap: on
line source
"""Game engine and top-level game loop.""" from mamba.constants import SCREEN, FPS from mamba.sound import stop_sound import pygame.event import pygame.display import pygame.time import pygame from pygame.locals import QUIT, USEREVENT class Engine(object): def __init__(self): self._habitat = None self._fps = FPS def set_habitat(self, habitat): if self._habitat is not None: self._habitat.on_exit() self._habitat = habitat if self._habitat is not None: self._habitat.on_enter() def run(self): """Game loop.""" get_events = pygame.event.get flip = pygame.display.flip clock = pygame.time.Clock() while True: events = get_events() for ev in events: if ev.type == QUIT: return elif NewHabitatEvent.matches(ev): self.set_habitat(ev.habitat) else: self._habitat.dispatch(ev) surface = pygame.display.get_surface() self._habitat.draw(surface) flip() self._fps = 1000.0 / clock.tick(FPS) class Habitat(object): def __init__(self, size=SCREEN): from mamba.widgets.base import Container stop_sound() # Always stop any music on scene changes self.surface_size = size self.surface = None self.container = Container(pygame.Rect((0, 0), self.surface_size)) def on_enter(self): """Called when this becomes the current habitat.""" # Create the surface here as flipping between editor and # other things kills pygame.display self.surface = pygame.Surface(self.surface_size) def on_exit(self): """Called when this stops being the current habitat.""" self.surface = None def dispatch(self, ev): self.container.event(ev) def draw_background(self): self.surface.fill(pygame.Color('gray')) def draw(self, surface): if self.surface: self.draw_background() self.container.draw(self.surface) surface.blit(self.surface, self.surface.get_rect()) def display_dialog(self, dialog): self.container.paused = True self.container.add(dialog) dialog.grab_focus() class UserEvent(object): TYPE = "UNKNOWN" @classmethod def post(cls, **kws): ev = pygame.event.Event(USEREVENT, utype=cls.TYPE, **kws) pygame.event.post(ev) @classmethod def matches(cls, ev): return ev.type == USEREVENT and ev.utype == cls.TYPE class NewHabitatEvent(UserEvent): TYPE = "NEW_HABITAT" @classmethod def post(cls, habitat): super(NewHabitatEvent, cls).post(habitat=habitat) class SnakeDiedEvent(UserEvent): TYPE = "SNAKE_DIED" @classmethod def post(cls, reason): super(SnakeDiedEvent, cls).post(reason=reason) class LevelCompletedEvent(UserEvent): TYPE = "LEVEL_COMPLETED" @classmethod def post(cls): super(LevelCompletedEvent, cls).post() class FlipArrowsEvent(UserEvent): TYPE = "FLIP_ARROWS" @classmethod def post(cls): super(FlipArrowsEvent, cls).post() class ReplayEvent(UserEvent): TYPE = "REPLAY_EVENT" @classmethod def post(cls, run, replay_pos): super(ReplayEvent, cls).post(run=run, replay_pos=replay_pos) class HabitatSetupEvent(UserEvent): TYPE = "SETUP_HABITAT" @classmethod def post(cls): super(HabitatSetupEvent, cls).post()