- fix include delay bug in Animation class
- multiple values for boolean true in config files - sprite wipe out animation - sprite children optionally drawn on parent surface - text wrapping function handles line breaks - blinds animation function for returning rects
This commit is contained in:
parent
0878ad6181
commit
301f547a25
|
@ -58,7 +58,7 @@ class Animation(GameChild):
|
||||||
include_delay)
|
include_delay)
|
||||||
|
|
||||||
def is_account_playing(self, account, include_delay):
|
def is_account_playing(self, account, include_delay):
|
||||||
return account.playing and (not include_delay or not account.delay)
|
return account.playing and (include_delay or not account.delay)
|
||||||
|
|
||||||
def reset_timer(self, method=None):
|
def reset_timer(self, method=None):
|
||||||
if not method:
|
if not method:
|
||||||
|
|
|
@ -8,19 +8,20 @@ from .Input import *
|
||||||
from .Animation import *
|
from .Animation import *
|
||||||
from .extension import *
|
from .extension import *
|
||||||
|
|
||||||
class Audio(GameChild):
|
class Audio(Animation):
|
||||||
|
|
||||||
UP, DOWN = .1, -.1
|
UP, DOWN = .1, -.1
|
||||||
BASE_VOLUME = 1.0
|
BASE_VOLUME = 1.0
|
||||||
CONFIG_SEPARATOR = ","
|
CONFIG_SEPARATOR = ","
|
||||||
|
|
||||||
def __init__(self, game):
|
def __init__(self, game):
|
||||||
GameChild.__init__(self, game)
|
Animation.__init__(self, game)
|
||||||
# self.original_volumes = {}
|
# self.original_volumes = {}
|
||||||
self.current_bgm = None
|
self.current_bgm = None
|
||||||
self.volume = self.BASE_VOLUME
|
self.volume = self.BASE_VOLUME
|
||||||
if self.check_command_line("-mute"):
|
if self.check_command_line("-mute"):
|
||||||
self.volume = 0
|
self.volume = 0
|
||||||
|
self.register(self.play_sfx)
|
||||||
self.audio_panel = AudioPanel(self)
|
self.audio_panel = AudioPanel(self)
|
||||||
self.subscribe(self.respond)
|
self.subscribe(self.respond)
|
||||||
self.sfx = {}
|
self.sfx = {}
|
||||||
|
@ -106,6 +107,9 @@ class Audio(GameChild):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def play_sfx(self, name):
|
||||||
|
self.sfx[name].play()
|
||||||
|
|
||||||
#
|
#
|
||||||
# Loading BGM procedure
|
# Loading BGM procedure
|
||||||
#
|
#
|
||||||
|
@ -180,13 +184,7 @@ class Audio(GameChild):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
# for ii in range(pygame.mixer.get_num_channels()):
|
Animation.update(self)
|
||||||
# channel = pygame.mixer.Channel(ii)
|
|
||||||
# sound = channel.get_sound()
|
|
||||||
# if sound is not None:
|
|
||||||
# if sound not in self.original_volumes.keys():
|
|
||||||
# self.original_volumes[sound] = sound.get_volume()
|
|
||||||
# sound.set_volume(self.original_volumes[sound] * self.volume)
|
|
||||||
self.audio_panel.update()
|
self.audio_panel.update()
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,6 +207,9 @@ class BGM(GameChild):
|
||||||
def get_volume(self):
|
def get_volume(self):
|
||||||
return self.volume
|
return self.volume
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.path == other.path
|
||||||
|
|
||||||
|
|
||||||
class SoundEffect(GameChild, pygame.mixer.Sound):
|
class SoundEffect(GameChild, pygame.mixer.Sound):
|
||||||
|
|
||||||
|
@ -329,6 +330,7 @@ class AudioPanel(Animation):
|
||||||
self.active = False
|
self.active = False
|
||||||
if self.bgm_elapsed is not None:
|
if self.bgm_elapsed is not None:
|
||||||
self.get_audio().play_bgm(start=self.bgm_elapsed)
|
self.get_audio().play_bgm(start=self.bgm_elapsed)
|
||||||
|
self.file_browser.hide()
|
||||||
|
|
||||||
def respond(self, event):
|
def respond(self, event):
|
||||||
if self.get_delegate().compare(event, "toggle-audio-panel") and self.get_audio().sfx:
|
if self.get_delegate().compare(event, "toggle-audio-panel") and self.get_audio().sfx:
|
||||||
|
@ -444,7 +446,7 @@ class AudioPanelRow(BlinkingSprite):
|
||||||
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
||||||
|
|
||||||
def respond(self, event):
|
def respond(self, event):
|
||||||
if event.button == 1:
|
if self.parent.active and event.button == 1:
|
||||||
if self.parent.file_browser.is_hidden() and self.location.collidepoint(event.pos):
|
if self.parent.file_browser.is_hidden() and self.location.collidepoint(event.pos):
|
||||||
if not self.selected:
|
if not self.selected:
|
||||||
self.parent.file_browser.visit(self.parent.file_browser.HOME)
|
self.parent.file_browser.visit(self.parent.file_browser.HOME)
|
||||||
|
@ -530,6 +532,15 @@ class AudioPanelRow(BlinkingSprite):
|
||||||
shutil.copyfile(config_path, backup_path)
|
shutil.copyfile(config_path, backup_path)
|
||||||
self.get_configuration().write(open(config_path, "w"))
|
self.get_configuration().write(open(config_path, "w"))
|
||||||
|
|
||||||
|
def set_clickable(self, clickable=True):
|
||||||
|
self.play_button.set_clickable(clickable)
|
||||||
|
self.stop_button.set_clickable(clickable)
|
||||||
|
self.volume_spinner.set_clickable(clickable)
|
||||||
|
if not self.is_bgm:
|
||||||
|
self.fade_out_spinner.set_clickable(clickable)
|
||||||
|
self.loops_spinner.set_clickable(clickable)
|
||||||
|
self.maxtime_spinner.set_clickable(clickable)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
self.play_button.location.midleft = self.location.move(5, 0).midright
|
self.play_button.location.midleft = self.location.move(5, 0).midright
|
||||||
self.stop_button.location.midleft = self.play_button.location.midright
|
self.stop_button.location.midleft = self.play_button.location.midright
|
||||||
|
@ -612,8 +623,7 @@ class AudioPanelFileBrowser(Sprite):
|
||||||
for row in self.parent.rows:
|
for row in self.parent.rows:
|
||||||
row.selected = False
|
row.selected = False
|
||||||
row.stop_blinking()
|
row.stop_blinking()
|
||||||
row.play_button.set_clickable()
|
row.set_clickable(True)
|
||||||
row.stop_button.set_clickable()
|
|
||||||
for row in self.rows:
|
for row in self.rows:
|
||||||
if row.has_child("button"):
|
if row.has_child("button"):
|
||||||
row.get_child("button").set_clickable(False)
|
row.get_child("button").set_clickable(False)
|
||||||
|
@ -623,8 +633,7 @@ class AudioPanelFileBrowser(Sprite):
|
||||||
|
|
||||||
def unhide(self):
|
def unhide(self):
|
||||||
for row in self.parent.rows:
|
for row in self.parent.rows:
|
||||||
row.play_button.set_clickable(False)
|
row.set_clickable(False)
|
||||||
row.stop_button.set_clickable(False)
|
|
||||||
for row in self.rows:
|
for row in self.rows:
|
||||||
if row.has_child("button"):
|
if row.has_child("button"):
|
||||||
row.get_child("button").set_clickable()
|
row.get_child("button").set_clickable()
|
||||||
|
@ -762,6 +771,7 @@ class AudioPanelSpinner(Sprite):
|
||||||
self.down_button.location.topleft = self.display.location.right - 1, \
|
self.down_button.location.topleft = self.display.location.right - 1, \
|
||||||
self.up_button.location.bottom - 1
|
self.up_button.location.bottom - 1
|
||||||
self.down_button.display_surface = self.get_current_frame()
|
self.down_button.display_surface = self.get_current_frame()
|
||||||
|
self.set_clickable()
|
||||||
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
||||||
|
|
||||||
def unsubscribe(self, callback=None, kind=None):
|
def unsubscribe(self, callback=None, kind=None):
|
||||||
|
@ -788,7 +798,7 @@ class AudioPanelSpinner(Sprite):
|
||||||
self.update_display()
|
self.update_display()
|
||||||
|
|
||||||
def respond(self, event):
|
def respond(self, event):
|
||||||
if event.button == 1:
|
if self.clickable and event.button == 1:
|
||||||
relative_position = Vector(*event.pos).get_moved(
|
relative_position = Vector(*event.pos).get_moved(
|
||||||
-self.location.left, -self.location.top)
|
-self.location.left, -self.location.top)
|
||||||
up_collides = self.up_button.collide(relative_position)
|
up_collides = self.up_button.collide(relative_position)
|
||||||
|
@ -800,6 +810,9 @@ class AudioPanelSpinner(Sprite):
|
||||||
self.increment(False)
|
self.increment(False)
|
||||||
self.parent.update_config()
|
self.parent.update_config()
|
||||||
|
|
||||||
|
def set_clickable(self, clickable=True):
|
||||||
|
self.clickable = clickable
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
self.get_current_frame().fill(self.background)
|
self.get_current_frame().fill(self.background)
|
||||||
self.label.update()
|
self.label.update()
|
||||||
|
@ -816,8 +829,8 @@ class AudioPanelButton(Sprite):
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.callback_kwargs = callback_kwargs
|
self.callback_kwargs = callback_kwargs
|
||||||
self.containers = containers
|
self.containers = containers
|
||||||
self.clickable = True
|
|
||||||
self.pass_mods = pass_mods
|
self.pass_mods = pass_mods
|
||||||
|
self.set_clickable()
|
||||||
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
||||||
|
|
||||||
def unsubscribe(self, callback=None, kind=None):
|
def unsubscribe(self, callback=None, kind=None):
|
||||||
|
@ -827,7 +840,7 @@ class AudioPanelButton(Sprite):
|
||||||
Sprite.unsubscribe(self, callback, kind)
|
Sprite.unsubscribe(self, callback, kind)
|
||||||
|
|
||||||
def respond(self, event):
|
def respond(self, event):
|
||||||
if self.clickable and event.button == 1:
|
if self.get_audio().audio_panel.active and self.clickable and event.button == 1:
|
||||||
pos = Vector(*event.pos)
|
pos = Vector(*event.pos)
|
||||||
for container in self.containers:
|
for container in self.containers:
|
||||||
pos.move(-container.location.left, -container.location.top)
|
pos.move(-container.location.left, -container.location.top)
|
||||||
|
|
|
@ -67,7 +67,7 @@ class Configuration(RawConfigParser):
|
||||||
set_option(section, "whitespace-placeholder", "-", False)
|
set_option(section, "whitespace-placeholder", "-", False)
|
||||||
set_option(section, "windows-dist-path", "dist/win/", False)
|
set_option(section, "windows-dist-path", "dist/win/", False)
|
||||||
set_option(section, "windows-icon-path", "", False)
|
set_option(section, "windows-icon-path", "", False)
|
||||||
set_option(section, "lowercase-boolean-true", "yes", False)
|
set_option(section, "boolean-true-lowercase", "yes, true, t, 1", False)
|
||||||
set_option(section, "osx-includes", "", False)
|
set_option(section, "osx-includes", "", False)
|
||||||
section = "display"
|
section = "display"
|
||||||
add_section(section)
|
add_section(section)
|
||||||
|
@ -275,9 +275,7 @@ class Configuration(RawConfigParser):
|
||||||
# if type(value) == str or type(value) == unicode:
|
# if type(value) == str or type(value) == unicode:
|
||||||
if type(value) == str:
|
if type(value) == str:
|
||||||
if pair in types["bool"]:
|
if pair in types["bool"]:
|
||||||
if value.lower() == self.get("setup", "lowercase-boolean-true"):
|
return value.lower() in self.get("setup", "boolean-true-lowercase")
|
||||||
return True
|
|
||||||
return False
|
|
||||||
elif pair in types["int"]:
|
elif pair in types["int"]:
|
||||||
return int(value)
|
return int(value)
|
||||||
elif pair in types["float"]:
|
elif pair in types["float"]:
|
||||||
|
@ -422,7 +420,7 @@ class TypeDeclarations(dict):
|
||||||
|
|
||||||
"setup": {"list": ["classifiers", "resource-search-path",
|
"setup": {"list": ["classifiers", "resource-search-path",
|
||||||
"requirements", "data-exclude",
|
"requirements", "data-exclude",
|
||||||
"additional-packages", "osx-includes"],
|
"additional-packages", "osx-includes", "boolean-true-lowercase"],
|
||||||
|
|
||||||
"path": ["installation-dir", "changelog", "description-file",
|
"path": ["installation-dir", "changelog", "description-file",
|
||||||
"main-object", "icon-path", "windows-dist-path",
|
"main-object", "icon-path", "windows-dist-path",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
import collections
|
||||||
from os import listdir
|
from os import listdir
|
||||||
from os.path import isfile, join
|
from os.path import isfile, join
|
||||||
from sys import exc_info, stdout
|
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
from pygame import Color, Rect, Surface, PixelArray, mask
|
from pygame import Color, Rect, Surface, PixelArray, mask
|
||||||
|
@ -10,11 +10,11 @@ from pygame.locals import *
|
||||||
|
|
||||||
from .Animation import Animation
|
from .Animation import Animation
|
||||||
from .Vector import Vector, EVector
|
from .Vector import Vector, EVector
|
||||||
from .extension import get_hue_shifted_surface, get_step
|
from .extension import get_hue_shifted_surface, get_step, load_frames, get_blinds_rects
|
||||||
|
|
||||||
class Sprite(Animation):
|
class Sprite(Animation):
|
||||||
|
|
||||||
def __init__(self, parent, framerate=None, neighbors=[], mass=None):
|
def __init__(self, parent, framerate=None, draw_children_on_frame=True):
|
||||||
Animation.__init__(self, parent, self.shift_frame, framerate)
|
Animation.__init__(self, parent, self.shift_frame, framerate)
|
||||||
self.frames = []
|
self.frames = []
|
||||||
self.mirrored = False
|
self.mirrored = False
|
||||||
|
@ -22,15 +22,20 @@ class Sprite(Animation):
|
||||||
self.locations = []
|
self.locations = []
|
||||||
self.framesets = [Frameset(self, framerate=framerate)]
|
self.framesets = [Frameset(self, framerate=framerate)]
|
||||||
self.frameset_index = 0
|
self.frameset_index = 0
|
||||||
self.neighbors = neighbors
|
|
||||||
self.mass = mass
|
|
||||||
self._step = EVector()
|
self._step = EVector()
|
||||||
self.children = {}
|
self.children = collections.OrderedDict()
|
||||||
|
self.draw_children_on_frame = draw_children_on_frame
|
||||||
self.set_frameset(0)
|
self.set_frameset(0)
|
||||||
self.locations.append(Location(self))
|
self.locations.append(Location(self))
|
||||||
self.motion_overflow = Vector()
|
self.motion_overflow = Vector()
|
||||||
self.display_surface = self.get_display_surface()
|
self.display_surface = self.get_display_surface()
|
||||||
self.register(self.toggle_hidden)
|
self.wipe_blinds = []
|
||||||
|
self.current_wipe_index = 0
|
||||||
|
self.register(self.toggle_hidden, self.wipe_out)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.halt(self.wipe_out)
|
||||||
|
self.current_wipe_index = 0
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name in ("location", "rect"):
|
if name in ("location", "rect"):
|
||||||
|
@ -61,6 +66,7 @@ class Sprite(Animation):
|
||||||
if self.get_current_frameset().length() > 1:
|
if self.get_current_frameset().length() > 1:
|
||||||
self.play()
|
self.play()
|
||||||
self.get_current_frameset().reset()
|
self.get_current_frameset().reset()
|
||||||
|
return self.get_current_frameset()
|
||||||
|
|
||||||
def register_interval(self):
|
def register_interval(self):
|
||||||
self.register(self.shift_frame,
|
self.register(self.shift_frame,
|
||||||
|
@ -81,25 +87,10 @@ class Sprite(Animation):
|
||||||
|
|
||||||
def load_from_path(self, path, transparency=False, ppa=True, key=None,
|
def load_from_path(self, path, transparency=False, ppa=True, key=None,
|
||||||
query=None, omit=False):
|
query=None, omit=False):
|
||||||
if isfile(path):
|
for frame in load_frames(self.get_resource(path), transparency, ppa, key, query):
|
||||||
paths = [path]
|
|
||||||
else:
|
|
||||||
if query:
|
|
||||||
paths = sorted(glob(join(path, query)))
|
|
||||||
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)
|
self.add_frame(frame, omit)
|
||||||
|
|
||||||
def fill_colorkey(self, img, key=None):
|
def fill_colorkey(img, key=None):
|
||||||
if not key:
|
if not key:
|
||||||
key = (255, 0, 255)
|
key = (255, 0, 255)
|
||||||
img = img.convert_alpha()
|
img = img.convert_alpha()
|
||||||
|
@ -116,6 +107,8 @@ class Sprite(Animation):
|
||||||
frameset = self.get_current_frameset()
|
frameset = self.get_current_frameset()
|
||||||
frameset.add_index(self.frames.index(frame))
|
frameset.add_index(self.frames.index(frame))
|
||||||
self.update_location_size()
|
self.update_location_size()
|
||||||
|
self.wipe_blinds = get_blinds_rects(*self.location.size)
|
||||||
|
self.wipe_blinds.reverse()
|
||||||
if frameset.length() > 1:
|
if frameset.length() > 1:
|
||||||
self.play()
|
self.play()
|
||||||
|
|
||||||
|
@ -205,14 +198,20 @@ class Sprite(Animation):
|
||||||
def hide(self):
|
def hide(self):
|
||||||
for location in self.locations:
|
for location in self.locations:
|
||||||
location.hide()
|
location.hide()
|
||||||
|
for child in self.children.values():
|
||||||
|
child.hide()
|
||||||
|
|
||||||
def unhide(self):
|
def unhide(self):
|
||||||
for location in self.locations:
|
for location in self.locations:
|
||||||
location.unhide()
|
location.unhide()
|
||||||
|
for child in self.children.values():
|
||||||
|
child.unhide()
|
||||||
|
|
||||||
def toggle_hidden(self):
|
def toggle_hidden(self):
|
||||||
for location in self.locations:
|
for location in self.locations:
|
||||||
location.toggle_hidden()
|
location.toggle_hidden()
|
||||||
|
for child in self.children.values():
|
||||||
|
child.toggle_hidden()
|
||||||
|
|
||||||
def is_hidden(self):
|
def is_hidden(self):
|
||||||
return all(location.is_hidden() for location in self.locations)
|
return all(location.is_hidden() for location in self.locations)
|
||||||
|
@ -248,19 +247,41 @@ class Sprite(Animation):
|
||||||
def has_child(self, name):
|
def has_child(self, name):
|
||||||
return name in self.children
|
return name in self.children
|
||||||
|
|
||||||
|
def remove_child(self, name):
|
||||||
|
if self.has_child(name):
|
||||||
|
self.children.pop(name)
|
||||||
|
|
||||||
|
def wipe_out(self):
|
||||||
|
for child in self.children.values():
|
||||||
|
if not child.is_playing(child.wipe_out):
|
||||||
|
child.play(child.wipe_out)
|
||||||
|
self.current_wipe_index += 1
|
||||||
|
if self.current_wipe_index == len(self.wipe_blinds):
|
||||||
|
self.current_wipe_index = 0
|
||||||
|
self.halt(self.wipe_out)
|
||||||
|
self.hide()
|
||||||
|
|
||||||
|
def get_current_blinds(self):
|
||||||
|
return self.wipe_blinds[self.current_wipe_index]
|
||||||
|
|
||||||
def update(self, areas=None, substitute=None, flags=0):
|
def update(self, areas=None, substitute=None, flags=0):
|
||||||
Animation.update(self)
|
Animation.update(self)
|
||||||
if self.is_stepping():
|
if self.is_stepping():
|
||||||
self.move(self._step.dx, self._step.dy)
|
self.move(self._step.dx, self._step.dy)
|
||||||
for neighbor in self.neighbors:
|
|
||||||
self.move(*get_step(self.location.center, neighbor.location.center,
|
|
||||||
neighbor.mass))
|
|
||||||
if self.get_current_frameset().length():
|
if self.get_current_frameset().length():
|
||||||
|
if self.is_playing(self.wipe_out):
|
||||||
|
areas = self.get_current_blinds()
|
||||||
self.draw(areas, substitute, flags)
|
self.draw(areas, substitute, flags)
|
||||||
for child in self.children.values():
|
for child in self.children.values():
|
||||||
|
if self.draw_children_on_frame:
|
||||||
|
child.display_surface = self.get_current_frame()
|
||||||
|
else:
|
||||||
|
child.display_surface = self.get_display_surface()
|
||||||
|
save_child_topleft = child.location.topleft
|
||||||
|
child.move(*self.location.topleft)
|
||||||
child.update()
|
child.update()
|
||||||
# for location in self.locations:
|
if not self.draw_children_on_frame:
|
||||||
# location.update()
|
child.location.topleft = save_child_topleft
|
||||||
|
|
||||||
def draw(self, areas=None, substitute=None, flags=0):
|
def draw(self, areas=None, substitute=None, flags=0):
|
||||||
for location in self.locations:
|
for location in self.locations:
|
||||||
|
@ -316,18 +337,6 @@ class Location(Rect):
|
||||||
def is_hidden(self):
|
def is_hidden(self):
|
||||||
return self.hidden
|
return self.hidden
|
||||||
|
|
||||||
def update(self):
|
|
||||||
pass
|
|
||||||
# for neighbor in self.sprite.neighbors:
|
|
||||||
# if neighbor.mass:
|
|
||||||
# closest = neighbor.location
|
|
||||||
# for location in neighbor.locations[1:]:
|
|
||||||
# if get_distance(self.center, location.center) < \
|
|
||||||
# get_distance(self.center, closest.center):
|
|
||||||
# closest = location
|
|
||||||
# self.move_ip(get_step(self.center, closest.center,
|
|
||||||
# neighbor.mass))
|
|
||||||
|
|
||||||
|
|
||||||
class Fader(Surface):
|
class Fader(Surface):
|
||||||
|
|
||||||
|
@ -493,6 +502,7 @@ class BlinkingSprite(Sprite):
|
||||||
def __init__(self, parent, blink_rate, framerate=None):
|
def __init__(self, parent, blink_rate, framerate=None):
|
||||||
Sprite.__init__(self, parent, framerate)
|
Sprite.__init__(self, parent, framerate)
|
||||||
self.register(self.blink, interval=blink_rate)
|
self.register(self.blink, interval=blink_rate)
|
||||||
|
self.register(self.start_blinking, self.stop_blinking)
|
||||||
self.play(self.blink)
|
self.play(self.blink)
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import itertools, random
|
import itertools, random, os, glob
|
||||||
from math import sin, cos, atan2, radians, sqrt, pi
|
from math import sin, cos, atan2, radians, sqrt, pi
|
||||||
|
|
||||||
|
import pygame
|
||||||
from pygame import Surface, PixelArray, Color, Rect, draw, gfxdraw
|
from pygame import Surface, PixelArray, Color, Rect, draw, gfxdraw
|
||||||
from pygame.mixer import get_num_channels, Channel
|
from pygame.mixer import get_num_channels, Channel
|
||||||
from pygame.locals import *
|
from pygame.locals import *
|
||||||
|
@ -119,6 +120,16 @@ def place_in_rect(rect, incoming, contain=True, *args):
|
||||||
if not collides:
|
if not collides:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
def constrain_dimensions_2d(vector, container):
|
||||||
|
dw = vector[0] - container[0]
|
||||||
|
dh = vector[1] - container[1]
|
||||||
|
if dw > 0 or dh > 0:
|
||||||
|
if dw > dh:
|
||||||
|
size = container[0], int(round(container[0] / vector[0] * vector[1]))
|
||||||
|
else:
|
||||||
|
size = int(round(container[1] / vector[1] * vector[0])), container[1]
|
||||||
|
return size
|
||||||
|
|
||||||
# from http://www.realtimerendering.com/resources/GraphicsGems/gemsii/xlines.c
|
# from http://www.realtimerendering.com/resources/GraphicsGems/gemsii/xlines.c
|
||||||
def get_intersection(p0, p1, p2, p3):
|
def get_intersection(p0, p1, p2, p3):
|
||||||
x0, y0 = p0
|
x0, y0 = p0
|
||||||
|
@ -215,16 +226,21 @@ def render_box(font=None, text=None, antialias=True, color=(0, 0, 0), background
|
||||||
surface.fill(background)
|
surface.fill(background)
|
||||||
return get_boxed_surface(surface, background, border, border_width, padding)
|
return get_boxed_surface(surface, background, border, border_width, padding)
|
||||||
|
|
||||||
def get_wrapped_text_surface(font, text, width, antialias, color,
|
def get_wrapped_text_surface(font, text, width, antialias=True, color=(0, 0, 0),
|
||||||
background=None, border=None, border_width=1,
|
background=None, border=None, border_width=1,
|
||||||
padding=0):
|
padding=0, align="left"):
|
||||||
words = text.split()
|
lines = []
|
||||||
if words:
|
height = 0
|
||||||
|
for chunk in text.split("\n"):
|
||||||
line_text = ""
|
line_text = ""
|
||||||
lines = []
|
|
||||||
height = 0
|
|
||||||
ii = 0
|
ii = 0
|
||||||
finished = False
|
finished = False
|
||||||
|
if chunk.startswith("\*") and chunk.endswith("\*"):
|
||||||
|
chunk = chunk.replace("\*", "*")
|
||||||
|
elif chunk.startswith("*") and chunk.endswith("*"):
|
||||||
|
chunk = chunk[1:-1]
|
||||||
|
font.set_italic(True)
|
||||||
|
words = chunk.split(" ")
|
||||||
while not finished:
|
while not finished:
|
||||||
line_width = font.size(line_text + " " + words[ii])[0]
|
line_width = font.size(line_text + " " + words[ii])[0]
|
||||||
if line_width > width or ii == len(words) - 1:
|
if line_width > width or ii == len(words) - 1:
|
||||||
|
@ -233,25 +249,26 @@ def get_wrapped_text_surface(font, text, width, antialias, color,
|
||||||
line_text += " "
|
line_text += " "
|
||||||
line_text += words[ii]
|
line_text += words[ii]
|
||||||
finished = True
|
finished = True
|
||||||
line = font.render(line_text, antialias, color, background)
|
line = font.render(line_text, antialias, color)
|
||||||
height += line.get_height()
|
height += line.get_height()
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
line_text = ""
|
line_text = ""
|
||||||
else:
|
else:
|
||||||
line_text += " " + words[ii]
|
line_text += " " + words[ii]
|
||||||
ii += 1
|
ii += 1
|
||||||
top = 0
|
font.set_italic(False)
|
||||||
surface = Surface((width, height), SRCALPHA)
|
top = 0
|
||||||
if background:
|
surface = Surface((width, height), pygame.SRCALPHA)
|
||||||
surface.fill(background)
|
if background:
|
||||||
rect = surface.get_rect()
|
surface.fill(background)
|
||||||
for line in lines:
|
rect = surface.get_rect()
|
||||||
line_rect = line.get_rect()
|
for line in lines:
|
||||||
line_rect.midtop = rect.centerx, top
|
line_rect = line.get_rect()
|
||||||
surface.blit(line, line_rect)
|
line_rect.top = top
|
||||||
top += line_rect.h
|
if align == "center":
|
||||||
else:
|
line_rect.centerx = rect.centerx
|
||||||
surface = Surface((0, 0), SRCALPHA)
|
surface.blit(line, line_rect)
|
||||||
|
top += line_rect.h
|
||||||
return get_boxed_surface(surface, background, border, border_width, padding)
|
return get_boxed_surface(surface, background, border, border_width, padding)
|
||||||
|
|
||||||
def replace_color(surface, color, replacement):
|
def replace_color(surface, color, replacement):
|
||||||
|
@ -305,6 +322,37 @@ def fill_tile(surface, tile, rect=None):
|
||||||
for y in range(0, surface.get_height(), h):
|
for y in range(0, surface.get_height(), h):
|
||||||
surface.blit(tile, (x, y))
|
surface.blit(tile, (x, y))
|
||||||
|
|
||||||
|
def load_frames(path, transparency=False, ppa=True, key=None, query=None):
|
||||||
|
if os.path.isfile(path):
|
||||||
|
paths = [path]
|
||||||
|
else:
|
||||||
|
if query:
|
||||||
|
paths = sorted(glob.glob(os.path.join(path, query)))
|
||||||
|
else:
|
||||||
|
paths = [os.path.join(path, name) for name in sorted(os.listdir(path))]
|
||||||
|
frames = []
|
||||||
|
for path in paths:
|
||||||
|
img = pygame.image.load(path)
|
||||||
|
if transparency:
|
||||||
|
if ppa:
|
||||||
|
frame = img.convert_alpha()
|
||||||
|
else:
|
||||||
|
frame = fill_colorkey(img, key)
|
||||||
|
else:
|
||||||
|
frame = img.convert()
|
||||||
|
frames.append(frame)
|
||||||
|
return frames
|
||||||
|
|
||||||
|
def fill_colorkey(img, key=None):
|
||||||
|
if key is None:
|
||||||
|
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 get_shadowed_text(text, font, offset, color, antialias=True, shadow_color=(0, 0, 0),
|
def get_shadowed_text(text, font, offset, color, antialias=True, shadow_color=(0, 0, 0),
|
||||||
colorkey=(255, 0, 255)):
|
colorkey=(255, 0, 255)):
|
||||||
foreground = font.render(text, antialias, color)
|
foreground = font.render(text, antialias, color)
|
||||||
|
@ -321,6 +369,24 @@ def get_shadowed_text(text, font, offset, color, antialias=True, shadow_color=(0
|
||||||
(abs(offset[1]) - offset[1]) / 2))
|
(abs(offset[1]) - offset[1]) / 2))
|
||||||
return surface
|
return surface
|
||||||
|
|
||||||
|
def get_blinds_rects(w, h, step=.05, count=4):
|
||||||
|
blinds = []
|
||||||
|
blind_h = int(round(h / float(count)))
|
||||||
|
for ii in range(1, count + 1):
|
||||||
|
blinds.append(Rect(0, blind_h * ii, w, 0))
|
||||||
|
inflate_h = int(round(blind_h * step))
|
||||||
|
if inflate_h < 1:
|
||||||
|
inflate_h = 1
|
||||||
|
rects = []
|
||||||
|
while blinds[0].h < blind_h:
|
||||||
|
rects.append([])
|
||||||
|
for blind in blinds:
|
||||||
|
bottom = blind.bottom
|
||||||
|
blind.inflate_ip(0, inflate_h)
|
||||||
|
blind.bottom = bottom
|
||||||
|
rects[-1].append(blind.copy())
|
||||||
|
return rects
|
||||||
|
|
||||||
def get_blinds_frames(surface, step=.05, count=4, fill=(0, 0, 0, 0)):
|
def get_blinds_frames(surface, step=.05, count=4, fill=(0, 0, 0, 0)):
|
||||||
frames = []
|
frames = []
|
||||||
rects = []
|
rects = []
|
||||||
|
|
Loading…
Reference in New Issue