Compare commits

...

11 Commits

Author SHA1 Message Date
Storm Dragon
80fe2caff3 Oops, accidentally removed the obj_update function. 2025-02-03 23:59:46 -05:00
Storm Dragon
2df86c9c76 Add the ability for obj_play to play a sound once. 2025-02-03 23:49:08 -05:00
Storm Dragon
5fa90f9e84 Updated play_falling_random. 2025-02-03 21:58:02 -05:00
Storm Dragon
658709ebce Random play functions for positional audio and positional falling audio. 2025-02-02 17:04:04 -05:00
Storm Dragon
d5c79c0770 Hopefully last fix to messagebox. This turned out to be harder than I originally thought. 2025-02-01 15:14:29 -05:00
Storm Dragon
24f9a126d4 I think I was over complicating it. 2025-02-01 15:11:22 -05:00
Storm Dragon
c316d4e570 I think I actually got it this time. 2025-02-01 15:05:13 -05:00
Storm Dragon
e66655d75f Another attempt to keep messagebox from double speaking. 2025-02-01 14:59:46 -05:00
Storm Dragon
c5406d5089 Attempt to keep messagebox from double speaking. 2025-02-01 14:53:55 -05:00
Storm Dragon
b5b472eebe Added simple message box for spoken text that might need to be repeated. 2025-02-01 14:41:52 -05:00
Storm Dragon
9f03de15b8 Add a text entry using wx. 2024-08-01 21:10:27 -04:00

View File

@@ -32,6 +32,7 @@ except ImportError:
import math
import numpy as np
import time
import wx
localConfig = configparser.ConfigParser()
globalConfig = configparser.ConfigParser()
@@ -116,6 +117,18 @@ def read_config(readGlobal = False):
except:
pass
def get_input(prompt = "Enter text:", text = ""):
app = wx.App(False)
dialog = wx.TextEntryDialog(None, prompt, "Input", text)
dialog.SetValue(text)
if dialog.ShowModal() == wx.ID_OK:
userInput = dialog.GetValue()
else:
userInput = None
dialog.Destroy()
return userInput
def speak(text, interupt=True):
if speechProvider == "speechd":
if interupt: spd.cancel()
@@ -297,15 +310,29 @@ def calculate_volume_and_pan(player_pos, obj_pos):
left = right = 1
return volume, left, right
def obj_play(sounds, soundName, player_pos, obj_pos):
def obj_play(sounds, soundName, player_pos, obj_pos, loop=True):
"""Play a sound with positional audio.
Args:
sounds: Dictionary of sound objects
soundName: Name of sound to play
player_pos: Player's position for audio panning
obj_pos: Object's position for audio panning
loop: Whether to loop the sound (default True)
Returns:
The sound channel object, or None if out of range
"""
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)
x = sounds[soundName].play(-1 if loop else 0) # -1 for loop, 0 for once
# Apply the volume and pan
x.set_volume(volume * left, volume * right)
if x:
x.set_volume(volume * left, volume * right)
return x
def obj_update(x, player_pos, obj_pos):
if x is None:
return None
@@ -356,6 +383,80 @@ def play_random(sounds, soundName, pause = False, interrupt = False):
if pause == True:
time.sleep(sounds[randomKey].get_length())
def play_random_positional(sounds, soundName, playerX, objectX):
"""Play a random sound with positional audio.
Args:
sounds: Dictionary of sound objects
soundName: Base name of sound (e.g. 'falling_skull' will match 'falling_skull1', 'falling_skull2', etc.)
playerX: Player's x position for audio panning
objectX: Object's x position for audio panning
Returns:
The sound channel object for updating position
"""
keys = [k for k in sounds.keys() if k.startswith(soundName)]
if not keys:
return None
randomKey = random.choice(keys)
volume, left, right = calculate_volume_and_pan(playerX, objectX)
if volume == 0:
return None
channel = sounds[randomKey].play()
if channel:
channel.set_volume(volume * left, volume * right)
return channel
def play_random_falling(sounds, soundName, playerX, objectX, startY, currentY=0, maxY=20, existingChannel=None):
"""Play or update a random sound with positional audio that increases in volume as it 'falls'.
Args:
sounds: Dictionary of sound objects
soundName: Base name of sound (e.g. 'falling_skull' will match 'falling_skull1', 'falling_skull2', etc.)
playerX: Player's x position for audio panning
objectX: Object's x position for audio panning
startY: Starting Y position (0-20, higher = quieter start)
currentY: Current Y position (0 = ground level)
maxY: Maximum Y value (default 20)
existingChannel: Existing sound channel to update instead of creating new one (default None)
Returns:
The sound channel object for updating position/volume, or None if sound should stop
"""
# Calculate horizontal positioning
volume, left, right = calculate_volume_and_pan(playerX, objectX)
# Calculate vertical fall volume multiplier (0 at maxY, 1 at y=0)
fallMultiplier = 1 - (currentY / maxY)
# Adjust final volumes
finalVolume = volume * fallMultiplier
finalLeft = left * finalVolume
finalRight = right * finalVolume
if existingChannel is not None:
if volume == 0: # Out of audible range
existingChannel.stop()
return None
existingChannel.set_volume(finalLeft, finalRight)
return existingChannel
else: # Need to create new channel
if volume == 0: # Don't start if out of range
return None
# Find matching sound files
keys = [k for k in sounds.keys() if k.startswith(soundName)]
if not keys:
return None
randomKey = random.choice(keys)
channel = sounds[randomKey].play()
if channel:
channel.set_volume(finalLeft, finalRight)
return channel
def instructions():
# Read in the instructions file
try:
@@ -406,6 +507,16 @@ def display_text(text):
event = pygame.event.clear()
time.sleep(0.001)
def messagebox(text):
speak(text + "\nPress any key to repeat or enter to continue.")
while True:
event = pygame.event.wait()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN:
return
else:
speak(text + "\nPress any key to repeat or enter to continue.")
def learn_sounds(sounds):
loop = True
pygame.mixer.music.pause()