From 47b9c1a27f44444ad4f7f1e061a3413238adf179 Mon Sep 17 00:00:00 2001 From: frank <420@shampoo.ooo> Date: Sat, 22 May 2021 19:14:44 -0400 Subject: [PATCH] extension functions: diagonal to rect, marching ants, fill borders; audio channel volume, init volume to 1 --- pgfw/Audio.py | 45 +++++++++++++++++++++++++++++---------------- pgfw/extension.py | 26 +++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/pgfw/Audio.py b/pgfw/Audio.py index 92ffb78..1ddedc5 100644 --- a/pgfw/Audio.py +++ b/pgfw/Audio.py @@ -15,10 +15,9 @@ class Audio(Animation): def __init__(self, game): Animation.__init__(self, game) - # self.original_volumes = {} self.current_bgm = None self.volume = 1.0 - self.pre_muted_volume = None + self.pre_muted_volume = 1.0 if self.check_command_line("-mute"): self.get_configuration().set("audio", "volume", 0) self.register(self.play_sfx) @@ -52,6 +51,19 @@ class Audio(Animation): if channel.get_busy(): channel.set_volume(channel.get_sound().get_volume() * self.volume) + def get_volume(self): + return self.volume + + def set_channel_volume(self, channel, *args): + ''' + Set channel volume taking global volume into account. One or two values can be passed into *args. + A single value will affect both left and right speakers. Two values will be used as the left and right + speakers separately. This is the behavior of pygame's Channel.set_volume method + ''' + for ii in range(len(args)): + args[ii] *= self.volume + channel.set_volume(*args) + def respond(self, event): compare = self.get_game().delegate.compare if compare(event, "volume-mute"): @@ -110,8 +122,7 @@ class Audio(Animation): prefix = re.sub(r"{}".format(os.path.sep), r"_", prefix) + "_" self.load_sfx_file(os.path.join(node, leaf,), prefix=prefix) - def load_sfx_file(self, path, name=None, replace=False, prefix="", - volume=1.0, fade_out=0, loops=0, maxtime=0): + def load_sfx_file(self, path, name=None, replace=False, prefix="", volume=1.0, fade_out=0, loops=0, maxtime=0): path = self.get_resource(path) if path and self.is_loadable(path): if name is None: @@ -120,13 +131,17 @@ class Audio(Animation): print("skipping existing sound effect for {}: {}".format(name, path)) else: print("loading sound effect {} into {}".format(path, name)) - self.sfx[name] = SoundEffect( - self, path, volume, loops, fade_out, maxtime=maxtime) + self.sfx[name] = SoundEffect(self, path, volume, loops, fade_out, maxtime=maxtime) return True return False - def play_sfx(self, name, loops=None, maxtime=None, fade_ms=None, position=None, - x=None): + def get_sfx(self, name): + ''' + Get a SoundEffect object (which inherits pygame's Sound) from this object's dictonary of loaded sfx + ''' + return self.sfx[name] + + def play_sfx(self, name, loops=None, maxtime=None, fade_ms=None, position=None, x=None): return self.sfx[name].play(loops, maxtime, fade_ms, position, x) # @@ -169,6 +184,8 @@ class Audio(Animation): if name is None: name = os.path.basename(path).split(".")[0] self.bgm[prefix + name] = BGM(self, path, volume) + if self.current_bgm is None: + self.current_bgm = self.bgm[prefix + name] return True def play_bgm(self, name=None, store_as_current=True, start=0): @@ -236,8 +253,7 @@ class BGM(GameChild): class SoundEffect(GameChild, pygame.mixer.Sound): - def __init__(self, parent, path, volume=1.0, loops=0, fade_out_length=0, - fade_in_length=0, maxtime=0): + def __init__(self, parent, path, volume=1.0, loops=0, fade_out_length=0, fade_in_length=0, maxtime=0): self.path = path GameChild.__init__(self, parent) pygame.mixer.Sound.__init__(self, path) @@ -248,10 +264,8 @@ class SoundEffect(GameChild, pygame.mixer.Sound): self.fade_in_length = fade_in_length self.maxtime = maxtime - def play(self, loops=None, maxtime=None, fade_ms=None, position=None, - x=None): - self.set_volume( - self.local_volume * self.get_configuration("audio", "volume")) + def play(self, loops=None, maxtime=None, fade_ms=None, position=None, x=None): + self.set_volume(self.local_volume * self.get_configuration("audio", "volume")) if loops is None: loops = self.loops if maxtime is None: @@ -268,8 +282,7 @@ class SoundEffect(GameChild, pygame.mixer.Sound): return channel def get_panning(self, position): - return 1 - max(0, ((position - .5) * 2)), \ - 1 + min(0, ((position - .5) * 2)) + return 1 - max(0, ((position - .5) * 2)), 1 + min(0, ((position - .5) * 2)) def adjust_volume(self, increment): self.local_volume += increment diff --git a/pgfw/extension.py b/pgfw/extension.py index 69c864e..feebba3 100644 --- a/pgfw/extension.py +++ b/pgfw/extension.py @@ -181,8 +181,19 @@ def get_value_in_range(start, end, position, reverse=False): position = 1 - position return (end - start) * position + start -def get_boxed_surface(surface, background=None, border=None, border_width=1, - padding=0): +def fill_borders(surface, color=Color(0, 0, 0), thickness=1, rect=None, flags=0, include=(True, True, True, True)): + if rect is None: + rect = surface.get_rect() + if include[0]: + surface.fill(color, (rect.left, rect.top, rect.w, thickness), flags) + if include[1]: + surface.fill(color, (rect.right - thickness, rect.top + thickness, thickness, rect.h - thickness * 2), flags) + if include[2]: + surface.fill(color, (rect.left, rect.bottom - thickness, rect.w, thickness), flags) + if include[3]: + surface.fill(color, (rect.left, rect.top + thickness, thickness, rect.h - thickness * 2), flags) + +def get_boxed_surface(surface, background=None, border=None, border_width=1, padding=0): if padding: if isinstance(padding, int): padding = [padding] * 2 @@ -225,7 +236,8 @@ def render_box(font=None, text=None, antialias=True, color=(0, 0, 0), background surface = container else: surface = pygame.Surface((width, height), SRCALPHA) - surface.fill(background) + if background is not None: + surface.fill(background) return get_boxed_surface(surface, background, border, border_width, padding) def get_wrapped_text_surface(font, text, width, antialias=True, color=(0, 0, 0), @@ -491,3 +503,11 @@ def compute_bezier_points(vertices, numPoints=60): secondFDY += thirdFDY points.append(Vector(pointX, pointY)) return points + +def get_marching_ants_color(position, time=0, colors=((0, 0, 0), (255, 255, 255))): + return Color(*(colors[0], colors[1])[((position / 2) % 2 + (time % 2)) % 2]) + +def diagonal_to_rect(start, end): + sx, sy = start + ex, ey = end + return Rect(min(sx, ex), min(sy, ey), abs(sx - ex), abs(ex - ey))