interpolator; cubic splines; sprite hide; write user config

This commit is contained in:
Frank DeMarco 2014-01-13 01:07:39 +09:00
parent b325cbaada
commit 206caee387
5 changed files with 179 additions and 13 deletions

17
README
View File

@ -6,11 +6,10 @@ Classes to facilitate creation of Pygame projects
Example
=======
-------
Save and run the following script to create a project that redraws a square at a
random location every second. This script is also written in the `sample.py`
file.
Save and run to create a project that redraws a square at a random location
every second. This script is also written in the `sample.py` file.
from time import sleep
from random import randint
@ -21,7 +20,7 @@ class SampleGame(Game):
square_width = 30
# update is a special method that runs once every frame
# instructions in the update method automatically run once every frame
def update(self):
sleep(1)
screen = self.get_screen()
@ -37,21 +36,21 @@ if __name__ == '__main__':
License
=======
-------
This software is dedicated to the public domain. See
http://creativecommons.org/publicdomain/zero/1.0/ for details.
Todo
====
----
- Remove unecessary python libraries from windows build
- Debug levels
Contact
=======
-------
frank dot s dot demarco at gmail
http://a-o.in
http://A-O.in

View File

@ -128,7 +128,11 @@ class Configuration(RawConfigParser):
def read_project_config_file(self):
path = self.locate_project_config_file()
if path:
self.read(path)
fp = open(path)
self.set_modifiable(fp)
fp.seek(0)
self.readfp(fp)
fp.close()
else:
self.print_debug("No configuration file found")
@ -146,6 +150,17 @@ class Configuration(RawConfigParser):
def is_shared_mode(self):
return "-s" in argv
def set_modifiable(self, fp):
config = RawConfigParser()
config.readfp(fp)
modifiable = []
for section in config._sections:
modifiable.append([section, []])
for option in config._sections[section]:
if option != "__name__":
modifiable[-1][1].append(option)
self.modifiable = modifiable
def print_debug(self, statement):
if self.is_debug_mode():
print statement
@ -266,6 +281,25 @@ class Configuration(RawConfigParser):
items.append((option, self.get(section, option)))
return items
def write(self, fp):
for section in self.modifiable:
fp.write("[%s]\n" % section[0])
for name in section[1]:
value = self.get(section[0], name)
fp.write("%s = %s\n" % (name, self.get_raw_value(value)))
fp.write("\n")
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
class TypeDeclarations(dict):

View File

@ -12,6 +12,7 @@ from Input import Input
from ScreenGrabber import ScreenGrabber
from Profile import Profile
from VideoRecorder import VideoRecorder
from Interpolator import Interpolator
class Game(GameChild):
@ -43,6 +44,7 @@ class Game(GameChild):
self.audio = Audio(self)
self.screen_grabber = ScreenGrabber(self)
self.video_recorder = VideoRecorder(self)
self.interpolator = Interpolator(self)
def frame(self):
self.delegate.dispatch()

119
pgfw/Interpolator.py Normal file
View File

@ -0,0 +1,119 @@
from GameChild import GameChild
class Interpolator(dict, GameChild):
def __init__(self, parent):
GameChild.__init__(self, parent)
self.read()
def read(self):
for name, value in self.get_configuration("interpolate").iteritems():
self[name] = Nodes(value)
class Nodes(list):
LINEAR, CUBIC = range(2)
def __init__(self, raw):
list.__init__(self, [])
self.parse_raw(raw)
self.set_splines()
def parse_raw(self, raw):
raw = raw.strip()
if raw[0].upper() == "L":
self.interpolation_method = self.LINEAR
else:
self.interpolation_method = self.CUBIC
for node in raw[1:].strip().split(","):
self.append(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):
pass
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 = [Spline(a[ii], b[ii], c[ii], d[ii], self[ii].x) for \
ii in xrange(n)]
def get_y(self, t):
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 __repr__(self):
return "<%i, %s>" % (self.interpolation_method, list(self))
def print_checkpoints(self):
start, end = int(self[0].x), int(self[-1].x)
step = (end - start) / 8
for t in xrange(start, end + step, step):
print "%i\t%.3f" % (t, self.get_y(t))
class Node(list):
def __init__(self, raw):
list.__init__(self, (float(value) for value in raw.strip().split()))
def __getattr__(self, name):
if name == "x":
return self[0]
elif name == "y":
return self[1]
return list.__get__(self, name)
class Spline:
def __init__(self, a, b, c, d, x):
self.a = a
self.b = b
self.c = c
self.d = d
self.x = x
def __repr__(self):
x = self.x
return ("<%.1e + %.1e * (x - %.1e) + %.1e * (x - %.1e) ** 2 + " + \
"%.1e * (x - %.1e) ** 3>") % (self.a, self.b, x, self.c, x,
self.d, x)
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

View File

@ -19,6 +19,7 @@ class Sprite(Animation):
Animation.__init__(self, parent, self.shift_frame, framerate)
self.clear_frames()
self.mirrored = False
self.hidden = False
self.alpha = 255
self.locations = [Location(self)]
self.framesets = [Frameset(self, framerate=framerate)]
@ -42,6 +43,8 @@ class Sprite(Animation):
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,
@ -161,6 +164,12 @@ class Sprite(Animation):
def add_frameset(self, order, framerate=None, name=None):
self.framesets.append(Frameset(self, order, framerate, name))
def hide(self):
self.hidden = True
def unhide(self):
self.hidden = False
def update(self):
Animation.update(self)
self.draw()
@ -243,13 +252,16 @@ class Fader(Surface):
frame.set_alpha(255)
self.blit(frame, (0, 0))
frame.set_alpha(sprite.alpha)
sprite.display_surface.blit(self, self.location)
if not sprite.hidden:
self.blit_to_display(self)
elif self.fade_remaining is None or self.get_alpha() >= sprite.alpha:
if self.fade_remaining >= 0:
self.update_alpha()
sprite.display_surface.blit(sprite.get_current_frame(),
self.location)
if not sprite.hidden:
self.blit_to_display(sprite.get_current_frame())
def blit_to_display(self, frame):
self.location.sprite.display_surface.blit(frame, self.location)
def update_alpha(self):
remaining = self.fade_remaining = self.fade_length - (get_ticks() - \