Compare commits

..

No commits in common. "401b2a8527c6bb1d562f2fb79b4cbcbe9e783bf3" and "639198e8de8bf8921dc5177cbc9ec45ad4be371d" have entirely different histories.

3 changed files with 52 additions and 192 deletions

View File

@ -10,12 +10,11 @@ from os.path import isfile, join
from inspect import isfunction from inspect import isfunction
from xdg import BaseDirectory from xdg import BaseDirectory
from setproctitle import setproctitle from setproctitle import setproctitle
import pygame import pyglet
import pyperclip import pyperclip
import random import random
import re import re
import requests import requests
import textwrap
import webbrowser import webbrowser
# Global variable for speech provider # Global variable for speech provider
try: try:
@ -30,7 +29,6 @@ except ImportError:
print("No other speech providers found.") print("No other speech providers found.")
exit() exit()
import math import math
import numpy as np
import time import time
localConfig = configparser.ConfigParser() localConfig = configparser.ConfigParser()
@ -115,46 +113,20 @@ def read_config(readGlobal = False):
globalConfig.read_file(configfile) globalConfig.read_file(configfile)
except: except:
pass pass
def speak(text, interupt=True): def speak(text, interupt = True):
if speechProvider == "speechd": if speechProvider == "speechd":
if interupt: spd.cancel() if interupt == True: spd.cancel()
spd.say(text) spd.say(text)
else: else:
if speechProvider == "accessible_output2": if speechProvider == "accessible_output2":
s.speak(text, interrupt=True) 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():
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
return True
return False
pygame.event.pump()
def exit_game(): def exit_game():
if speechProvider == "speechd": spd.close() if speechProvider == "speechd": spd.close()
pygame.mixer.music.stop() # Close the pyglet window
pygame.quit() pyglet.app.exit()
exit()
def initialize_gui(gameTitle): def initialize_gui(gameTitle):
# Check for, and possibly create, storm-games path # Check for, and possibly create, storm-games path
@ -169,101 +141,18 @@ def initialize_gui(gameTitle):
global gameName global gameName
gameName = gameTitle gameName = gameTitle
setproctitle(str.lower(str.replace(gameTitle, " ", ""))) setproctitle(str.lower(str.replace(gameTitle, " ", "")))
# start pygame # init pyglet window
pygame.init() window = pyglet.window.Window(500, 300, gameTitle)
# start the display (required by the event loop)
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)
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 {'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"])]
soundFiles = [f for f in listdir("sounds/") if isfile(join("sounds/", f)) and (f.split('.')[1].lower() in ["ogg","wav"])] # make a dict with pyglet media {'bottle':<soundobject>}
except Exception as e:
print("No sounds found.")
speak("No sounds found.", False)
#lets make a dict with pygame.mixer.Sound() objects {'bottle':<soundobject>}
soundData = {} soundData = {}
for f in soundFiles: for f in soundFiles:
soundData[f.split('.')[0]] = pygame.mixer.Sound("sounds/" + f) soundData[f.split('.')[0]] = pyglet.media.load("sounds/" + f, streaming = False)
soundData['game-intro'].play() soundData['game-intro'].play()
time.sleep(soundData['game-intro'].get_length()) time.sleep(soundData['game-intro'].duration)
return soundData 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)
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()
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
leftVolume = (50 - position) / 100
rightVolume = (position + 50) / 100
tone = generate_tone(frequency)
channel = tone.play()
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
position += direction
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()
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
clock.tick(40)
def cut_scene(sounds, soundName): def cut_scene(sounds, soundName):
pygame.event.clear() pygame.event.clear()
pygame.mixer.stop() pygame.mixer.stop()
@ -275,46 +164,45 @@ def cut_scene(sounds, soundName):
pygame.mixer.stop() pygame.mixer.stop()
pygame.event.pump() pygame.event.pump()
def obj_play(sounds, soundName, playerPos, objPos):
def calculate_volume_and_pan(player_pos, obj_pos): distance = playerPos - objPos
distance = abs(player_pos - obj_pos) if distance > 9 or distance < -9:
max_distance = 12 # Maximum audible distance # The item is out of range, so play it at 0
if distance > max_distance: left = 0
return 0, 0, 0 # No sound if out of range right = 0
# Calculate volume (non-linear scaling for more noticeable changes) elif distance == 0:
volume = ((max_distance - distance) / max_distance) ** 1.5 left = 0.9
# Determine left/right based on relative position right = 0.9
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: else:
# Player is on the object angle = math.radians(distance * 5)
left = right = 1 left = math.sqrt(2)/2.0 * (math.cos(angle) + math.sin(angle))
return volume, left, right right = math.sqrt(2)/2.0 * (math.cos(angle) - math.sin(angle))
if left < 0: left *= -1
def obj_play(sounds, soundName, player_pos, obj_pos): if right < 0: right *= -1
volume, left, right = calculate_volume_and_pan(player_pos, obj_pos) # x is the channel for the sound
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)
# Apply the volume and pan # Apply the position information to the channel
x.set_volume(volume * left, volume * right) x.set_volume(left, right)
# return the channel so that it can be used in the update and stop functions.
return x return x
def obj_update(x, player_pos, obj_pos):
if x is None: def obj_update(x, playerPos, objPos):
return None distance = playerPos - objPos
volume, left, right = calculate_volume_and_pan(player_pos, obj_pos) if distance > 9 or distance < -9:
if volume == 0: left = 0
x.stop() right = 0
return None elif distance == 0:
# Apply the volume and pan left = 0.9
x.set_volume(volume * left, volume * right) 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
return x return x
def obj_stop(x): def obj_stop(x):
@ -325,22 +213,6 @@ def obj_stop(x):
except: except:
return x 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): def play_random(sounds, soundName, pause = False, interrupt = False):
key = [] key = []
for i in sounds.keys(): for i in sounds.keys():
@ -410,7 +282,7 @@ def learn_sounds(sounds):
loop = True loop = True
pygame.mixer.music.pause() pygame.mixer.music.pause()
i = 0 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"]) and (not f.lower().startswith("_"))] 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"])]
# j keeps track of last spoken index so it isn't voiced on key up. # j keeps track of last spoken index so it isn't voiced on key up.
j = -1 j = -1
while loop == True: while loop == True:
@ -445,12 +317,9 @@ def game_menu(sounds, *options):
if pygame.mixer.music.get_busy(): if pygame.mixer.music.get_busy():
pygame.mixer.music.unpause() pygame.mixer.music.unpause()
else: else:
try: pygame.mixer.music.load("sounds/music_menu.ogg")
pygame.mixer.music.load("sounds/music_menu.ogg") pygame.mixer.music.set_volume(0.75)
pygame.mixer.music.set_volume(0.75) pygame.mixer.music.play(-1)
pygame.mixer.music.play(-1)
except:
pass
i = 0 i = 0
# j keeps track of last spoken index so it isn't voiced on key up. # j keeps track of last spoken index so it isn't voiced on key up.
j = -1 j = -1

View File

@ -1,7 +0,0 @@
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

View File

@ -1,2 +0,0 @@
-r requirements.txt
python-speechd>=0.11.1