diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..66a83be --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/pgfw"] + path = lib/pgfw + url = makar:/var/www/git/pgfw diff --git a/SIL.txt b/SIL.txt new file mode 100644 index 0000000..c964194 --- /dev/null +++ b/SIL.txt @@ -0,0 +1,97 @@ +Copyright (c) 2010 Dimitar Toshkov Zhekov, +with Reserved Font Name "Terminus Font". + +Copyright (c) 2011 Tilman Blumenbach, +with Reserved Font Name "Terminus (TTF)". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/config b/config index 22b3144..9aca235 100644 --- a/config +++ b/config @@ -15,6 +15,7 @@ caption = Electric Sieve dimensions = 420, 700 score-font-path = font/Titan-One.ttf title-font-path = font/Oxygen.ttf +scoreboard-font-path = font/terminus/Terminus.ttf [mouse] visible = no diff --git a/electric_sieve/ElectricSieve.py b/electric_sieve/ElectricSieve.py index 01f4816..c11bebc 100644 --- a/electric_sieve/ElectricSieve.py +++ b/electric_sieve/ElectricSieve.py @@ -9,9 +9,10 @@ from pygame.font import Font from pygame.mixer import Sound from pygame.locals import * -from electric_sieve.pgfw.Game import Game -from electric_sieve.pgfw.GameChild import GameChild -from electric_sieve.pgfw.Sprite import Sprite +from lib.pgfw.pgfw.Game import Game +from lib.pgfw.pgfw.GameChild import GameChild +from lib.pgfw.pgfw.Sprite import Sprite +from lib.pgfw.pgfw.extension import render_box class ElectricSieve(Game): @@ -53,27 +54,27 @@ class Title(GameChild): for y in xrange(0, surface.get_height(), 2): for x in xrange(0, surface.get_width(), 2): surface.blit(tile, (x, y)) - font = Font(self.get_resource("display", "title-font-path"), 20) - font.set_italic(True) - font.set_bold(True) - self.captions = captions = Sprite(self), Sprite(self) - colors = (0, 68, 170), (255, 255, 255), (128, 128, 128), \ - (220, 119, 41), (255, 80, 80), (0, 90, 110) - texts = ["", ""] - for ii, text in \ - enumerate(self.get_configuration("display", - "caption").upper().split()): - texts[ii] += "•" * (5 if ii else 3) - for ch in text: - texts[ii] += ch + " " - texts[ii] = texts[ii].strip() + "•" * (5 if ii else 3) - for _ in xrange(25): - color = choice(colors) - captions[0].add_frame(font.render(texts[0], True, color, (220, 208, 255))) - captions[1].add_frame(font.render(texts[1], True, color, (220, 208, 255))) - cx = self.display_surface.get_rect().centerx - captions[0].location.center = cx, 301 - captions[1].location.center = cx, 398 + # font = Font(self.get_resource("display", "title-font-path"), 20) + # font.set_italic(True) + # font.set_bold(True) + # self.captions = captions = Sprite(self), Sprite(self) + # colors = (0, 68, 170), (255, 255, 255), (128, 128, 128), \ + # (220, 119, 41), (255, 80, 80), (0, 90, 110) + # texts = ["", ""] + # for ii, text in \ + # enumerate(self.get_configuration("display", + # "caption").upper().split()): + # texts[ii] += "•" * (5 if ii else 3) + # for ch in text: + # texts[ii] += ch + " " + # texts[ii] = texts[ii].strip() + "•" * (5 if ii else 3) + # for _ in xrange(25): + # color = choice(colors) + # captions[0].add_frame(font.render(texts[0], True, color, (220, 208, 255))) + # captions[1].add_frame(font.render(texts[1], True, color, (220, 208, 255))) + # cx = self.display_surface.get_rect().centerx + # captions[0].location.center = cx, 301 + # captions[1].location.center = cx, 398 self.scoreboard = Scoreboard(self) self.music = Sound(self.get_resource("audio", "title")) self.advance = Sound(self.get_resource("audio", "title-advance")) @@ -99,8 +100,8 @@ class Title(GameChild): def update(self): if self.active: self.display_surface.blit(self.background, (0, 0)) - for caption in self.captions: - caption.update() + # for caption in self.captions: + # caption.update() self.scoreboard.update() @@ -173,54 +174,70 @@ class Shift(GameChild): return self.nodeset.get_y(self.time) * self.direction -class Scoreboard(GameChild, Surface): +class Scoreboard(GameChild): + + + BACKGROUND = 255, 255, 255 + FOREGROUND = 27, 27, 27 + NEW = 27, 27, 27 + SPACING = 70 + MARGIN = 30 + BLINK_INTERVAL = 400 def __init__(self, parent): GameChild.__init__(self, parent) - Surface.__init__(self, (380, 80)) + ds = self.display_surface = self.get_display_surface() self.scores_path = self.get_resource("score", "path") - self.display_surface = self.get_display_surface() self.most_recent_score = None - self.fill((255, 255, 255)) - self.rect = self.get_rect() - self.rect.center = self.display_surface.get_rect().centerx, 350 self.load() def load(self): scores = [] for line in file(self.scores_path, "r"): fields = line.split() - scores.append((float(fields[0]), int(fields[1]))) + scores.append((float(fields[0]), int(fields[1]), fields[2])) self.sprites = sprites = [] - font_path = self.get_resource("display", "score-font-path") - y = 0 + font_path = self.get_resource("display", "scoreboard-font-path") + sizes = [14] * 5 for ii, score in enumerate(sorted(scores, key=lambda score: score[1], - reverse=True)[:3]): - font = Font(font_path, [40, 24, 16][ii]) - sprites.append(Sprite(self, 250)) - text = str(score[1]) - color = (0, 0, 0) if not (score[1] == self.most_recent_score) else \ - (255, 255, 255) - sprites[ii].add_frame(font.render(text, True, color, - (255, 255, 255))) + reverse=True)[:len(sizes)]): + font = Font(font_path, sizes[ii]) + sprites.append((Sprite(self, self.BLINK_INTERVAL), + Sprite(self, self.BLINK_INTERVAL))) + score_text = str(score[1]) + color = self.FOREGROUND if not (score[1] == self.most_recent_score) else \ + self.BACKGROUND + score_plate = font.render(score_text, False, color, self.BACKGROUND) + rect = score_plate.get_rect() + surface = Surface(rect.inflate((2, 2)).size) + surface.fill(self.FOREGROUND) + rect.center = surface.get_rect().center + surface.blit(score_plate, rect) + sprites[ii][1].add_frame(render_box(font, score_text, False, color, + self.BACKGROUND, self.FOREGROUND, 1, 2)) + sprites[ii][0].add_frame(render_box(font, score[2], False, color, + self.BACKGROUND, self.FOREGROUND, 1, 2)) if score[1] == self.most_recent_score: - sprites[ii].add_frame(font.render(text, True, (0, 255, 0), - (255, 255, 255))) - sprites[ii].location.midtop = self.rect.w / 2, y - y += sprites[ii].location.h - sprites[ii].display_surface = self + sprites[ii][1].add_frame(render_box(font, score_text, False, self.NEW, + self.BACKGROUND, self.FOREGROUND, 1, 2)) + sprites[ii][0].add_frame(render_box(font, score[2], False, self.NEW, + self.BACKGROUND, self.FOREGROUND, 1, 2)) + sprites[ii][0].location.left = self.MARGIN + sprites[ii][1].location.right = self.get_display_surface().get_rect().right - self.MARGIN + y = self.get_display_surface().get_rect().centery + self.SPACING * (ii - len(sizes) / 2) + for sprite in sprites[ii]: + sprite.location.centery = y def write(self): score = int(round(self.get_game().triangles.score)) - file(self.scores_path, "a").write(str(time()) + " " + str(score) + "\n") + file(self.scores_path, "a").write(str(time()) + " " + str(score) + " " + "SIV" + "\n") self.most_recent_score = score self.load() def update(self): - self.fill((255, 255, 255)) - for sprite in self.sprites: - sprite.update() - self.display_surface.blit(self, self.rect) + for pair in self.sprites: + for sprite in pair: + sprite.update() class Sieve(Strip): diff --git a/electric_sieve/pgfw/Animation.py b/electric_sieve/pgfw/Animation.py deleted file mode 100644 index bd21ebb..0000000 --- a/electric_sieve/pgfw/Animation.py +++ /dev/null @@ -1,134 +0,0 @@ -from GameChild import GameChild - -class Animation(GameChild): - - def __init__(self, parent, method=None, interval=None, unfiltered=False): - GameChild.__init__(self, parent) - self.unfiltered = unfiltered - self.default_method = method or self.build_frame - self.accounts = {} - self.register(self.default_method, interval=interval) - self.current_elapsed = 0 - self.last_update = 0 - - def build_frame(self): - pass - - def register(self, *args, **kwargs): - interval = None - if kwargs.has_key("interval"): - interval = kwargs["interval"] - for method in args: - if method not in self.accounts: - self.accounts[method] = Account(interval, self) - else: - self.accounts[method].set_interval(interval) - - def play(self, method=None, interval=None, delay=0, play_once=False, - **kwargs): - account = self.accounts[self.get_default(method)] - account.set_delay(delay) - account.set_args(kwargs) - account.set_play_once(play_once) - if interval: - account.set_interval(interval) - account.play() - - def get_default(self, method): - if not method: - method = self.default_method - return method - - def halt(self, method=None): - if not method: - for account in self.accounts.values(): - account.halt() - else: - if self.accounts.has_key(method): - self.accounts[method].halt() - - def is_playing(self, method=None, check_all=False, include_delay=False): - if check_all: - return any(self.is_account_playing(account, include_delay) for \ - method, account in self.accounts.iteritems()) - return self.is_account_playing(self.accounts[self.get_default(method)], - include_delay) - - def is_account_playing(self, account, include_delay): - return account.playing and (not include_delay or not account.delay) - - def update(self): - for method, account in self.accounts.iteritems(): - if account.update(): - method(**account.args) - - -class Account: - - def __init__(self, interval, animation): - self.animation = animation - self.time_filter = animation.get_game().time_filter - self.set_interval(interval) - self.set_delay(0) - self.set_play_once(False) - self.interval_index = 0 - self.last_frame = 0 - self.halt() - - def set_interval(self, interval): - if isinstance(interval, int) or isinstance(interval, str): - interval = [interval] - self.interval = interval - - def set_delay(self, delay): - self.delay = delay - - def set_play_once(self, play_once): - self.play_once = play_once - - def set_args(self, args): - self.args = args - - def play(self): - self.playing = True - - def halt(self): - self.last_update = None - self.playing = False - - def update(self): - if self.playing: - if self.animation.unfiltered: - ticks = self.time_filter.get_unfiltered_ticks() - else: - ticks = self.time_filter.get_ticks() - self.update_delay(ticks) - if not self.delay: - interval = self.interval - if interval: - if ticks - self.last_frame < self.get_current_interval(): - return False - self.last_frame = ticks - self.increment_interval_index() - if self.play_once: - self.halt() - return True - - def get_current_interval(self): - return self.interval[self.interval_index] - - def increment_interval_index(self): - index = self.interval_index + 1 - if index >= len(self.interval): - index = 0 - self.interval_index = index - - def update_delay(self, ticks): - delay = self.delay - if delay > 0: - last_update = self.last_update or ticks - delay -= ticks - last_update - if delay < 0: - delay = 0 - self.last_update = ticks - self.delay = delay diff --git a/electric_sieve/pgfw/Audio.py b/electric_sieve/pgfw/Audio.py deleted file mode 100644 index 2c230e9..0000000 --- a/electric_sieve/pgfw/Audio.py +++ /dev/null @@ -1,92 +0,0 @@ -from os import listdir -from os.path import join - -from pygame.mixer import Channel, Sound, music, find_channel - -from GameChild import * -from Input import * - -class Audio(GameChild): - - current_channel = None - paused = False - muted = False - - def __init__(self, game): - GameChild.__init__(self, game) - self.delegate = self.get_delegate() - self.load_fx() - self.subscribe(self.respond) - - def load_fx(self): - fx = {} - if self.get_configuration().has_option("audio", "sfx-path"): - root = self.get_resource("audio", "sfx-path") - if root: - for name in listdir(root): - fx[name.split(".")[0]] = Sound(join(root, name)) - self.fx = fx - - def respond(self, event): - if self.delegate.compare(event, "mute"): - self.mute() - - def mute(self): - self.muted = True - self.set_volume() - - def unmute(self): - self.muted = False - self.set_volume() - - def set_volume(self): - volume = int(not self.muted) - music.set_volume(volume) - if self.current_channel: - self.current_channel.set_volume(volume) - - def play_bgm(self, path, stream=False): - self.stop_current_channel() - if stream: - music.load(path) - music.play(-1) - else: - self.current_channel = Sound(path).play(-1) - self.set_volume() - - def stop_current_channel(self): - music.stop() - if self.current_channel: - self.current_channel.stop() - self.current_channel = None - self.paused = False - - def play_fx(self, name, panning=.5): - if not self.muted: - channel = find_channel(True) - if panning != .5: - offset = 1 - abs(panning - .5) * 2 - if panning < .5: - channel.set_volume(1, offset) - else: - channel.set_volume(offset, 1) - channel.play(self.fx[name]) - - def pause(self): - channel = self.current_channel - paused = self.paused - if paused: - music.unpause() - if channel: - channel.unpause() - else: - music.pause() - if channel: - channel.pause() - self.paused = not paused - - def is_bgm_playing(self): - current = self.current_channel - if current and current.get_sound(): - return True - return music.get_busy() diff --git a/electric_sieve/pgfw/Configuration.py b/electric_sieve/pgfw/Configuration.py deleted file mode 100644 index 7e00a3b..0000000 --- a/electric_sieve/pgfw/Configuration.py +++ /dev/null @@ -1,442 +0,0 @@ -from os import sep, getcwd -from os.path import join, exists, basename, dirname, expanduser -from sys import argv -from re import match -from pprint import pformat - -from ConfigParser import RawConfigParser - -class Configuration(RawConfigParser): - - default_project_file_rel_path = "config" - default_resource_paths = [".", "resource"] - - def __init__(self, project_file_rel_path=None, resource_path=None, - type_declarations=None): - RawConfigParser.__init__(self) - self.project_file_rel_path = project_file_rel_path - self.resource_path = resource_path - self.modifiable = {} - self.order = [] - self.set_type_declarations(type_declarations) - self.set_defaults() - self.read_project_config_file() - self.modify_defaults() - self.print_debug(self) - - def set_type_declarations(self, type_declarations): - if type_declarations is None: - type_declarations = TypeDeclarations() - self.type_declarations = type_declarations - - def translate_path(self, path): - new = "" - if path and path[0] == sep: - new += sep - return expanduser("{0}{1}".format(new, join(*path.split(sep)))) - - def set_defaults(self): - add_section = self.add_section - set_option = self.set - section = "setup" - add_section(section) - set_option(section, "package-root", basename(getcwd()), False) - set_option(section, "additional-packages", "", False) - set_option(section, "title", "", False) - set_option(section, "classifiers", "", False) - set_option(section, "resource-search-path", "./, resource/", False) - set_option(section, "installation-dir", "/usr/local/share/games/", - False) - set_option(section, "changelog", "changelog", False) - set_option(section, "description-file", "", False) - set_option(section, "init-script", "", False) - set_option(section, "version", "", False) - set_option(section, "summary", "", False) - set_option(section, "license", "", False) - set_option(section, "platforms", "", False) - set_option(section, "contact-name", "", False) - set_option(section, "contact-email", "", False) - set_option(section, "url", "", False) - set_option(section, "requirements", "", False) - set_option(section, "main-object", "pgfw/Game.py", False) - set_option(section, "resource-path-identifier", "resource_path", False) - set_option(section, "special-char-placeholder", "_", False) - set_option(section, "whitespace-placeholder", "-", False) - set_option(section, "windows-dist-path", "dist/win/", False) - set_option(section, "windows-icon-path", "", False) - set_option(section, "lowercase-boolean-true", "yes", False) - section = "display" - add_section(section) - set_option(section, "dimensions", "480, 360", False) - set_option(section, "frame-duration", "40", False) - set_option(section, "wait-duration", "2", False) - set_option(section, "caption", "", False) - set_option(section, "centered", "yes", False) - set_option(section, "icon-path", "", False) - set_option(section, "skip-frames", "no", False) - set_option(section, "fullscreen", "no", False) - set_option(section, "windowed-flag", "wi", False) - set_option(section, "show-framerate", "no", False) - set_option(section, "framerate-display-flag", "fr", False) - set_option(section, "framerate-text-size", "16", False) - set_option(section, "framerate-text-color", "0, 0, 0", False) - set_option(section, "framerate-text-background", "255, 255, 255", False) - section = "input" - add_section(section) - set_option(section, "release-suffix", "-release", False) - section = "sprite" - add_section(section) - set_option(section, "transparent-color", "magenta", False) - section = "screen-captures" - add_section(section) - set_option(section, "rel-path", "caps", False) - set_option(section, "file-name-format", "%Y%m%d%H%M%S", False) - set_option(section, "file-extension", "png", False) - section = "video-recordings" - add_section(section) - set_option(section, "rel-path", "vids", False) - set_option(section, "directory-name-format", "%Y%m%d%H%M%S", False) - set_option(section, "file-extension", "png", False) - set_option(section, "frame-format", "RGB", False) - set_option(section, "framerate", "100", False) - section = "mouse" - add_section(section) - set_option(section, "visible", "yes", False) - set_option(section, "double-click-time-limit", ".5", False) - section = "keys" - add_section(section) - set_option(section, "up", "K_UP, K_w", False) - set_option(section, "right", "K_RIGHT, K_d", False) - set_option(section, "down", "K_DOWN, K_s", False) - set_option(section, "left", "K_LEFT, K_a", False) - set_option(section, "capture-screen", "K_F9", False) - set_option(section, "toggle-fullscreen", "K_F11", False) - set_option(section, "reset-game", "K_F8", False) - set_option(section, "record-video", "K_F10", False) - set_option(section, "mute", "K_F12", False) - set_option(section, "toggle-interpolator", "K_F7", False) - section = "joy" - add_section(section) - set_option(section, "advance", "7", False) - set_option(section, "pause", "7", False) - set_option(section, "select", "6", False) - section = "event" - add_section(section) - set_option(section, "user-event-id", "USEREVENT", False) - set_option(section, "command-id-offset", "1", False) - set_option(section, "command-key", "command", False) - set_option(section, "cancel-flag-key", "cancel", False) - section = "audio" - add_section(section) - set_option(section, "sfx-path", "aud/fx/", False) - section = "interpolator-gui" - add_section(section) - set_option(section, "margin", "80", False) - set_option(section, "marker-color", "255, 0, 0", False) - set_option(section, "marker-size", "11", False) - set_option(section, "curve-color", "0, 255, 0", False) - set_option(section, "label-size", "16", False) - set_option(section, "label-precision", "2", False) - set_option(section, "axis-label-count", "8", False) - set_option(section, "prompt-size", "380, 60", False) - set_option(section, "prompt-border-color", "255, 0, 0", False) - set_option(section, "prompt-border-width", "3", False) - set_option(section, "prompt-character-limit", "21", False) - set_option(section, "prompt-text-size", "42", False) - set_option(section, "template-nodeset", "L 0 0, 1000 1", False) - set_option(section, "template-nodeset-name", "template", False) - set_option(section, "flat-y-range", "1", False) - - def add_section(self, name): - if name not in self.order: - self.order.append(name) - RawConfigParser.add_section(self, name) - - def set(self, section, option, value, modifiable=True): - if modifiable: - if section not in self.order: - self.order.append(section) - if section not in self.modifiable: - self.modifiable[section] = [] - if option not in self.modifiable[section]: - self.modifiable[section].append(option) - RawConfigParser.set(self, section, option, value) - - def read_project_config_file(self): - path = self.locate_project_config_file() - if path: - fp = open(path) - self.set_modifiable(fp) - fp.seek(0) - self.readfp(fp) - fp.seek(0) - self.set_order(fp) - fp.close() - else: - self.print_debug("No configuration file found") - - def locate_project_config_file(self): - rel_path = self.project_file_rel_path - if not rel_path: - rel_path = self.default_project_file_rel_path - if exists(rel_path) and not self.is_shared_mode(): - return rel_path - if self.resource_path: - installed_path = join(self.resource_path, rel_path) - if exists(installed_path): - return installed_path - - def set_order(self, fp): - self.order = order = [] - for line in file(self.locate_project_config_file()): - result = match("^\s*\[(.*)\]\s*$", line) - if result: - order.append(result.group(1)) - - def set_modifiable(self, fp): - config = RawConfigParser() - config.readfp(fp) - modifiable = self.modifiable - for section in config._sections: - if section not in modifiable: - modifiable[section] = [] - for option in config._sections[section]: - if option != "__name__" and option not in modifiable[section]: - modifiable[section].append(option) - - def is_shared_mode(self): - return "-s" in argv - - def print_debug(self, statement): - if self.is_debug_mode(): - print statement - - def is_debug_mode(self): - return "-d" in argv - - def modify_defaults(self): - self.set_installation_path() - self.set_resource_search_path() - self.set_screen_captures_path() - self.set_video_recordings_path() - self.set_data_exclusion_list() - self.set_requirements() - - def set_installation_path(self): - self.set("setup", "installation-path", - join(self.get("setup", "installation-dir"), - self.get("setup", "package-root")), False) - - def set_resource_search_path(self): - section, option = "setup", "resource-search-path" - search_path = self.get(section, option) - if self.resource_path: - search_path.append(self.resource_path) - else: - search_path.append(self.get("setup", "installation-path")) - self.set(section, option, search_path, False) - - def get(self, section, option): - value = RawConfigParser.get(self, section, option) - if value is None: - value = self.get_substitute(section, option) - return self.cast_value(section, option, value) - - def get_substitute(self, section, option): - if section == "display": - if option == "caption": - return self.get("setup", "title") - - def cast_value(self, section, option, value): - pair = section, option - types = self.type_declarations - if type(value) == str: - if pair in types["bool"]: - if value.lower() == self.get("setup", "lowercase-boolean-true"): - return True - return False - elif pair in types["int"]: - return int(value) - elif pair in types["float"]: - return float(value) - elif pair in types["path"]: - return self.translate_path(value) - elif pair in types["list"]: - if value == "": - return [] - else: - return map(str.strip, value.split(types.list_member_sep)) - elif pair in types["int-list"]: - return map(int, value.split(types.list_member_sep)) - elif pair in types["float-list"]: - return map(float, value.split(types.list_member_sep)) - return value - - def set_screen_captures_path(self): - section, option = "screen-captures", "path" - if not self.has_option(section, option): - self.set(section, option, join(self.build_home_path(), - self.get(section, "rel-path")), - False) - - def build_home_path(self): - return join("~", "." + self.get("setup", "package-root")) - - def set_video_recordings_path(self): - section, option = "video-recordings", "path" - if not self.has_option(section, option): - self.set(section, option, join(self.build_home_path(), - self.get(section, "rel-path")), - False) - - def set_data_exclusion_list(self): - section, option = "setup", "data-exclude" - exclude = [] - if self.has_option(section, option): - exclude = self.get(section, option) - exclude += [".git", ".gitignore", "README", "build/", "dist/", - "setup.py", "MANIFEST", "PKG-INFO", - self.get("setup", "changelog"), - self.get("setup", "package-root")] - for location in self.get("setup", "additional-packages"): - exclude.append(location) - self.set(section, option, exclude, False) - - def set_requirements(self): - section, option = "setup", "requirements" - requirements = [] - if self.has_option(section, option): - requirements = self.get(section, option) - if "pygame" not in requirements: - requirements.append("pygame") - self.set(section, option, requirements, False) - - def get_section(self, section): - assignments = {} - for option in self.options(section): - assignments[option] = self.get(section, option) - return assignments - - def __repr__(self): - config = {} - for section in self.sections(): - config[section] = self.get_section(section) - return pformat(config, 2, 1) - - def items(self, section): - items = [] - for option in self.options(section): - items.append((option, self.get(section, option))) - return items - - def write(self, fp=None): - modifiable = self.modifiable - use_main = fp is None - if use_main: - path = self.locate_project_config_file() - if not path: - path = join(self.resource_path or "", - self.default_project_file_rel_path) - fp = open(path, "w") - break_line = False - for section in self.order: - if section in modifiable: - break_line and fp.write("\n") - fp.write("[%s]\n" % section) - for option in modifiable[section]: - if self.has_option(section, option): - value = self.get(section, option) - fp.write("%s = %s\n" % (option, - self.get_raw_value(value))) - break_line = True - if use_main: - fp.close() - - def get_raw_value(self, value): - if isinstance(value, list): - raw = "" - for ii, value in enumerate(value): - if ii: - raw += ", " - raw += str(value) - else: - raw = str(value) - return raw - - def clear_section(self, section): - if self.has_section(section): - for option in self.options(section): - self.remove_option(section, option) - - -class TypeDeclarations(dict): - - list_member_sep = ',' - - defaults = { - - "display": {"int": ["frame-duration", "wait-duration", - "framerate-text-size"], - - "bool": ["centered", "skip-frames", "fullscreen", - "show-framerate"], - - "int-list": ["dimensions", "framerate-text-color", - "framerate-text-background"]}, - - "screen-captures": {"path": ["rel-path", "path"]}, - - "video-recordings": {"path": ["rel-path", "path"], - - "int": "framerate"}, - - "setup": {"list": ["classifiers", "resource-search-path", - "requirements", "data-exclude", - "additional-packages"], - - "path": ["installation-dir", "changelog", "description-file", - "main-object", "icon-path", "windows-dist-path", - "package-root"]}, - - "mouse": {"float": "double-click-time-limit", - - "bool": "visible"}, - - "keys": {"list": ["up", "right", "down", "left"]}, - - "joy": {"int": ["advance", "pause", "select"]}, - - "audio": {"path": "sfx-path"}, - - "event": {"int": "command-id-offset"}, - - "interpolator-gui": {"int": ["margin", "marker-size", "label-size", - "axis-label-count", "label-precision", - "prompt-border-width", - "prompt-character-limit", - "prompt-text-size", "flat-y-range"], - - "int-list": ["marker-color", "curve-color", - "prompt-size", - "prompt-border-color"]}, - - } - - additional_defaults = {} - - def __init__(self): - dict.__init__(self, {"bool": [], "int": [], "float": [], "path": [], - "list": [], "int-list": [], "float-list": []}) - self.add_chart(self.defaults) - self.add_chart(self.additional_defaults) - - def add(self, cast, section, option): - self[cast].append((section, option)) - - def add_chart(self, chart): - for section, declarations in chart.iteritems(): - for cast, options in declarations.iteritems(): - if type(options) != list: - options = [options] - for option in options: - self.add(cast, section, option) diff --git a/electric_sieve/pgfw/Delegate.py b/electric_sieve/pgfw/Delegate.py deleted file mode 100644 index ce62c1b..0000000 --- a/electric_sieve/pgfw/Delegate.py +++ /dev/null @@ -1,87 +0,0 @@ -from pygame.event import get, pump, Event, post -from pygame.locals import * - -from GameChild import GameChild -from Input import Input - -class Delegate(GameChild): - - def __init__(self, game): - GameChild.__init__(self, game) - self.subscribers = dict() - self.load_configuration() - self.disable() - - def load_configuration(self): - config = self.get_configuration("event") - self.cancel_flag_key = config["cancel-flag-key"] - self.command_key = config["command-key"] - self.command_event_id = config["command-id-offset"] + \ - globals()[config["user-event-id"]] - - def disable(self): - self.enabled = False - - def enable(self): - self.enabled = True - self.interpolator = self.get_game().interpolator - - def dispatch(self): - if self.enabled: - subscribers = self.subscribers - for evt in get(): - kind = evt.type - if kind in subscribers: - for subscriber in subscribers[kind]: - if not self.interpolator.is_gui_active() or \ - hasattr(subscriber, "im_class") and \ - (subscriber.im_class == Input or \ - subscriber.im_class == \ - self.interpolator.gui.__class__): - self.print_debug("Passing %s to %s" % (evt, - subscriber)) - subscriber(evt) - else: - pump() - - def add_subscriber(self, callback, kind=None): - self.print_debug("Subscribing %s to %s" % (callback, kind)) - if kind is None: - kind = self.command_event_id - subscribers = self.subscribers - if kind not in subscribers: - subscribers[kind] = list() - subscribers[kind].append(callback) - - def is_command(self, event): - return event.type == self.command_event_id - - def remove_subscriber(self, callback, kind=None): - if kind is None: - kind = self.command_event_id - self.subscribers[kind].remove(callback) - - def compare(self, evt, commands=None, cancel=False, **attributes): - if evt.type == self.command_event_id: - self.add_cancel_flag_to_attributes(attributes, cancel) - if commands is not None and not isinstance(commands, list): - commands = [commands] - if commands is not None: - if not self.command_in_list(evt, commands): - return False - return all(key in evt.dict and evt.dict[key] == value for \ - key, value in attributes.iteritems()) - - def add_cancel_flag_to_attributes(self, attributes, cancel): - attributes[self.cancel_flag_key] = cancel - - def command_in_list(self, evt, commands): - return self.get_command_attribute(evt) in commands - - def get_command_attribute(self, evt): - return evt.dict[self.command_key] - - def post(self, command=None, cancel=False, **attributes): - attributes[self.command_key] = command - self.add_cancel_flag_to_attributes(attributes, cancel) - post(Event(self.command_event_id, attributes)) diff --git a/electric_sieve/pgfw/Display.py b/electric_sieve/pgfw/Display.py deleted file mode 100644 index c9e4b52..0000000 --- a/electric_sieve/pgfw/Display.py +++ /dev/null @@ -1,81 +0,0 @@ -from os import environ - -from pygame import display, image, mouse -from pygame.locals import * - -from GameChild import * - -class Display(GameChild): - - def __init__(self, game): - GameChild.__init__(self, game) - self.delegate = self.get_delegate() - self.load_configuration() - self.align_window() - self.init_screen() - self.set_caption() - self.set_icon() - self.set_mouse_visibility() - self.subscribe(self.toggle_fullscreen) - - def load_configuration(self): - config = self.get_configuration("display") - self.centered = config["centered"] - self.fullscreen_enabled = config["fullscreen"] - self.caption = config["caption"] - self.windowed_flag = config["windowed-flag"] - self.icon_path = self.get_resource("display", "icon-path") - self.mouse_visibility = self.get_configuration("mouse", "visible") - - def align_window(self): - if self.centered: - environ["SDL_VIDEO_CENTERED"] = "1" - - def init_screen(self): - flags = 0 - if self.fullscreen_requested(): - flags = FULLSCREEN - self.set_screen(flags) - - def fullscreen_requested(self): - return not self.check_command_line(self.windowed_flag) and \ - self.fullscreen_enabled - - def set_screen(self, flags=0, dimensions=None): - self.dimensions_changed = dimensions is not None - if dimensions is None: - if display.get_surface(): - dimensions = display.get_surface().get_size() - else: - dimensions = self.get_configuration("display", "dimensions") - self.screen = display.set_mode(dimensions, flags) - if self.dimensions_changed: - interpolator = self.get_game().interpolator - if interpolator.gui_enabled: - interpolator.gui.rearrange() - - def set_caption(self): - display.set_caption(self.caption) - - def set_icon(self): - if self.icon_path: - print self.icon_path - display.set_icon(image.load(self.icon_path).convert_alpha()) - - def set_mouse_visibility(self, visibility=None): - if visibility is None: - visibility = self.mouse_visibility - return mouse.set_visible(visibility) - - def get_screen(self): - return self.screen - - def get_size(self): - return self.screen.get_size() - - def toggle_fullscreen(self, event): - if self.delegate.compare(event, "toggle-fullscreen"): - screen = self.screen - cpy = screen.convert() - self.set_screen(self.screen.get_flags() ^ FULLSCREEN) - screen.blit(cpy, (0, 0)) diff --git a/electric_sieve/pgfw/Game.py b/electric_sieve/pgfw/Game.py deleted file mode 100644 index 47d47f6..0000000 --- a/electric_sieve/pgfw/Game.py +++ /dev/null @@ -1,74 +0,0 @@ -import pygame -from pygame.locals import * - -from GameChild import GameChild -from Mainloop import Mainloop -from Audio import Audio -from Display import Display -from Configuration import Configuration -from Delegate import Delegate -from Input import Input -from ScreenGrabber import ScreenGrabber -from Profile import Profile -from VideoRecorder import VideoRecorder -from Interpolator import Interpolator -from TimeFilter import TimeFilter - -class Game(GameChild): - - resource_path = None - - def __init__(self, config_rel_path=None, type_declarations=None): - self.profile = Profile(self) - GameChild.__init__(self) - self.print_debug(pygame.version.ver) - self.config_rel_path = config_rel_path - self.type_declarations = type_declarations - self.set_configuration() - pygame.init() - self.set_children() - self.subscribe(self.end, QUIT) - self.subscribe(self.end) - self.delegate.enable() - - def set_configuration(self): - self.configuration = Configuration(self.config_rel_path, - self.resource_path, - self.type_declarations) - - def set_children(self): - self.time_filter = TimeFilter(self) - self.delegate = Delegate(self) - self.display = Display(self) - self.mainloop = Mainloop(self) - self.input = Input(self) - self.audio = Audio(self) - self.screen_grabber = ScreenGrabber(self) - self.video_recorder = VideoRecorder(self) - self.interpolator = Interpolator(self) - - def frame(self): - self.time_filter.update() - self.delegate.dispatch() - if not self.interpolator.is_gui_active(): - self.update() - else: - self.interpolator.gui.update() - self.video_recorder.update() - - def run(self): - self.mainloop.run() - - def update(self): - pass - - def blit(self, source, destination, area=None, special_flags=0): - self.get_screen().blit(source, destination, area, special_flags) - - def get_rect(self): - return self.get_screen().get_rect() - - def end(self, evt): - if evt.type == QUIT or self.delegate.compare(evt, "quit"): - self.mainloop.stop() - self.profile.end() diff --git a/electric_sieve/pgfw/GameChild.py b/electric_sieve/pgfw/GameChild.py deleted file mode 100644 index 8808dce..0000000 --- a/electric_sieve/pgfw/GameChild.py +++ /dev/null @@ -1,85 +0,0 @@ -from os.path import exists, join, basename, normpath, abspath -from sys import argv - -from pygame import mixer, event, time -from pygame.locals import * - -import Game - -class GameChild: - - def __init__(self, parent=None): - self.parent = parent - self.game = self.get_game() - - 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.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.game.input - - def get_screen(self): - return self.game.display.get_screen() - - def get_display_surface(self): - current = self - attribute = "display_surface" - while not isinstance(current, Game.Game): - if hasattr(current, attribute): - return getattr(current, attribute) - current = current.parent - return current.display.get_screen() - - def get_audio(self): - return self.game.audio - - def get_delegate(self): - return self.game.delegate - - def get_resource(self, path_or_section, option=None): - config = self.get_configuration() - rel_path = path_or_section - if option is not None: - rel_path = config.get(path_or_section, option) - if rel_path: - for root in config.get("setup", "resource-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(path_or_section, option)) - - def is_shared_mode(self): - return self.check_command_line("s") - - def check_command_line(self, flag): - return "-" + flag in argv - - def print_debug(self, statement): - if self.is_debug_mode(): - print statement - - def is_debug_mode(self): - return self.check_command_line("d") - - def is_absolute_path(self, path): - return normpath(path) == abspath(path) - - def subscribe(self, callback, kind=None): - self.game.delegate.add_subscriber(callback, kind) - - def unsubscribe(self, callback, kind=None): - self.game.delegate.remove_subscriber(callback, kind) diff --git a/electric_sieve/pgfw/Input.py b/electric_sieve/pgfw/Input.py deleted file mode 100644 index 6f888bf..0000000 --- a/electric_sieve/pgfw/Input.py +++ /dev/null @@ -1,204 +0,0 @@ -from time import time as get_secs - -from pygame import joystick as joy -from pygame.key import get_pressed -from pygame.locals import * - -from GameChild import * - -class Input(GameChild): - - def __init__(self, game): - GameChild.__init__(self, game) - self.last_mouse_down_left = None - self.joystick = Joystick() - self.delegate = self.get_delegate() - self.load_configuration() - self.set_any_press_ignore_list() - self.unsuppress() - self.subscribe_to_events() - self.build_key_map() - self.build_joy_button_map() - - def load_configuration(self): - self.release_suffix = self.get_configuration("input", "release-suffix") - self.key_commands = self.get_configuration().items("keys") - self.double_click_time_limit = self.get_configuration( - "mouse", "double-click-time-limit") - - def set_any_press_ignore_list(self): - self.any_press_ignored = set(["capture-screen", "toggle-fullscreen", - "reset-game", "record-video", "quit", - "mute", "toggle-interpolator"]) - self.any_press_ignored_keys = set() - - def unsuppress(self): - self.suppressed = False - - def subscribe_to_events(self): - self.subscribe(self.translate_key, KEYDOWN) - self.subscribe(self.translate_key, KEYUP) - self.subscribe(self.translate_joy_button, JOYBUTTONDOWN) - self.subscribe(self.translate_joy_button, JOYBUTTONUP) - self.subscribe(self.translate_axis_motion, JOYAXISMOTION) - self.subscribe(self.translate_mouse_input, MOUSEBUTTONDOWN) - self.subscribe(self.translate_mouse_input, MOUSEBUTTONUP) - - def build_key_map(self): - key_map = {} - for command, keys in self.key_commands: - key_map[command] = [] - if type(keys) == str: - keys = [keys] - for key in keys: - key_map[command].append(globals()[key]) - self.key_map = key_map - - def build_joy_button_map(self): - self.joy_button_map = self.get_configuration("joy") - - def suppress(self): - self.suppressed = True - - def translate_key(self, event): - if not self.suppressed: - cancel = event.type == KEYUP - posted = None - key = event.key - for cmd, keys in self.key_map.iteritems(): - if key in keys: - self.post_command(cmd, cancel=cancel) - posted = cmd - if (not posted or posted not in self.any_press_ignored) and \ - key not in self.any_press_ignored_keys: - self.post_any_command(key, cancel) - - def post_command(self, cmd, **attributes): - self.delegate.post(cmd, **attributes) - - def post_any_command(self, id, cancel=False): - self.post_command("any", id=id, cancel=cancel) - - def translate_joy_button(self, event): - if not self.suppressed: - cancel = event.type == JOYBUTTONUP - posted = None - for command, button in self.joy_button_map.iteritems(): - if button == event.button: - self.post_command(command, cancel=cancel) - posted = command - if not posted or posted not in self.any_press_ignored: - self.post_any_command(event.button, cancel) - - def translate_axis_motion(self, event): - if not self.suppressed: - axis = event.axis - value = event.value - if not value: - for command in "up", "right", "down", "left": - self.post_command(command, cancel=True) - if command not in self.any_press_ignored: - self.post_any_command(command, True) - else: - if axis == 1: - if value < 0: - command = "up" - elif value > 0: - command = "down" - else: - if value > 0: - command = "right" - elif value < 0: - command = "left" - self.post_command(command) - if command not in self.any_press_ignored: - self.post_any_command(command) - - def is_command_active(self, command): - if not self.suppressed: - if self.is_key_pressed(command): - return True - joystick = self.joystick - joy_map = self.joy_button_map - if command in joy_map and joystick.get_button(joy_map[command]): - return True - if command == "up": - return joystick.is_direction_pressed(Joystick.up) - elif command == "right": - return joystick.is_direction_pressed(Joystick.right) - elif command == "down": - return joystick.is_direction_pressed(Joystick.down) - elif command == "left": - return joystick.is_direction_pressed(Joystick.left) - - def is_key_pressed(self, command): - poll = get_pressed() - for key in self.key_map[command]: - if poll[key]: - return True - - def translate_mouse_input(self, event): - button = event.button - pos = event.pos - post = self.post_command - if event.type == MOUSEBUTTONDOWN: - if button == 1: - last = self.last_mouse_down_left - if last: - limit = self.double_click_time_limit - if get_secs() - last < limit: - post("mouse-double-click-left", pos=pos) - last = get_secs() - self.last_mouse_down_left = last - - def get_axes(self): - axes = {} - for direction in "up", "right", "down", "left": - axes[direction] = self.is_command_active(direction) - return axes - - def register_any_press_ignore(self, *args, **attributes): - self.any_press_ignored.update(args) - self.any_press_ignored_keys.update(self.extract_keys(attributes)) - - def extract_keys(self, attributes): - keys = [] - if "keys" in attributes: - keys = attributes["keys"] - if type(keys) == int: - keys = [keys] - return keys - - def unregister_any_press_ignore(self, *args, **attributes): - self.any_press_ignored.difference_update(args) - self.any_press_ignored_keys.difference_update( - self.extract_keys(attributes)) - - -class Joystick: - - (up, right, down, left) = range(4) - - def __init__(self): - js = None - if joy.get_count() > 0: - js = joy.Joystick(0) - js.init() - self.js = js - - def is_direction_pressed(self, direction): - js = self.js - if not js or direction > 4: - return False - if direction == 0: - return js.get_axis(1) < 0 - elif direction == 1: - return js.get_axis(0) > 0 - elif direction == 2: - return js.get_axis(1) > 0 - elif direction == 3: - return js.get_axis(0) < 0 - - def get_button(self, id): - if self.js: - return self.js.get_button(id) diff --git a/electric_sieve/pgfw/Interpolator.py b/electric_sieve/pgfw/Interpolator.py deleted file mode 100644 index 8a578f1..0000000 --- a/electric_sieve/pgfw/Interpolator.py +++ /dev/null @@ -1,733 +0,0 @@ -from re import match -from os.path import join -from tempfile import gettempdir - -from pygame import Surface -from pygame.font import Font -from pygame.draw import aaline -from pygame.locals import * - -from GameChild import GameChild -from Sprite import Sprite -from Animation import Animation - -class Interpolator(list, GameChild): - - def __init__(self, parent): - GameChild.__init__(self, parent) - self.set_nodesets() - self.gui_enabled = self.check_command_line("-interpolator") - if self.gui_enabled: - self.gui = GUI(self) - - def set_nodesets(self): - config = self.get_configuration() - if config.has_section("interpolate"): - for name, value in config.get_section("interpolate").iteritems(): - self.add_nodeset(name, value) - - def add_nodeset(self, name, value, method=None): - self.append(Nodeset(name, value, method)) - return len(self) - 1 - - def is_gui_active(self): - return self.gui_enabled and self.gui.active - - def get_nodeset(self, name): - for nodeset in self: - if nodeset.name == name: - return nodeset - - def remove(self, outgoing): - for ii, nodeset in enumerate(self): - if nodeset.name == outgoing.name: - self.pop(ii) - break - - -class Nodeset(list): - - LINEAR, CUBIC = range(2) - - def __init__(self, name, nodes, method=None): - list.__init__(self, []) - self.name = name - if isinstance(nodes, str): - self.parse_raw(nodes) - else: - self.interpolation_method = method - self.parse_list(nodes) - self.set_splines() - - def parse_raw(self, raw): - raw = raw.strip() - if raw[0].upper() == "L": - self.set_interpolation_method(self.LINEAR, False) - else: - self.set_interpolation_method(self.CUBIC, False) - for node in raw[1:].strip().split(","): - self.add_node(map(float, node.strip().split()), False) - - def set_interpolation_method(self, method, refresh=True): - self.interpolation_method = method - if refresh: - self.set_splines() - - def add_node(self, coordinates, refresh=True): - x = coordinates[0] - inserted = False - index = 0 - for ii, node in enumerate(self): - if x < node.x: - self.insert(ii, Node(coordinates)) - inserted = True - index = ii - break - elif x == node.x: - return None - if not inserted: - self.append(Node(coordinates)) - index = len(self) - 1 - if refresh: - self.set_splines() - return index - - def parse_list(self, nodes): - for node in nodes: - self.add_node(node) - - def set_splines(self): - if self.interpolation_method == self.LINEAR: - self.set_linear_splines() - else: - self.set_cubic_splines() - - def set_linear_splines(self): - self.splines = splines = [] - for ii in xrange(len(self) - 1): - x1, y1, x2, y2 = self[ii] + self[ii + 1] - m = float(y2 - y1) / (x2 - x1) - splines.append(LinearSpline(x1, y1, m)) - - def set_cubic_splines(self): - n = len(self) - 1 - a = [node.y for node in self] - b = [None] * n - d = [None] * n - h = [self[ii + 1].x - self[ii].x for ii in xrange(n)] - alpha = [None] + [(3.0 / h[ii]) * (a[ii + 1] - a[ii]) - \ - (3.0 / h[ii - 1]) * (a[ii] - a[ii - 1]) \ - for ii in xrange(1, n)] - c = [None] * (n + 1) - l = [None] * (n + 1) - u = [None] * (n + 1) - z = [None] * (n + 1) - l[0] = 1 - u[0] = z[0] = 0 - for ii in xrange(1, n): - l[ii] = 2 * (self[ii + 1].x - self[ii - 1].x) - \ - h[ii - 1] * u[ii - 1] - u[ii] = h[ii] / l[ii] - z[ii] = (alpha[ii] - h[ii - 1] * z[ii - 1]) / l[ii] - l[n] = 1 - z[n] = c[n] = 0 - for jj in xrange(n - 1, -1, -1): - c[jj] = z[jj] - u[jj] * c[jj + 1] - b[jj] = (a[jj + 1] - a[jj]) / h[jj] - \ - (h[jj] * (c[jj + 1] + 2 * c[jj])) / 3 - d[jj] = (c[jj + 1] - c[jj]) / (3 * h[jj]) - self.splines = [CubicSpline(self[ii].x, a[ii], b[ii], c[ii], - d[ii]) for ii in xrange(n)] - - def get_y(self, t, loop=False, reverse=False, natural=False): - if loop or reverse: - if reverse and int(t) / int(self[-1].x) % 2: - t = self[-1].x - t - t %= self[-1].x - elif not natural: - if t < self[0].x: - t = self[0].x - elif t > self[-1].x: - t = self[-1].x - splines = self.splines - for ii in xrange(len(splines) - 1): - if t < splines[ii + 1].x: - return splines[ii].get_y(t) - return splines[-1].get_y(t) - - def remove(self, node, refresh=True): - list.remove(self, node) - if refresh: - self.set_splines() - - def resize(self, left, length, refresh=True): - old_left = self[0].x - old_length = self.get_length() - for node in self: - node.x = left + length * (node.x - old_left) / old_length - if refresh: - self.set_splines() - - def get_length(self): - return self[-1].x - self[0].x - - -class Node(list): - - def __init__(self, coordinates): - list.__init__(self, coordinates) - - def __getattr__(self, name): - if name == "x": - return self[0] - elif name == "y": - return self[1] - return list.__get__(self, name) - - def __setattr__(self, name, value): - if name == "x": - list.__setitem__(self, 0, value) - elif name == "y": - list.__setitem__(self, 1, value) - else: - list.__setattr__(self, name, value) - - -class Spline: - - def __init__(self, x): - self.x = x - - -class CubicSpline(Spline): - - def __init__(self, x, a, b, c, d): - Spline.__init__(self, x) - self.a = a - self.b = b - self.c = c - self.d = d - - def get_y(self, t): - x = self.x - return self.a + self.b * (t - x) + self.c * (t - x) ** 2 + self.d * \ - (t - x) ** 3 - - -class LinearSpline(Spline): - - def __init__(self, x, y, m): - Spline.__init__(self, x) - self.y = y - self.m = m - - def get_y(self, t): - return self.m * (t - self.x) + self.y - - -class GUI(Animation): - - B_DUPLICATE, B_WRITE, B_DELETE, B_LINEAR, B_CUBIC, B_SPLIT = range(6) - S_NONE, S_LEFT, S_RIGHT = range(3) - - def __init__(self, parent): - Animation.__init__(self, parent, unfiltered=True) - self.audio = self.get_audio() - self.display = self.get_game().display - self.display_surface = self.get_display_surface() - self.time_filter = self.get_game().time_filter - self.delegate = self.get_delegate() - self.split = self.S_NONE - self.success_indicator_active = True - self.success_indicator_blink_count = 0 - self.load_configuration() - self.font = Font(None, self.label_size) - self.prompt = Prompt(self) - self.set_temporary_file() - self.set_background() - self.set_success_indicator() - self.set_plot_rect() - self.set_marker_frame() - self.set_buttons() - self.active = False - self.set_nodeset_index() - self.set_y_range() - self.set_markers() - self.subscribe(self.respond_to_command) - self.subscribe(self.respond_to_mouse_down, MOUSEBUTTONDOWN) - self.subscribe(self.respond_to_key, KEYDOWN) - self.register(self.show_success_indicator, interval=100) - self.register(self.save_temporary_file, interval=10000) - self.play(self.save_temporary_file) - - def load_configuration(self): - config = self.get_configuration("interpolator-gui") - self.label_size = config["label-size"] - self.axis_label_count = config["axis-label-count"] - self.margin = config["margin"] - self.curve_color = config["curve-color"] - self.marker_size = config["marker-size"] - self.marker_color = config["marker-color"] - self.label_precision = config["label-precision"] - self.template_nodeset = config["template-nodeset"] - self.template_nodeset_name = config["template-nodeset-name"] - self.flat_y_range = config["flat-y-range"] - - def set_temporary_file(self): - self.temporary_file = open(join(gettempdir(), "pgfw-config"), "w") - - def set_background(self): - surface = Surface(self.display_surface.get_size()) - surface.fill((0, 0, 0)) - self.background = surface - - def set_success_indicator(self): - surface = Surface((10, 10)) - surface.fill((0, 255, 0)) - rect = surface.get_rect() - rect.topleft = self.display_surface.get_rect().topleft - self.success_indicator, self.success_indicator_rect = surface, rect - - def set_plot_rect(self): - margin = self.margin - self.plot_rect = self.display_surface.get_rect().inflate(-margin, - -margin) - - def set_marker_frame(self): - size = self.marker_size - surface = Surface((size, size)) - transparent_color = (255, 0, 255) - surface.fill(transparent_color) - surface.set_colorkey(transparent_color) - line_color = self.marker_color - aaline(surface, line_color, (0, 0), (size - 1, size - 1)) - aaline(surface, line_color, (0, size - 1), (size - 1, 0)) - self.marker_frame = surface - - def set_buttons(self): - self.buttons = buttons = [] - text = "Duplicate", "Write", "Delete", "Linear", "Cubic", "Split: No" - x = 0 - for instruction in text: - buttons.append(Button(self, instruction, x)) - x += buttons[-1].location.w + 10 - - def set_nodeset_index(self, increment=None, index=None): - parent = self.parent - if index is None: - if not increment: - index = 0 - else: - index = self.nodeset_index + increment - limit = len(parent) - 1 - if index > limit: - index = 0 - elif index < 0: - index = limit - self.nodeset_index = index - self.set_nodeset_label() - - def set_nodeset_label(self): - surface = self.font.render(self.get_nodeset().name, True, (0, 0, 0), - (255, 255, 255)) - rect = surface.get_rect() - rect.bottomright = self.display_surface.get_rect().bottomright - self.nodeset_label, self.nodeset_label_rect = surface, rect - - def get_nodeset(self): - if not len(self.parent): - self.parent.add_nodeset(self.template_nodeset_name, - self.template_nodeset) - self.set_nodeset_index(0) - return self.parent[self.nodeset_index] - - def set_y_range(self): - width = self.plot_rect.w - nodeset = self.get_nodeset() - self.y_range = y_range = [nodeset[0].y, nodeset[-1].y] - x = 0 - while x < width: - y = nodeset.get_y(self.get_function_coordinates(x)[0]) - if y < y_range[0]: - y_range[0] = y - elif y > y_range[1]: - y_range[1] = y - x += width * .01 - if y_range[1] - y_range[0] == 0: - y_range[1] += self.flat_y_range - if self.split: - self.adjust_for_split(y_range, nodeset) - self.set_axis_labels() - - def get_function_coordinates(self, xp=0, yp=0): - nodeset = self.get_nodeset() - x_min, x_max, (y_min, y_max) = nodeset[0].x, nodeset[-1].x, self.y_range - rect = self.plot_rect - x = float(xp) / (rect.right - rect.left) * (x_max - x_min) + x_min - y = float(yp) / (rect.bottom - rect.top) * (y_min - y_max) + y_max - return x, y - - def adjust_for_split(self, y_range, nodeset): - middle = nodeset[0].y if self.split == self.S_LEFT else nodeset[-1].y - below, above = middle - y_range[0], y_range[1] - middle - if below > above: - y_range[1] += below - above - else: - y_range[0] -= above - below - - def set_axis_labels(self): - self.axis_labels = labels = [] - nodeset, formatted, render, rect, yr = (self.get_nodeset(), - self.get_formatted_measure, - self.font.render, - self.plot_rect, self.y_range) - for ii, node in enumerate(nodeset[0::len(nodeset) - 1]): - xs = render(formatted(node.x), True, (0, 0, 0), (255, 255, 255)) - xsr = xs.get_rect() - xsr.top = rect.bottom - if not ii: - xsr.left = rect.left - else: - xsr.right = rect.right - ys = render(formatted(yr[ii]), True, (0, 0, 0), (255, 255, 255)) - ysr = ys.get_rect() - ysr.right = rect.left - if not ii: - ysr.bottom = rect.bottom - else: - ysr.top = rect.top - labels.append(((xs, xsr), (ys, ysr))) - - def get_formatted_measure(self, measure): - return "%s" % float(("%." + str(self.label_precision) + "g") % measure) - - def deactivate(self): - self.active = False - self.time_filter.open() - self.audio.muted = self.saved_mute_state - self.display.set_mouse_visibility(self.saved_mouse_state) - - def respond_to_command(self, event): - compare = self.delegate.compare - if compare(event, "toggle-interpolator"): - self.toggle() - elif self.active: - if compare(event, "reset-game"): - self.deactivate() - elif compare(event, "quit"): - self.get_game().end(event) - - def toggle(self): - if self.active: - self.deactivate() - else: - self.activate() - - def activate(self): - self.active = True - self.time_filter.close() - self.saved_mute_state = self.audio.muted - self.audio.mute() - self.draw() - self.saved_mouse_state = self.display.set_mouse_visibility(True) - - def respond_to_mouse_down(self, event): - redraw = False - if self.active and not self.prompt.active: - nodeset_rect = self.nodeset_label_rect - plot_rect = self.plot_rect - if event.button == 1: - pos = event.pos - if nodeset_rect.collidepoint(pos): - self.set_nodeset_index(1) - redraw = True - elif self.axis_labels[0][0][1].collidepoint(pos): - text = "{0} {1}".format(*map(self.get_formatted_measure, - self.get_nodeset()[0])) - self.prompt.activate(text, self.resize_nodeset, 0) - elif self.axis_labels[1][0][1].collidepoint(pos): - text = "{0} {1}".format(*map(self.get_formatted_measure, - self.get_nodeset()[-1])) - self.prompt.activate(text, self.resize_nodeset, -1) - else: - bi = self.collide_buttons(pos) - if bi is not None: - if bi == self.B_WRITE: - self.get_configuration().write() - self.play(self.show_success_indicator) - elif bi in (self.B_LINEAR, self.B_CUBIC): - nodeset = self.get_nodeset() - if bi == self.B_LINEAR: - nodeset.set_interpolation_method(Nodeset.LINEAR) - else: - nodeset.set_interpolation_method(Nodeset.CUBIC) - self.store_in_configuration() - redraw = True - elif bi == self.B_DUPLICATE: - self.prompt.activate("", self.add_nodeset) - elif bi == self.B_DELETE and len(self.parent) > 1: - self.parent.remove(self.get_nodeset()) - self.set_nodeset_index(1) - self.store_in_configuration() - redraw = True - elif bi == self.B_SPLIT: - self.toggle_split() - redraw = True - elif plot_rect.collidepoint(pos) and \ - not self.collide_markers(pos): - xp, yp = pos[0] - plot_rect.left, pos[1] - plot_rect.top - self.get_nodeset().add_node( - self.get_function_coordinates(xp, yp)) - self.store_in_configuration() - redraw = True - elif event.button == 3: - pos = event.pos - if nodeset_rect.collidepoint(pos): - self.set_nodeset_index(-1) - redraw = True - elif plot_rect.collidepoint(pos): - marker = self.collide_markers(pos) - if marker: - self.get_nodeset().remove(marker.node) - self.store_in_configuration() - redraw = True - elif self.active and self.prompt.active and \ - not self.prompt.rect.collidepoint(event.pos): - self.prompt.deactivate() - redraw = True - if redraw: - self.set_y_range() - self.set_markers() - self.draw() - - def resize_nodeset(self, text, index): - result = match("^\s*(-{,1}\d*\.{,1}\d*)\s+(-{,1}\d*\.{,1}\d*)\s*$", - text) - if result: - try: - nodeset = self.get_nodeset() - x, y = map(float, result.group(1, 2)) - if (index == -1 and x > nodeset[0].x) or \ - (index == 0 and x < nodeset[-1].x): - nodeset[index].y = y - if index == -1: - nodeset.resize(nodeset[0].x, x - nodeset[0].x) - else: - nodeset.resize(x, nodeset[-1].x - x) - self.store_in_configuration() - self.set_y_range() - self.set_axis_labels() - self.set_markers() - self.draw() - return True - except ValueError: - return False - - def collide_buttons(self, pos): - for ii, button in enumerate(self.buttons): - if button.location.collidepoint(pos): - return ii - - def store_in_configuration(self): - config = self.get_configuration() - section = "interpolate" - config.clear_section(section) - for nodeset in self.parent: - code = "L" if nodeset.interpolation_method == Nodeset.LINEAR else \ - "C" - for ii, node in enumerate(nodeset): - if ii > 0: - code += "," - code += " {0} {1}".format(*map(self.get_formatted_measure, - node)) - if not config.has_section(section): - config.add_section(section) - config.set(section, nodeset.name, code) - - def toggle_split(self): - self.split += 1 - if self.split > self.S_RIGHT: - self.split = self.S_NONE - self.buttons[self.B_SPLIT].set_frame(["Split: No", "Split: L", - "Split: R"][self.split]) - - def add_nodeset(self, name): - nodeset = self.get_nodeset() - self.set_nodeset_index(index=self.parent.add_nodeset(\ - name, nodeset, nodeset.interpolation_method)) - self.store_in_configuration() - self.draw() - return True - - def collide_markers(self, pos): - for marker in self.markers: - if marker.location.collidepoint(pos): - return marker - - def set_markers(self): - self.markers = markers = [] - for node in self.get_nodeset()[1:-1]: - markers.append(Marker(self, node)) - markers[-1].location.center = self.get_plot_coordinates(*node) - - def get_plot_coordinates(self, x=0, y=0): - nodeset = self.get_nodeset() - x_min, x_max, (y_min, y_max) = nodeset[0].x, nodeset[-1].x, self.y_range - x_ratio = float(x - x_min) / (x_max - x_min) - rect = self.plot_rect - xp = x_ratio * (rect.right - rect.left) + rect.left - y_ratio = float(y - y_min) / (y_max - y_min) - yp = rect.bottom - y_ratio * (rect.bottom - rect.top) - return xp, yp - - def draw(self): - display_surface = self.display_surface - display_surface.blit(self.background, (0, 0)) - display_surface.blit(self.nodeset_label, self.nodeset_label_rect) - self.draw_axes() - self.draw_function() - self.draw_markers() - self.draw_buttons() - - def draw_axes(self): - display_surface = self.display_surface - for xl, yl in self.axis_labels: - display_surface.blit(*xl) - display_surface.blit(*yl) - - def draw_function(self): - rect = self.plot_rect - surface = self.display_surface - nodeset = self.get_nodeset() - step = 1 - for x in xrange(rect.left, rect.right + step, step): - ii = x - rect.left - fx = nodeset.get_y(self.get_function_coordinates(ii)[0]) - y = self.get_plot_coordinates(y=fx)[1] - if ii > 0: - aaline(surface, self.curve_color, (x - step, last_y), (x, y)) - last_y = y - - def draw_markers(self): - for marker in self.markers: - marker.update() - - def draw_buttons(self): - for button in self.buttons: - button.update() - - def respond_to_key(self, event): - if self.prompt.active: - prompt = self.prompt - if event.key == K_RETURN: - if prompt.callback[0](prompt.text, *prompt.callback[1]): - prompt.deactivate() - elif event.key == K_BACKSPACE: - prompt.text = prompt.text[:-1] - prompt.update() - prompt.draw_text() - elif (event.unicode.isalnum() or event.unicode.isspace() or \ - event.unicode in (".", "-", "_")) and len(prompt.text) < \ - prompt.character_limit: - prompt.text += event.unicode - prompt.update() - prompt.draw_text() - - def show_success_indicator(self): - self.draw() - if self.success_indicator_blink_count > 1: - self.success_indicator_blink_count = 0 - self.halt(self.show_success_indicator) - else: - if self.success_indicator_active: - self.display_surface.blit(self.success_indicator, - self.success_indicator_rect) - if self.success_indicator_active: - self.success_indicator_blink_count += 1 - self.success_indicator_active = not self.success_indicator_active - - def save_temporary_file(self): - fp = self.temporary_file - fp.seek(0) - fp.truncate() - self.get_configuration().write(fp) - - def rearrange(self): - self.set_background() - self.set_success_indicator() - self.set_plot_rect() - self.set_markers() - self.set_nodeset_label() - self.set_axis_labels() - self.set_buttons() - self.prompt.reset() - -class Marker(Sprite): - - def __init__(self, parent, node): - Sprite.__init__(self, parent) - self.add_frame(parent.marker_frame) - self.node = node - - -class Button(Sprite): - - def __init__(self, parent, text, left): - Sprite.__init__(self, parent) - self.set_frame(text) - self.location.bottomleft = left, \ - self.get_display_surface().get_rect().bottom - - def set_frame(self, text): - self.clear_frames() - self.add_frame(self.parent.font.render(text, True, (0, 0, 0), - (255, 255, 255))) - - -class Prompt(Sprite): - - def __init__(self, parent): - Sprite.__init__(self, parent) - self.load_configuration() - self.font = Font(None, self.text_size) - self.reset() - self.deactivate() - - def deactivate(self): - self.active = False - - def load_configuration(self): - config = self.get_configuration("interpolator-gui") - self.size = config["prompt-size"] - self.border_color = config["prompt-border-color"] - self.border_width = config["prompt-border-width"] - self.character_limit = config["prompt-character-limit"] - self.text_size = config["prompt-text-size"] - - def reset(self): - self.set_frame() - self.place() - - def set_frame(self): - self.clear_frames() - surface = Surface(self.size) - self.add_frame(surface) - surface.fill(self.border_color) - width = self.border_width * 2 - surface.fill((0, 0, 0), surface.get_rect().inflate(-width, -width)) - - def place(self): - self.location.center = self.display_surface.get_rect().center - - def activate(self, text, callback, *args): - self.active = True - self.text = str(text) - self.callback = callback, args - self.update() - self.draw_text() - - def draw_text(self): - surface = self.font.render(self.text, True, (255, 255, 255), (0, 0, 0)) - rect = surface.get_rect() - rect.center = self.location.center - self.display_surface.blit(surface, rect) diff --git a/electric_sieve/pgfw/Mainloop.py b/electric_sieve/pgfw/Mainloop.py deleted file mode 100644 index 419a966..0000000 --- a/electric_sieve/pgfw/Mainloop.py +++ /dev/null @@ -1,108 +0,0 @@ -from pygame import display -from pygame.font import Font -from pygame.time import get_ticks, wait - -from GameChild import GameChild - -class Mainloop(GameChild): - - def __init__(self, parent): - GameChild.__init__(self, parent) - self.overflow = 0 - self.frame_count = 1 - self.actual_frame_duration = 0 - self.frames_this_second = 0 - self.last_framerate_display = 0 - self.load_configuration() - self.init_framerate_display() - self.last_ticks = get_ticks() - self.stopping = False - - def load_configuration(self): - config = self.get_configuration("display") - self.target_frame_duration = config["frame-duration"] - self.wait_duration = config["wait-duration"] - self.skip_frames = config["skip-frames"] - self.show_framerate = config["show-framerate"] - self.framerate_text_size = config["framerate-text-size"] - self.framerate_text_color = config["framerate-text-color"] - self.framerate_text_background = config["framerate-text-background"] - self.framerate_display_flag = config["framerate-display-flag"] - - def init_framerate_display(self): - if self.framerate_display_active(): - screen = self.get_screen() - self.last_framerate_count = 0 - self.framerate_topright = screen.get_rect().topright - self.display_surface = screen - self.font = Font(None, self.framerate_text_size) - self.font.set_bold(True) - self.render_framerate() - - def framerate_display_active(self): - return self.check_command_line(self.framerate_display_flag) or \ - self.show_framerate - - def render_framerate(self): - text = self.font.render(str(self.last_framerate_count), False, - self.framerate_text_color, - self.framerate_text_background) - rect = text.get_rect() - rect.topright = self.framerate_topright - self.framerate_text = text - self.framerate_text_rect = rect - - def run(self): - while not self.stopping: - self.advance_frame() - self.update_frame_duration() - self.update_overflow() - self.stopping = False - - def advance_frame(self): - refresh = False - while self.frame_count > 0: - refresh = True - self.parent.frame() - if self.framerate_display_active(): - self.update_framerate() - self.frame_count -= 1 - if not self.skip_frames: - break - if refresh: - display.update() - - def update_frame_duration(self): - last_ticks = self.last_ticks - actual_frame_duration = get_ticks() - last_ticks - last_ticks = get_ticks() - while actual_frame_duration < self.target_frame_duration: - wait(self.wait_duration) - actual_frame_duration += get_ticks() - last_ticks - last_ticks = get_ticks() - self.actual_frame_duration = actual_frame_duration - self.last_ticks = last_ticks - - def update_overflow(self): - self.frame_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.frame_count += 1 - overflow -= target_frame_duration - overflow = self.overflow - - def update_framerate(self): - count = self.frames_this_second + 1 - if get_ticks() - self.last_framerate_display > 1000: - if count != self.last_framerate_count: - self.last_framerate_count = count - self.render_framerate() - self.last_framerate_display = get_ticks() - count = 0 - self.display_surface.blit(self.framerate_text, self.framerate_text_rect) - self.frames_this_second = count - - def stop(self): - self.stopping = True diff --git a/electric_sieve/pgfw/Profile.py b/electric_sieve/pgfw/Profile.py deleted file mode 100644 index 87a74d2..0000000 --- a/electric_sieve/pgfw/Profile.py +++ /dev/null @@ -1,26 +0,0 @@ -import cProfile -from time import strftime -from os import mkdir -from os.path import join, exists - -from GameChild import GameChild - -class Profile(cProfile.Profile, GameChild): - - def __init__(self, parent): - GameChild.__init__(self, parent) - cProfile.Profile.__init__(self) - if self.requested(): - self.enable() - - def requested(self): - return self.check_command_line("p") - - def end(self): - if self.requested(): - root = "stat/" - if not exists(root): - mkdir(root) - self.disable() - self.create_stats() - self.dump_stats(join(root, strftime("%Y%m%d-%H%M_%S.stat"))) diff --git a/electric_sieve/pgfw/ScreenGrabber.py b/electric_sieve/pgfw/ScreenGrabber.py deleted file mode 100644 index 2058683..0000000 --- a/electric_sieve/pgfw/ScreenGrabber.py +++ /dev/null @@ -1,41 +0,0 @@ -from os import makedirs -from os.path import exists, join -from sys import exc_info -from time import strftime - -from pygame import image - -from GameChild import * -from Input import * - -class ScreenGrabber(GameChild): - - def __init__(self, game): - GameChild.__init__(self, game) - self.delegate = self.get_delegate() - self.load_configuration() - self.subscribe(self.save_display) - - def load_configuration(self): - config = self.get_configuration("screen-captures") - self.save_path = config["path"] - self.file_name_format = config["file-name-format"] - self.file_extension = config["file-extension"] - - def save_display(self, event): - if self.delegate.compare(event, "capture-screen"): - directory = self.save_path - try: - if not exists(directory): - makedirs(directory) - name = self.build_name() - path = join(directory, name) - capture = image.save(self.get_screen(), path) - self.print_debug("Saved screen capture to %s" % (path)) - except: - self.print_debug("Couldn't save screen capture to %s, %s" %\ - (directory, exc_info()[1])) - - def build_name(self): - return "{0}.{1}".format(strftime(self.file_name_format), - self.file_extension) diff --git a/electric_sieve/pgfw/Setup.py b/electric_sieve/pgfw/Setup.py deleted file mode 100644 index 04cf753..0000000 --- a/electric_sieve/pgfw/Setup.py +++ /dev/null @@ -1,131 +0,0 @@ -from os import walk, remove -from os.path import sep, join, exists, normpath -from re import findall, sub -from distutils.core import setup -from distutils.command.install import install -from pprint import pprint -from fileinput import FileInput -from re import sub, match - -from Configuration import * - -class Setup: - - config = Configuration() - manifest_path = "MANIFEST" - - def __init__(self): - pass - - def remove_old_mainfest(self): - path = self.manifest_path - if exists(path): - remove(path) - - def build_package_list(self): - packages = [] - config = self.config.get_section("setup") - locations = [config["package-root"]] + config["additional-packages"] - for location in locations: - if exists(location): - for root, dirs, files in walk(location, followlinks=True): - packages.append(root.replace(sep, ".")) - return packages - - def build_data_map(self): - include = [] - config = self.config.get_section("setup") - exclude = map(normpath, config["data-exclude"]) - for root, dirs, files in walk("."): - dirs = self.remove_excluded(dirs, root, exclude) - files = [join(root, f) for f in self.remove_excluded(files, root, - exclude)] - if files: - include.append((normpath(join(config["installation-path"], - root)), files)) - return include - - def remove_excluded(self, paths, root, exclude): - removal = [] - for path in paths: - if normpath(join(root, path)) in exclude: - removal.append(path) - for path in removal: - paths.remove(path) - return paths - - def translate_title(self): - config = self.config.get_section("setup") - title = config["title"].replace(" ", config["whitespace-placeholder"]) - return sub("[^\w-]", config["special-char-placeholder"], title) - - def build_description(self): - description = "" - path = self.config.get("setup", "description-file") - if exists(path): - description = "\n%s\n%s\n%s" % (file(path).read(), - "Changelog\n=========", - self.translate_changelog()) - return description - - def translate_changelog(self): - translation = "" - path = self.config.get("setup", "changelog") - if exists(path): - lines = file(path).readlines() - package_name = lines[0].split()[0] - for line in lines: - line = line.strip() - if line.startswith(package_name): - version = findall("\((.*)\)", line)[0] - translation += "\n%s\n%s\n" % (version, "-" * len(version)) - elif line and not line.startswith("--"): - if line.startswith("*"): - translation += line + "\n" - else: - translation += " " + line + "\n" - return translation - - def setup(self, windows=[], options={}): - print "running setup..." - self.remove_old_mainfest() - config = self.config.get_section("setup") - scripts = [] - if config["init-script"]: - scripts.append(config["init-script"]) - setup(cmdclass={"install": insert_resource_path}, - name=self.translate_title(), - packages=self.build_package_list(), - scripts=scripts, - data_files=self.build_data_map(), - requires=config["requirements"], - version=config["version"], - description=config["summary"], - classifiers=config["classifiers"], - long_description=self.build_description(), - license=config["license"], - platforms=config["platforms"], - author=config["contact-name"], - author_email=config["contact-email"], - url=config["url"], - windows=windows, - options=options) - - -class insert_resource_path(install): - - def run(self): - install.run(self) - self.edit_game_object_file() - - def edit_game_object_file(self): - config = Configuration().get_section("setup") - for path in self.get_outputs(): - if path.endswith(config["main-object"]): - for line in FileInput(path, inplace=True): - pattern = "^ *{0} *=.*".\ - format(config["resource-path-identifier"]) - if match(pattern, line): - line = sub("=.*$", "= \"{0}\"".\ - format(config["installation-path"]), line) - print line.strip("\n") diff --git a/electric_sieve/pgfw/SetupWin.py b/electric_sieve/pgfw/SetupWin.py deleted file mode 100644 index 232322b..0000000 --- a/electric_sieve/pgfw/SetupWin.py +++ /dev/null @@ -1,69 +0,0 @@ -from os import makedirs, walk, sep, remove -from os.path import join, dirname, basename, exists -from shutil import rmtree, copy, rmtree -from itertools import chain -from zipfile import ZipFile - -import py2exe - -from Setup import Setup - -class SetupWin(Setup): - - def __init__(self): - Setup.__init__(self) - self.replace_isSystemDLL() - - def replace_isSystemDLL(self): - origIsSystemDLL = py2exe.build_exe.isSystemDLL - def isSystemDLL(pathname): - if basename(pathname).lower() in ("libogg-0.dll", "sdl_ttf.dll"): - return 0 - return origIsSystemDLL(pathname) - py2exe.build_exe.isSystemDLL = isSystemDLL - - def setup(self): - config = self.config.get_section("setup") - windows = [{}] - if config["init-script"]: - windows[0]["script"] = config["init-script"] - if config["windows-icon-path"]: - windows[0]["icon-resources"] = [(1, config["windows-icon-path"])] - Setup.setup(self, windows, - {"py2exe": {"packages": self.build_package_list(), - "dist_dir": config["windows-dist-path"]}}) - rmtree("build") - self.copy_data_files() - self.create_archive() - - def copy_data_files(self): - root = self.config.get("setup", "windows-dist-path") - for path in chain(*zip(*self.build_data_map())[1]): - dest = join(root, dirname(path)) - if not exists(dest): - makedirs(dest) - copy(path, dest) - self.include_readme(root) - - def include_readme(self, root): - name = "README" - if exists(name): - readme = open(name, "r") - reformatted = open(join(root, name + ".txt"), "w") - for line in open(name, "r"): - reformatted.write(line.rstrip() + "\r\n") - - def create_archive(self): - config = self.config.get_section("setup") - title = self.translate_title() + "-" + config["version"] + "-win" - archive_name = title + ".zip" - archive = ZipFile(archive_name, "w") - destination = config["windows-dist-path"] - for root, dirs, names in walk(destination): - for name in names: - path = join(root, name) - archive.write(path, path.replace(destination, title + sep)) - archive.close() - copy(archive_name, "dist") - remove(archive_name) - rmtree(destination) diff --git a/electric_sieve/pgfw/Sprite.py b/electric_sieve/pgfw/Sprite.py deleted file mode 100644 index 1df6bd1..0000000 --- a/electric_sieve/pgfw/Sprite.py +++ /dev/null @@ -1,359 +0,0 @@ -from os import listdir -from os.path import isfile, join -from sys import exc_info, stdout -from glob import glob -from traceback import print_exc, print_stack - -from pygame import Color, Rect, Surface -from pygame.image import load -from pygame.transform import flip -from pygame.locals import * - -from Animation import Animation -from Vector import Vector - -class Sprite(Animation): - - def __init__(self, parent, framerate=None): - Animation.__init__(self, parent, self.shift_frame, framerate) - self.frames = [] - self.mirrored = False - self.hidden = False - self.alpha = 255 - self.locations = [Location(self)] - self.framesets = [Frameset(self, framerate=framerate)] - self.set_frameset(0) - self.motion_overflow = Vector() - self.display_surface = self.get_display_surface() - - def __getattr__(self, name): - if name in ("location", "rect"): - return self.locations[0] - if hasattr(Animation, "__getattr__"): - return Animation.__getattr__(self, name) - raise AttributeError, name - - def set_frameset(self, identifier): - if isinstance(identifier, str): - for ii, frameset in enumerate(self.framesets): - if frameset.name == identifier: - identifier = ii - break - self.frameset_index = identifier - self.register_interval() - self.update_location_size() - if self.get_current_frameset().length() > 1: - self.play() - - def register_interval(self): - self.register(self.shift_frame, - interval=self.get_current_frameset().framerate) - - def get_current_frameset(self): - return self.framesets[self.frameset_index] - - def update_location_size(self): - size = self.get_current_frameset().rect.size - for location in self.locations: - location.size = size - location.fader.init_surface() - - def set_framerate(self, framerate): - self.get_current_frameset().set_framerate(framerate) - self.register_interval() - - def load_from_path(self, path, transparency=False, ppa=True, key=None, - extension=None, omit=False): - if isfile(path): - paths = [path] - else: - if extension: - paths = sorted(glob(join(path, "*." + extension))) - else: - paths = [join(path, name) for name in sorted(listdir(path))] - for path in paths: - img = load(path) - if transparency: - if ppa: - frame = img.convert_alpha() - else: - frame = self.fill_colorkey(img, key) - else: - frame = img.convert() - self.add_frame(frame, omit) - - def fill_colorkey(self, img, key=None): - if not key: - key = (255, 0, 255) - img = img.convert_alpha() - frame = Surface(img.get_size()) - frame.fill(key) - frame.set_colorkey(key) - frame.blit(img, (0, 0)) - return frame - - def add_frame(self, frame, omit=False): - self.frames.append(frame) - frame.set_alpha(self.alpha) - if not omit: - frameset = self.get_current_frameset() - frameset.add_index(self.frames.index(frame)) - self.update_location_size() - if frameset.length() > 1: - self.play() - - def shift_frame(self): - self.get_current_frameset().shift() - - def get_current_frame(self): - return self.frames[self.get_current_frameset().get_current_id()] - - def move(self, dx=0, dy=0): - for location in self.locations: - location.move_ip(dx, dy) - - def reset_motion_overflow(self): - for location in self.locations: - location.reset_motion_overflow() - - def collide(self, other): - if not isinstance(other, Rect): - other = other.rect - for location in self.locations: - if location.colliderect(other): - return location - - def mirror(self): - frames = self.frames - for ii, frame in enumerate(frames): - frames[ii] = flip(frame, True, False) - self.mirrored = not self.mirrored - - def clear_frames(self): - self.frames = [] - for frameset in self.framesets: - frameset.order = [] - frameset.reset() - frameset.measure_rect() - - def add_location(self, topleft=None, offset=(0, 0), count=1, base=0): - if topleft is not None: - for ii in xrange(count): - self.locations.append(Location( - self, Rect(topleft, self.locations[0].size))) - else: - base = self.locations[base] - current_offset = list(offset) - for ii in xrange(count): - self.locations.append(Location(self, - base.move(*current_offset))) - current_offset[0] += offset[0] - current_offset[1] += offset[1] - return self.locations[-1] - - def fade(self, length=0, out=None, index=None): - if index is None: - for location in self.locations: - location.fader.start(length, out) - else: - self.locations[index].fader.start(length, out) - - def set_alpha(self, alpha): - self.alpha = alpha - for frame in self.frames: - frame.set_alpha(alpha) - for location in self.locations: - location.fader.set_alpha() - - def add_frameset(self, order, framerate=None, name=None): - frameset = Frameset(self, order, framerate, name) - self.framesets.append(frameset) - return frameset - - def hide(self): - self.hidden = True - - def unhide(self): - self.hidden = False - - def remove_locations(self, location=None): - if location: - self.locations.remove(location) - else: - self.locations = self.locations[:1] - - def reverse(self, frameset=None): - if frameset: - frameset.reverse() - else: - for frameset in self.framesets: - frameset.reverse() - - def update(self, flags=0): - Animation.update(self) - self.draw(flags) - - def draw(self, flags=0): - for location in self.locations: - location.fader.draw(flags) - - -class Location(Rect): - - def __init__(self, sprite, rect=(0, 0, 0, 0)): - self.sprite = sprite - Rect.__init__(self, rect) - self.motion_overflow = Vector() - self.fader = Fader(self) - - def move_ip(self, dx, dy): - if isinstance(dx, float) or isinstance(dy, float): - excess = self.update_motion_overflow(dx, dy) - Rect.move_ip(self, int(dx) + excess[0], int(dy) + excess[1]) - else: - Rect.move_ip(self, dx, dy) - - def update_motion_overflow(self, dx, dy): - overflow = self.motion_overflow - overflow.move(dx - int(dx), dy - int(dy)) - excess = map(int, overflow) - overflow[0] -= int(overflow[0]) - overflow[1] -= int(overflow[1]) - return excess - - def reset_motion_overflow(self): - self.motion_overflow.place_at_origin() - - -class Fader(Surface): - - def __init__(self, location): - self.location = location - self.time_filter = location.sprite.get_game().time_filter - self.reset() - - def reset(self): - self.init_surface() - self.fade_remaining = None - - def init_surface(self): - Surface.__init__(self, self.location.size) - if self.location.sprite.frames: - background = Surface(self.get_size()) - sprite = self.location.sprite - key = sprite.get_current_frame().get_colorkey() or (255, 0, 255) - self.set_colorkey(key) - background.fill(key) - self.background = background - self.set_alpha() - - def set_alpha(self, alpha=None): - if alpha is None: - alpha = self.location.sprite.alpha - Surface.set_alpha(self, alpha) - - def start(self, length, out=None): - if self.fade_remaining <= 0: - alpha = self.get_alpha() - maximum = self.location.sprite.alpha - if out is None: - out = alpha == maximum - if out and alpha > 0 or not out and alpha < maximum: - self.fade_length = self.fade_remaining = length - self.start_time = self.time_filter.get_ticks() - self.fading_out = out - - def draw(self, flags): - sprite = self.location.sprite - if self.fade_remaining >= 0: - self.update_alpha() - self.clear() - frame = sprite.get_current_frame() - frame.set_alpha(255) - self.blit(frame, (0, 0)) - frame.set_alpha(sprite.alpha) - if not sprite.hidden: - self.blit_to_display(self, flags) - elif self.fade_remaining is None or self.get_alpha() >= sprite.alpha: - if self.fade_remaining >= 0: - self.update_alpha() - if not sprite.hidden: - self.blit_to_display(sprite.get_current_frame(), flags) - - def blit_to_display(self, frame, flags): - self.location.sprite.display_surface.blit(frame, self.location, None, - flags) - - def update_alpha(self): - remaining = self.fade_remaining = self.fade_length - \ - (self.time_filter.get_ticks() - self.start_time) - ratio = self.fade_length and float(remaining) / self.fade_length - if not self.fading_out: - ratio = 1 - ratio - maximum = self.location.sprite.alpha - alpha = int(ratio * maximum) - if alpha > maximum: - alpha = maximum - elif alpha < 0: - alpha = 0 - self.set_alpha(alpha) - - def clear(self): - self.blit(self.background, (0, 0)) - - -class Frameset(): - - def __init__(self, sprite, order=[], framerate=None, name=None): - self.sprite = sprite - self.name = name - self.reversed = False - self.order = [] - self.rect = Rect(0, 0, 0, 0) - self.add_index(order) - self.set_framerate(framerate) - self.reset() - - def add_index(self, order): - if isinstance(order, int): - order = [order] - self.order += order - self.measure_rect() - - def set_framerate(self, framerate): - self.framerate = framerate - - def reset(self): - self.current_index = 0 - - def get_current_id(self): - return self.order[self.current_index] - - def measure_rect(self): - max_width, max_height = 0, 0 - frames = self.sprite.frames - for index in self.order: - frame = frames[index] - width, height = frame.get_size() - max_width = max(width, max_width) - max_height = max(height, max_height) - self.rect.size = max_width, max_height - - def shift(self): - if len(self.order) > 1: - self.increment_index() - - def increment_index(self): - increment = 1 if not self.reversed else -1 - index = self.current_index + increment - if index < 0: - index = self.length() - 1 - elif index >= self.length(): - index = 0 - self.current_index = index - - def length(self): - return len(self.order) - - def reverse(self): - self.reversed = not self.reversed diff --git a/electric_sieve/pgfw/TimeFilter.py b/electric_sieve/pgfw/TimeFilter.py deleted file mode 100644 index e57e3c1..0000000 --- a/electric_sieve/pgfw/TimeFilter.py +++ /dev/null @@ -1,36 +0,0 @@ -from pygame.time import get_ticks - -from GameChild import GameChild - -class TimeFilter(GameChild): - - def __init__(self, parent): - GameChild.__init__(self, parent) - self.ticks = self.unfiltered_ticks = self.last_ticks = get_ticks() - self.open() - - def close(self): - self.closed = True - - def open(self): - self.closed = False - - def get_ticks(self): - return self.ticks - - def get_unfiltered_ticks(self): - return self.unfiltered_ticks - - def get_last_ticks(self): - return self.last_ticks - - def get_last_frame_duration(self): - return self.last_frame_duration - - def update(self): - ticks = get_ticks() - self.last_frame_duration = duration = ticks - self.last_ticks - if not self.closed: - self.ticks += duration - self.unfiltered_ticks += duration - self.last_ticks = ticks diff --git a/electric_sieve/pgfw/Vector.py b/electric_sieve/pgfw/Vector.py deleted file mode 100644 index 819e847..0000000 --- a/electric_sieve/pgfw/Vector.py +++ /dev/null @@ -1,69 +0,0 @@ -class Vector(list): - - def __init__(self, x=0, y=0): - list.__init__(self, (x, y)) - - def __getattr__(self, name): - if name == "x": - return self[0] - elif name == "y": - return self[1] - - def __setattr__(self, name, value): - if name == "x": - self[0] = value - elif name == "y": - self[1] = value - else: - list.__setattr__(self, name, value) - - def __add__(self, other): - return Vector(self.x + other[0], self.y + other[1]) - - __radd__ = __add__ - - def __iadd__(self, other): - self.x += other[0] - self.y += other[1] - return self - - def __sub__(self, other): - return Vector(self.x - other[0], self.y - other[1]) - - def __rsub__(self, other): - return Vector(other[0] - self.x, other[1] - self.y) - - def __isub__(self, other): - self.x -= other[0] - self.y -= other[1] - return self - - def __mul__(self, other): - return Vector(self.x * other, self.y * other) - - __rmul__ = __mul__ - - def __imul__(self, other): - self.x *= other - self.y *= other - return self - - def apply_to_components(self, function): - self.x = function(self.x) - self.y = function(self.y) - - def place(self, x=None, y=None): - if x is not None: - self.x = x - if y is not None: - self.y = y - - def move(self, dx=0, dy=0): - if dx: - self.x += dx - if dy: - self.y += dy - - def place_at_origin(self): - self.x = 0 - self.y = 0 diff --git a/electric_sieve/pgfw/VideoRecorder.py b/electric_sieve/pgfw/VideoRecorder.py deleted file mode 100644 index 2aba53c..0000000 --- a/electric_sieve/pgfw/VideoRecorder.py +++ /dev/null @@ -1,71 +0,0 @@ -from os import makedirs -from os.path import exists, join -from tempfile import TemporaryFile -from time import strftime - -from pygame.image import tostring, frombuffer, save -from pygame.time import get_ticks - -from GameChild import GameChild - -class VideoRecorder(GameChild): - - def __init__(self, parent): - GameChild.__init__(self, parent) - self.display_surface = self.get_display_surface() - self.delegate = self.get_delegate() - self.load_configuration() - self.reset() - self.subscribe(self.respond) - - def load_configuration(self): - config = self.get_configuration("video-recordings") - self.root = config["path"] - self.directory_name_format = config["directory-name-format"] - self.file_extension = config["file-extension"] - self.frame_format = config["frame-format"] - self.framerate = config["framerate"] - - def reset(self): - self.recording = False - self.frame_length = None - self.frames = None - self.last_frame = 0 - - def respond(self, event): - compare = self.delegate.compare - if compare(event, "record-video"): - self.toggle_record() - elif compare(event, "reset-game"): - self.reset() - - def toggle_record(self): - recording = not self.recording - if recording: - self.frame_length = len(self.get_string()) - self.frames = TemporaryFile() - else: - self.write_frames() - self.recording = recording - - def get_string(self): - return tostring(self.display_surface, self.frame_format) - - def write_frames(self): - root = join(self.root, strftime(self.directory_name_format)) - if not exists(root): - makedirs(root) - size = self.display_surface.get_size() - frames = self.frames - frames.seek(0) - for ii, frame in enumerate(iter(lambda: frames.read(self.frame_length), - "")): - path = join(root, "%04i.png" % ii) - save(frombuffer(frame, size, self.frame_format), path) - print "wrote video frames to " + root - - def update(self): - ticks = get_ticks() - if self.recording and ticks - self.last_frame >= self.framerate: - self.frames.write(self.get_string()) - self.last_frame = ticks diff --git a/electric_sieve/pgfw/__init__.py b/lib/__init__.py similarity index 100% rename from electric_sieve/pgfw/__init__.py rename to lib/__init__.py diff --git a/lib/pgfw b/lib/pgfw new file mode 160000 index 0000000..a0aba9a --- /dev/null +++ b/lib/pgfw @@ -0,0 +1 @@ +Subproject commit a0aba9a0bb527ec7f3d7269cdd522448560a99c3 diff --git a/resource/font/terminus/Terminus-Bold.ttf b/resource/font/terminus/Terminus-Bold.ttf new file mode 100644 index 0000000..06700de Binary files /dev/null and b/resource/font/terminus/Terminus-Bold.ttf differ diff --git a/resource/font/terminus/Terminus-Italic.ttf b/resource/font/terminus/Terminus-Italic.ttf new file mode 100644 index 0000000..e80d0c0 Binary files /dev/null and b/resource/font/terminus/Terminus-Italic.ttf differ diff --git a/resource/font/terminus/Terminus.ttf b/resource/font/terminus/Terminus.ttf new file mode 100644 index 0000000..f4bb6b2 Binary files /dev/null and b/resource/font/terminus/Terminus.ttf differ diff --git a/resource/high-scores b/resource/high-scores index 09db111..c5c40c1 100644 --- a/resource/high-scores +++ b/resource/high-scores @@ -1,20 +1,8 @@ -1398631170.296798 200 -1398631170.296798 100 -1398631170.296798 40 -1398635621.7 158 -1398635792.99 154 -1398636058.07 180 -1398636195.37 232 -1398636310.09 131 -1398636404.1 120 -1398636488.41 165 -1398636581.89 173 -1398636667.8 186 -1398647055.97 78 -1398647195.17 187 -1398647939.59 155 -1398648230.57 88 -1436645313.22 196 -1436645428.32 246 -1436645528.27 193 -1437504178.89 165 +1398631170.296798 100 SIV +1398631170.296798 70 SIV +1398631170.296798 45 SIV +1398635621.7 25 SIV +1398635792.99 10 SIV +1437514837.26 206 SIV +1437514932.23 22 SIV +1437514988.25 88 SIV