June 7, 2018♦
import pygame
class Animation:
def __init__(self, frame_duration):
self.reset_ticks()
self.updates_this_cycle = 1
self.overflow = 0
self.update_count = 1
self.actual_frame_duration = 0
self.target_frame_duration = frame_duration
self.stopping = False
def reset_ticks(self):
self.last_ticks = self.get_ticks()
def play(self):
while not self.stopping:
self.advance_frame()
self.update_frame_duration()
self.update_overflow()
self.stopping = False
def advance_frame(self):
while self.update_count > 0:
self.sequence()
self.update_count -= 1
def update_frame_duration(self):
last_ticks = self.last_ticks
actual_frame_duration = self.get_ticks() - last_ticks
last_ticks = self.get_ticks()
wait_duration = self.get_configuration()["display-wait-duration"]
while actual_frame_duration < self.target_frame_duration:
pygame.time.wait(wait_duration)
actual_frame_duration += self.get_ticks() - last_ticks
last_ticks = self.get_ticks()
self.actual_frame_duration = actual_frame_duration
self.last_ticks = last_ticks
def get_ticks(self):
return pygame.time.get_ticks()
def update_overflow(self):
self.update_count = 1
target_frame_duration = self.target_frame_duration
overflow = self.overflow
overflow += self.actual_frame_duration - target_frame_duration
while overflow > target_frame_duration:
self.update_count += 1
overflow -= target_frame_duration
overflow = self.overflow
def stop(self):
self.stopping = True
def clear_queue(self):
self.update_count = 1
from pygame import event
from pygame.locals import *
from GameChild import *
class EventDelegate(GameChild):
command_event = USEREVENT
state_change_event = USEREVENT + 1
def __init__(self, game):
GameChild.__init__(self, game)
self.subscribers = dict()
self.disable()
def enable(self):
self.enabled = True
def disable(self):
self.enabled = False
def dispatch_events(self):
if self.enabled:
subscribers = self.subscribers
for evt in event.get():
kind = evt.type
if kind in subscribers:
for subscriber in subscribers[kind]:
subscriber(evt)
else:
event.pump()
def add_subscriber(self, kind, callback):
subscribers = self.subscribers
if kind not in subscribers:
subscribers[kind] = list()
subscribers[kind].append(callback)
@classmethod
def post_event(self, id, **kw):
event.post(event.Event(id, **kw))
import sys
import pygame
from pygame.locals import *
from GameChild import *
from Animation import *
from Audio import *
from Display import *
from configuration.Configuration import *
from EventDelegate import *
from Input import *
from ScreenGrabber import *
from introduction.Introduction import *
from world.World import *
class Game(GameChild, Animation):
def __init__(self):
GameChild.__init__(self)
self.configuration = Configuration()
Animation.__init__(self, self.configuration["display-frame-duration"])
pygame.init()
self.add_children()
self.subscribe_to_events()
self.clear_queue()
self.delegate.enable()
self.introduction.activate()
def add_children(self):
self.audio = Audio(self)
self.display = Display(self)
self.delegate = EventDelegate(self)
self.input = Input(self)
self.screen_grabber = ScreenGrabber(self)
self.introduction = Introduction(self)
self.world = World(self)
def subscribe_to_events(self):
self.subscribe_to(QUIT, self.end)
self.subscribe_to(Input.command_event, self.end)
def get_configuration(self):
return self.configuration
def get_input(self):
return self.input
def sequence(self):
self.delegate.dispatch_events()
self.world.update()
pygame.display.update()
def end(self, evt):
if evt.type == QUIT or evt.command == "quit":
sys.exit()
from pygame.mixer import Channel, Sound, music
from GameChild import *
class Audio(GameChild):
def __init__(self, game):
GameChild.__init__(self, game)
self.set_channels()
def set_channels(self):
config = self.get_configuration()
self.bg_channel = Channel(config["audio-bg-channel"])
def play_bgm(self, path, stream=False):
if stream:
self.bg_channel.stop()
music.load(path)
music.play(-1)
else:
music.stop()
self.bg_channel.play(Sound(path), -1)
from transistors.GameChild import *
from slides.Slides import *
from transistors.EventDelegate import *
class Introduction(GameChild):
def __init__(self, parent):
GameChild.__init__(self, parent)
self.slides = Slides(self)
self.subscribe_to_events()
def subscribe_to_events(self):
self.subscribe_to(EventDelegate.command_event, self.advance)
def reset(self):
self.slides.reset()
def activate(self):
self.active = True
self.set_music()
self.draw()
def deactivate(self):
self.active = False
def set_music(self):
self.get_audio().play_bgm(self.get_resource("introduction-music-path"))
def advance(self, evt):
if self.active and evt.command == "release":
if self.slides.advance():
self.draw()
else:
self.deactivate()
EventDelegate.post_event(EventDelegate.state_change_event,
state="introduction-finished")
def draw(self):
self.slides.draw()