score box
parent
c5e62360a4
commit
539e61c054
@ -0,0 +1,3 @@
|
||||
[submodule "lib/pgfw"]
|
||||
path = lib/pgfw
|
||||
url = makar:/var/www/git/pgfw
|
@ -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.
|
@ -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
|
@ -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()
|
@ -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)
|
@ -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))
|
@ -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))
|
@ -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()
|
@ -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)
|
@ -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 |