From 58ab5aa854268465807d3a3daec7cd39cc9286f9 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Thu, 20 Jun 2024 02:03:06 -0400 Subject: [PATCH 1/9] A new try at sound panning with walking. --- __init__.py | 59 ++++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/__init__.py b/__init__.py index 901d315..16a4b4c 100755 --- a/__init__.py +++ b/__init__.py @@ -173,47 +173,42 @@ def cut_scene(sounds, soundName): pygame.mixer.stop() pygame.event.pump() -def obj_play(sounds, soundName, playerPos, objPos): - distance = playerPos - objPos - if distance > 9 or distance < -9: +def obj_play(sounds, sound_name, player_pos, obj_pos): + distance = player_pos - obj_pos + if abs(distance) > 9: # The item is out of range, so play it at 0 left = 0 right = 0 - elif distance == 0: - left = 0.9 - right = 0.9 else: - angle = math.radians(distance * 5) - left = math.sqrt(2)/2.0 * (math.cos(angle) + math.sin(angle)) - right = math.sqrt(2)/2.0 * (math.cos(angle) - math.sin(angle)) - if left < 0: left *= -1 - if right < 0: right *= -1 - # x is the channel for the sound - x = sounds[soundName].play(-1) + # Calculate the panning based on the distance + left = max(0, 1 - (distance / 9)) + right = max(0, 1 + (distance / 9)) + left = min(1, left) + right = min(1, right) + # Play the sound on a new channel + channel = sounds[sound_name].play(-1) # Apply the position information to the channel - x.set_volume(left, right) - # return the channel so that it can be used in the update and stop functions. - return x - -def obj_update(x, playerPos, objPos): - distance = playerPos - objPos - if distance > 9 or distance < -9: + channel.set_volume(left, right) + # Return the channel so that it can be used in the update and stop functions. + return channel + +def obj_update(channel, player_pos, obj_pos): + distance = player_pos - obj_pos + if abs(distance) > 9: left = 0 right = 0 - elif distance == 0: - left = 0.9 - right = 0.9 else: - angle = math.radians(distance * 5) - left = math.sqrt(2)/2.0 * (math.cos(angle) + math.sin(angle)) - right = math.sqrt(2)/2.0 * (math.cos(angle) - math.sin(angle)) - if left < 0: left *= -1 - if right < 0: right *= -1 + # Calculate the panning based on the distance + left = max(0, 1 - (distance / 9)) + right = max(0, 1 + (distance / 9)) + left = min(1, left) + right = min(1, right) # Apply the position information to the channel - x.set_volume(left, right) - # return the channel - return x - + channel.set_volume(left, right) + # Return the channel + return channel + +soundData def obj_stop(x): # Tries to stop a playing object channel try: From 0ef11785ec7d0d8b21955576b4bfe93f72267d0e Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Fri, 5 Jul 2024 17:04:12 -0400 Subject: [PATCH 2/9] Revert "A new try at sound panning with walking." This reverts commit 58ab5aa854268465807d3a3daec7cd39cc9286f9. --- __init__.py | 59 +++++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/__init__.py b/__init__.py index 16a4b4c..901d315 100755 --- a/__init__.py +++ b/__init__.py @@ -173,42 +173,47 @@ def cut_scene(sounds, soundName): pygame.mixer.stop() pygame.event.pump() -def obj_play(sounds, sound_name, player_pos, obj_pos): - distance = player_pos - obj_pos - if abs(distance) > 9: +def obj_play(sounds, soundName, playerPos, objPos): + distance = playerPos - objPos + if distance > 9 or distance < -9: # The item is out of range, so play it at 0 left = 0 right = 0 + elif distance == 0: + left = 0.9 + right = 0.9 else: - # Calculate the panning based on the distance - left = max(0, 1 - (distance / 9)) - right = max(0, 1 + (distance / 9)) - left = min(1, left) - right = min(1, right) - # Play the sound on a new channel - channel = sounds[sound_name].play(-1) + angle = math.radians(distance * 5) + left = math.sqrt(2)/2.0 * (math.cos(angle) + math.sin(angle)) + right = math.sqrt(2)/2.0 * (math.cos(angle) - math.sin(angle)) + if left < 0: left *= -1 + if right < 0: right *= -1 + # x is the channel for the sound + x = sounds[soundName].play(-1) # Apply the position information to the channel - channel.set_volume(left, right) - # Return the channel so that it can be used in the update and stop functions. - return channel - -def obj_update(channel, player_pos, obj_pos): - distance = player_pos - obj_pos - if abs(distance) > 9: + x.set_volume(left, right) + # return the channel so that it can be used in the update and stop functions. + return x + +def obj_update(x, playerPos, objPos): + distance = playerPos - objPos + if distance > 9 or distance < -9: left = 0 right = 0 + elif distance == 0: + left = 0.9 + right = 0.9 else: - # Calculate the panning based on the distance - left = max(0, 1 - (distance / 9)) - right = max(0, 1 + (distance / 9)) - left = min(1, left) - right = min(1, right) + angle = math.radians(distance * 5) + left = math.sqrt(2)/2.0 * (math.cos(angle) + math.sin(angle)) + right = math.sqrt(2)/2.0 * (math.cos(angle) - math.sin(angle)) + if left < 0: left *= -1 + if right < 0: right *= -1 # Apply the position information to the channel - channel.set_volume(left, right) - # Return the channel - return channel - -soundData + x.set_volume(left, right) + # return the channel + return x + def obj_stop(x): # Tries to stop a playing object channel try: From 0c73e988769740f1586861a383338307f7d6769d Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Fri, 5 Jul 2024 17:24:23 -0400 Subject: [PATCH 3/9] Improved sound while walking on left/right only. --- __init__.py | 73 +++++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/__init__.py b/__init__.py index 901d315..5107341 100755 --- a/__init__.py +++ b/__init__.py @@ -173,45 +173,46 @@ def cut_scene(sounds, soundName): pygame.mixer.stop() pygame.event.pump() -def obj_play(sounds, soundName, playerPos, objPos): - distance = playerPos - objPos - if distance > 9 or distance < -9: - # The item is out of range, so play it at 0 - left = 0 - right = 0 - elif distance == 0: - left = 0.9 - right = 0.9 + +def calculate_volume_and_pan(player_pos, obj_pos): + distance = abs(player_pos - obj_pos) + max_distance = 12 # Maximum audible distance + if distance > max_distance: + return 0, 0, 0 # No sound if out of range + # Calculate volume (non-linear scaling for more noticeable changes) + volume = ((max_distance - distance) / max_distance) ** 1.5 + # Determine left/right based on relative position + if player_pos < obj_pos: + # Object is to the right + left = max(0, 1 - (obj_pos - player_pos) / max_distance) + right = 1 + elif player_pos > obj_pos: + # Object is to the left + left = 1 + right = max(0, 1 - (player_pos - obj_pos) / max_distance) else: - angle = math.radians(distance * 5) - left = math.sqrt(2)/2.0 * (math.cos(angle) + math.sin(angle)) - right = math.sqrt(2)/2.0 * (math.cos(angle) - math.sin(angle)) - if left < 0: left *= -1 - if right < 0: right *= -1 - # x is the channel for the sound + # Player is on the object + left = right = 1 + return volume, left, right + +def obj_play(sounds, soundName, player_pos, obj_pos): + volume, left, right = calculate_volume_and_pan(player_pos, obj_pos) + if volume == 0: + return None # Don't play if out of range + # Play the sound on a new channel x = sounds[soundName].play(-1) - # Apply the position information to the channel - x.set_volume(left, right) - # return the channel so that it can be used in the update and stop functions. + # Apply the volume and pan + x.set_volume(volume * left, volume * right) return x - -def obj_update(x, playerPos, objPos): - distance = playerPos - objPos - if distance > 9 or distance < -9: - left = 0 - right = 0 - elif distance == 0: - left = 0.9 - right = 0.9 - else: - angle = math.radians(distance * 5) - left = math.sqrt(2)/2.0 * (math.cos(angle) + math.sin(angle)) - right = math.sqrt(2)/2.0 * (math.cos(angle) - math.sin(angle)) - if left < 0: left *= -1 - if right < 0: right *= -1 - # Apply the position information to the channel - x.set_volume(left, right) - # return the channel +def obj_update(x, player_pos, obj_pos): + if x is None: + return None + volume, left, right = calculate_volume_and_pan(player_pos, obj_pos) + if volume == 0: + x.stop() + return None + # Apply the volume and pan + x.set_volume(volume * left, volume * right) return x def obj_stop(x): From fabf48ff426283b50f0db100aafaf3be9431f10a Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sat, 13 Jul 2024 03:03:32 -0400 Subject: [PATCH 4/9] Powerbars added and working. --- __init__.py | 76 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 11 deletions(-) diff --git a/__init__.py b/__init__.py index 5107341..3a5e696 100755 --- a/__init__.py +++ b/__init__.py @@ -29,6 +29,7 @@ except ImportError: print("No other speech providers found.") exit() import math +import numpy as np import time localConfig = configparser.ConfigParser() @@ -148,19 +149,69 @@ def initialize_gui(gameTitle): pygame.display.set_mode((320, 200)) pygame.display.set_caption(gameTitle) # Set 32 channels for sound by default + pygame.mixer.pre_init(44100, -16, 2, 1024) pygame.mixer.init() pygame.mixer.set_num_channels(32) # Reserve the cut scene channel pygame.mixer.set_reserved(0) # Load sounds from the sound directory and creates a list like that {'bottle': 'bottle.ogg'} - soundFiles = [f for f in listdir("sounds/") if isfile(join("sounds/", f)) and (f.split('.')[1].lower() in ["ogg","wav"])] - #lets make a dict with pygame.mixer.Sound() objects {'bottle':} - soundData = {} - for f in soundFiles: - soundData[f.split('.')[0]] = pygame.mixer.Sound("sounds/" + f) - soundData['game-intro'].play() - time.sleep(soundData['game-intro'].get_length()) - return soundData + try: + soundFiles = [f for f in listdir("sounds/") if isfile(join("sounds/", f)) and (f.split('.')[1].lower() in ["ogg","wav"])] + #lets make a dict with pygame.mixer.Sound() objects {'bottle':} + soundData = {} + for f in soundFiles: + soundData[f.split('.')[0]] = pygame.mixer.Sound("sounds/" + f) + soundData['game-intro'].play() + time.sleep(soundData['game-intro'].get_length()) + return soundData + except Exception as e: + return False + +def generate_tone(frequency, duration=0.1, sample_rate=44100, volume = 0.2): + t = np.linspace(0, duration, int(sample_rate * duration), False) + tone = np.sin(2 * np.pi * frequency * t) + stereo_tone = np.vstack((tone, tone)).T # Create a 2D array for stereo + stereo_tone = (stereo_tone * 32767).astype(np.int16) + stereo_tone = (stereo_tone * 32767 * volume).astype(np.int16) # Apply volume + stereo_tone = np.ascontiguousarray(stereo_tone) # Ensure C-contiguous array + return pygame.sndarray.make_sound(stereo_tone) + +def x_powerbar(): + clock = pygame.time.Clock() + position = -50 + direction = 1 + while True: + frequency = 440 # A4 note + left_volume = (position + 50) / 100 + right_volume = (50 - position) / 100 + tone = generate_tone(frequency) + channel = tone.play() + channel.set_volume(left_volume, right_volume) + for event in pygame.event.get(): + if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: + channel.stop() + return position + position += direction + if position >= 50 or position <= -50: + direction *= -1 + clock.tick(45) # Speed of bar + +def y_powerbar(): + clock = pygame.time.Clock() + power = 0 + direction = 1 # 1 for increasing, -1 for decreasing + while True: + frequency = 220 + (power * 5) # Adjust these values to change the pitch range + tone = generate_tone(frequency) + channel = tone.play() + for event in pygame.event.get(): + if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: + channel.stop() + return power + power += direction + if power >= 100 or power <= 0: + direction *= -1 # Reverse direction at limits + clock.tick(45) def cut_scene(sounds, soundName): pygame.event.clear() @@ -327,9 +378,12 @@ def game_menu(sounds, *options): if pygame.mixer.music.get_busy(): pygame.mixer.music.unpause() else: - pygame.mixer.music.load("sounds/music_menu.ogg") - pygame.mixer.music.set_volume(0.75) - pygame.mixer.music.play(-1) + try: + pygame.mixer.music.load("sounds/music_menu.ogg") + pygame.mixer.music.set_volume(0.75) + pygame.mixer.music.play(-1) + except: + pass i = 0 # j keeps track of last spoken index so it isn't voiced on key up. j = -1 From 0e9c52f5e1e8cbc9f004dd58ec25f77b0d2dbe32 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sun, 14 Jul 2024 03:51:35 -0400 Subject: [PATCH 5/9] A few fixes for x-powerbar, more accurately exiting when exit keys are pressed, etc. --- __init__.py | 66 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/__init__.py b/__init__.py index 3a5e696..0a54971 100755 --- a/__init__.py +++ b/__init__.py @@ -124,6 +124,12 @@ def speak(text, interupt = True): s.speak(text, interrupt=True) +def check_for_exit(): + for event in pygame.event.get(): + if event.type == pygame.KEYDOWN and event.key in [pygame.K_ESCAPE, pygame.K_q]: + exit_game() + pygame.event.pump() + def exit_game(): if speechProvider == "speechd": spd.close() pygame.mixer.music.stop() @@ -154,18 +160,19 @@ def initialize_gui(gameTitle): pygame.mixer.set_num_channels(32) # Reserve the cut scene channel pygame.mixer.set_reserved(0) - # Load sounds from the sound directory and creates a list like that {'bottle': 'bottle.ogg'} + # Load sounds from the sound directory and creates a list like {'bottle': 'bottle.ogg'} try: soundFiles = [f for f in listdir("sounds/") if isfile(join("sounds/", f)) and (f.split('.')[1].lower() in ["ogg","wav"])] - #lets make a dict with pygame.mixer.Sound() objects {'bottle':} - soundData = {} - for f in soundFiles: - soundData[f.split('.')[0]] = pygame.mixer.Sound("sounds/" + f) - soundData['game-intro'].play() - time.sleep(soundData['game-intro'].get_length()) - return soundData except Exception as e: - return False + print("No sounds found.") + speak("No sounds found.", False) + #lets make a dict with pygame.mixer.Sound() objects {'bottle':} + soundData = {} + for f in soundFiles: + soundData[f.split('.')[0]] = pygame.mixer.Sound("sounds/" + f) + soundData['game-intro'].play() + time.sleep(soundData['game-intro'].get_length()) + return soundData def generate_tone(frequency, duration=0.1, sample_rate=44100, volume = 0.2): t = np.linspace(0, duration, int(sample_rate * duration), False) @@ -178,23 +185,27 @@ def generate_tone(frequency, duration=0.1, sample_rate=44100, volume = 0.2): def x_powerbar(): clock = pygame.time.Clock() - position = -50 - direction = 1 + position = -50 # Start from the leftmost position + direction = 1 # Move right initially while True: frequency = 440 # A4 note - left_volume = (position + 50) / 100 - right_volume = (50 - position) / 100 + left_volume = (50 - position) / 100 + right_volume = (position + 50) / 100 tone = generate_tone(frequency) channel = tone.play() channel.set_volume(left_volume, right_volume) for event in pygame.event.get(): if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: channel.stop() - return position + return position # This will return a value between -50 and 50 position += direction - if position >= 50 or position <= -50: - direction *= -1 - clock.tick(45) # Speed of bar + if position > 50: + position = 50 + direction = -1 + elif position < -50: + position = -50 + direction = 1 + clock.tick(40) # Speed of bar def y_powerbar(): clock = pygame.time.Clock() @@ -211,7 +222,8 @@ def y_powerbar(): power += direction if power >= 100 or power <= 0: direction *= -1 # Reverse direction at limits - clock.tick(45) + check_for_exit() + clock.tick(40) def cut_scene(sounds, soundName): pygame.event.clear() @@ -274,6 +286,22 @@ def obj_stop(x): except: return x +def play_ambiance(sounds, soundNames, probability, randomLocation = False): + # Check if any of the sounds in the list is already playing + for soundName in soundNames: + if pygame.mixer.find_channel(True) and pygame.mixer.find_channel(True).get_busy(): + return + if random.randint(1, 100) > probability: + return + # Choose a random sound from the list + ambianceSound = random.choice(soundNames) + channel = sounds[ambianceSound].play() + if randomLocation and channel: + left_volume = random.random() + right_volume = random.random() + channel.set_volume(left_volume, right_volume) + return channel # Return the channel object for potential further manipulation + def play_random(sounds, soundName, pause = False, interrupt = False): key = [] for i in sounds.keys(): @@ -343,7 +371,7 @@ def learn_sounds(sounds): loop = True pygame.mixer.music.pause() i = 0 - soundFiles = [f for f in listdir("sounds/") if isfile(join("sounds/", f)) and (f.split('.')[1].lower() in ["ogg","wav"]) and (f.split('.')[0].lower() not in ["game-intro", "music_menu"])] + soundFiles = [f for f in listdir("sounds/") if isfile(join("sounds/", f)) and (f.split('.')[1].lower() in ["ogg","wav"]) and (f.split('.')[0].lower() not in ["game-intro", "music_menu"]) and (not f.lower().startswith("_"))] # j keeps track of last spoken index so it isn't voiced on key up. j = -1 while loop == True: From 38522aee78a4d13d79eda73175ecbdf191227054 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Mon, 15 Jul 2024 19:52:02 -0400 Subject: [PATCH 6/9] First pass at creating requirements files. --- requirements.txt | 7 +++++++ requirements_linux.txt | 2 ++ 2 files changed, 9 insertions(+) create mode 100644 requirements.txt create mode 100644 requirements_linux.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f3dd51e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +pygame>=2.0.0 +pyperclip>=1.8.0 +requests>=2.25.0 +pyxdg>=0.27 +setproctitle>=1.2.0 +numpy>=1.19.0 +accessible-output2>=0.14 diff --git a/requirements_linux.txt b/requirements_linux.txt new file mode 100644 index 0000000..18a4555 --- /dev/null +++ b/requirements_linux.txt @@ -0,0 +1,2 @@ +-r requirements.txt +python-speechd>=0.11.1 From df386cbbd9da3df42b2c5fa879aed61aae59103e Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Tue, 16 Jul 2024 14:22:36 -0400 Subject: [PATCH 7/9] Improved check_for_exit function. --- __init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index 0a54971..f5037b4 100755 --- a/__init__.py +++ b/__init__.py @@ -126,8 +126,9 @@ def speak(text, interupt = True): def check_for_exit(): for event in pygame.event.get(): - if event.type == pygame.KEYDOWN and event.key in [pygame.K_ESCAPE, pygame.K_q]: - exit_game() + if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: + return True + return False pygame.event.pump() def exit_game(): From 9a6d6374f9583e127cb72c88df7a5a64090ca68d Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Mon, 22 Jul 2024 16:08:42 -0400 Subject: [PATCH 8/9] Added text along with the speak command. Updated window size. --- __init__.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/__init__.py b/__init__.py index f5037b4..94f0c50 100755 --- a/__init__.py +++ b/__init__.py @@ -15,6 +15,7 @@ import pyperclip import random import re import requests +import textwrap import webbrowser # Global variable for speech provider try: @@ -114,15 +115,33 @@ def read_config(readGlobal = False): globalConfig.read_file(configfile) except: pass - -def speak(text, interupt = True): + +def speak(text, interupt=True): if speechProvider == "speechd": - if interupt == True: spd.cancel() + if interupt: spd.cancel() spd.say(text) else: if speechProvider == "accessible_output2": s.speak(text, interrupt=True) - + # Display the text on screen + screen = pygame.display.get_surface() + font = pygame.font.Font(None, 36) + # Wrap the text + maxWidth = screen.get_width() - 40 # Leave a 20-pixel margin on each side + wrappedText = textwrap.wrap(text, width=maxWidth // font.size('A')[0]) + # Render each line + textSurfaces = [font.render(line, True, (255, 255, 255)) for line in wrappedText] + screen.fill((0, 0, 0)) # Clear screen with black + # Calculate total height of text block + totalHeight = sum(surface.get_height() for surface in textSurfaces) + # Start y-position (centered vertically) + currentY = (screen.get_height() - totalHeight) // 2 + # Blit each line of text + for surface in textSurfaces: + textRect = surface.get_rect(center=(screen.get_width() // 2, currentY + surface.get_height() // 2)) + screen.blit(surface, textRect) + currentY += surface.get_height() + pygame.display.flip() def check_for_exit(): for event in pygame.event.get(): @@ -153,7 +172,7 @@ def initialize_gui(gameTitle): # start pygame pygame.init() # start the display (required by the event loop) - pygame.display.set_mode((320, 200)) + pygame.display.set_mode((800, 600)) pygame.display.set_caption(gameTitle) # Set 32 channels for sound by default pygame.mixer.pre_init(44100, -16, 2, 1024) From 428a48678d51567fb3a88e031df1232818d60a50 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Mon, 22 Jul 2024 22:20:15 -0400 Subject: [PATCH 9/9] Power bars are now visual as well as audio. --- __init__.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/__init__.py b/__init__.py index 94f0c50..d2bac2c 100755 --- a/__init__.py +++ b/__init__.py @@ -205,16 +205,26 @@ def generate_tone(frequency, duration=0.1, sample_rate=44100, volume = 0.2): def x_powerbar(): clock = pygame.time.Clock() + screen = pygame.display.get_surface() position = -50 # Start from the leftmost position direction = 1 # Move right initially + barHeight = 20 while True: frequency = 440 # A4 note - left_volume = (50 - position) / 100 - right_volume = (position + 50) / 100 + leftVolume = (50 - position) / 100 + rightVolume = (position + 50) / 100 tone = generate_tone(frequency) channel = tone.play() - channel.set_volume(left_volume, right_volume) + channel.set_volume(leftVolume, rightVolume) + # Visual representation + screen.fill((0, 0, 0)) + barWidth = screen.get_width() - 40 # Leave 20px margin on each side + pygame.draw.rect(screen, (100, 100, 100), (20, screen.get_height() // 2 - barHeight // 2, barWidth, barHeight)) + markerPos = int(20 + (position + 50) / 100 * barWidth) + pygame.draw.rect(screen, (255, 0, 0), (markerPos - 5, screen.get_height() // 2 - barHeight, 10, barHeight * 2)) + pygame.display.flip() for event in pygame.event.get(): + check_for_exit() if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: channel.stop() return position # This will return a value between -50 and 50 @@ -229,20 +239,29 @@ def x_powerbar(): def y_powerbar(): clock = pygame.time.Clock() + screen = pygame.display.get_surface() power = 0 direction = 1 # 1 for increasing, -1 for decreasing + barWidth = 20 while True: frequency = 220 + (power * 5) # Adjust these values to change the pitch range tone = generate_tone(frequency) channel = tone.play() + # Visual representation + screen.fill((0, 0, 0)) + barHeight = screen.get_height() - 40 # Leave 20px margin on top and bottom + pygame.draw.rect(screen, (100, 100, 100), (screen.get_width() // 2 - barWidth // 2, 20, barWidth, barHeight)) + markerPos = int(20 + (100 - power) / 100 * barHeight) + pygame.draw.rect(screen, (255, 0, 0), (screen.get_width() // 2 - barWidth, markerPos - 5, barWidth * 2, 10)) + pygame.display.flip() for event in pygame.event.get(): + check_for_exit() if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: channel.stop() return power power += direction if power >= 100 or power <= 0: direction *= -1 # Reverse direction at limits - check_for_exit() clock.tick(40) def cut_scene(sounds, soundName):