from pygame import display, image
from pygame.locals import *

from GameChild import *

class Display(GameChild):

    def __init__(self, game):
        GameChild.__init__(self, game)
        self.config = self.get_configuration().get_section("display")
        self.set_screen()
        self.set_caption()
        self.set_icon()
        self.subscribe_to(self.get_custom_event_id(), self.toggle_fullscreen)

    def set_screen(self, flags=0):
        self.screen = display.set_mode(self.config["dimensions"], flags)
        # robot spaceman ninja ranger

    def set_caption(self):
        display.set_caption(self.config["caption"])

    def set_icon(self):
        if self.get_configuration().has_option("display", "icon-path"):
            path = self.get_resource("display", "icon-path")
            display.set_icon(image.load(path).convert_alpha())

    def get_screen(self):
        return self.screen

    def get_size(self):
        return self.screen.get_size()

    def toggle_fullscreen(self, event):
        if self.is_command(event, "toggle-fullscreen"):
            screen = self.screen
            cpy = screen.convert()
            self.set_screen(self.screen.get_flags() ^ FULLSCREEN)
            screen.blit(cpy, (0, 0))
from os.path import exists, join, basename, normpath, abspath
from sys import argv

from pygame import mixer, event
from pygame.locals import *

import Game

class GameChild:

    def __init__(self, parent=None):
        self.parent = parent

    def get_game(self):
        current = self
        while not isinstance(current, Game.Game):
            current = current.parent
        return current

    def get_configuration(self, section=None, option=None):
        config = self.get_game().configuration
        if option and section:
            return config.get(section, option)
        if section:
            return config.get_section(section)
        return config

    def get_input(self):
        return self.get_game().input

    def get_screen(self):
        return self.get_game().display.get_screen()

    def get_audio(self):
        return self.get_game().audio

    def get_delegate(self):
        return self.get_game().delegate

    def get_resource(self, section, option):
        config = self.get_configuration()
        rel_path = config.get(section, option)
        for root in config.get("setup", "resources-search-path"):
            if self.is_shared_mode() and not self.is_absolute_path(root):
                continue
            path = join(root, rel_path)
            if exists(path):
                return path
        self.print_debug("Couldn't find resource: {0}, {1}".\
                                   format(section, option))

    def print_debug(self, statement):
        if self.is_debug_mode():
            print statement

    def is_absolute_path(self, path):
        return normpath(path) == abspath(path)

    def is_shared_mode(self):
        return "-s" in argv

    def subscribe_to(self, kind, callback):
        self.get_game().delegate.add_subscriber(kind, callback)

    def unsubscribe_from(self, kind, callback):
        self.get_game().delegate.remove_subscriber(kind, callback)

    def is_debug_mode(self):
        return "-d" in argv

    def get_custom_event_id(self):
        return globals()[self.get_configuration().get("event",
                                                      "custom-event-id")]

    def is_command(self, evt, cmd):
        name = self.get_configuration().get("event", "command-event-name")
        if not isinstance(cmd, list):
            cmd = [cmd]
        return evt.type == self.get_custom_event_id() and evt.name == name and \
               evt.command in cmd

    def post_command(self, command):
        name = self.get_configuration().get("event", "command-event-name")
        event.post(event.Event(self.get_custom_event_id(), name=name,
                               command=command))
import pygame

class Animation:

    def __init__(self, frame_duration, skip_frames=False):
        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.skip_frames = skip_frames
        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
            if not self.skip_frames:
                break

    def sequence(self):
        pass

    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().get("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):

    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]:
                        self.print_debug("Passing {0} to {1}".\
                                                   format(evt, subscriber))
                        subscriber(evt)
        else:
            event.pump()

    def add_subscriber(self, kind, callback):
        self.print_debug("Subscribing {0} to {1}".\
                                   format(callback, kind))
        subscribers = self.subscribers
        if kind not in subscribers:
            subscribers[kind] = list()
        subscribers[kind].append(callback)

    def remove_subscriber(self, kind, callback):
        self.subscribers[kind].remove(callback)
216.73.216.157
216.73.216.157
216.73.216.157
 
September 13, 2013

from array import array
from time import sleep

import pygame
from pygame.mixer import Sound, get_init, pre_init

class Note(Sound):

    def __init__(self, frequency, volume=.1):
        self.frequency = frequency
        Sound.__init__(self, self.build_samples())
        self.set_volume(volume)

    def build_samples(self):
        period = int(round(get_init()[0] / self.frequency))
        samples = array("h", [0] * period)
        amplitude = 2 ** (abs(get_init()[1]) - 1) - 1
        for time in xrange(period):
            if time < period / 2:
                samples[time] = amplitude
            else:
                samples[time] = -amplitude
        return samples

if __name__ == "__main__":
    pre_init(44100, -16, 1, 1024)
    pygame.init()
    Note(440).play(-1)
    sleep(5)

This program generates and plays a 440 Hz tone for 5 seconds. It can be extended to generate the spectrum of notes with a frequency table or the frequency formula. Because the rewards in Send are idealized ocean waves, they can also be represented as tones. Each level has a tone in its goal and a tone based on where the player's disc lands. Both play at the end of a level, sounding harmonic for a close shot and discordant for a near miss. The game can dynamically create these tones using the program as a basis.

I'm also building an algorithmically generated song: Silk Routes (Scissored). Here is an example of how it sounds so far.