libstormgames/libstormgames.py

327 lines
11 KiB
Python
Raw Normal View History

2019-12-02 08:45:03 -05:00
#!/bin/python
# -*- coding: utf-8 -*-
"""Standard initializations and functions shared by all games."""
2019-12-08 14:55:41 -05:00
from sys import exit
2019-12-02 08:45:03 -05:00
import configparser
import os
from os import listdir
from os.path import isfile, join
from inspect import isfunction
from xdg import BaseDirectory
2019-12-11 08:04:56 -05:00
from setproctitle import setproctitle
2019-12-02 08:45:03 -05:00
import pygame
import pyperclip
import random
2019-12-04 13:39:16 -05:00
import re
2019-12-02 08:45:03 -05:00
import requests
import webbrowser
# Global variable for speech provider
try:
import speechd
spd = speechd.Client()
speechProvider = "speechd"
except ImportError:
import accessible_output2.outputs.auto
s = accessible_output2.outputs.auto.Auto()
speechProvider = "accessible_output2"
except ImportError:
print("No other speech providers found.")
exit()
2019-12-02 08:45:03 -05:00
import time
localConfig = configparser.ConfigParser()
globalConfig = configparser.ConfigParser()
class scoreboard():
'Handles scores and top 10'
def __init__(self, startingScore = 0):
read_config()
try:
localConfig.add_section("scoreboard")
except:
2020-08-30 01:23:32 -04:00
speak("Could not create scoreboard.")
self.score = startingScore
self.oldScores = []
for i in range(1, 11):
try:
self.oldScores.insert(i - 1, localConfig.getint("scoreboard", i))
except:
pass
self.oldScores.insert(i - 1, 0)
for i in range(1, 11):
if self.oldScores[i - 1] == None:
self.oldScores[i - 1] = 0
def __del__(self):
self.Update_Scores()
try:
write_config()
except:
2020-08-30 01:23:32 -04:00
speak("Could not update configuration file."
def Decrease_Score(self, points = 1):
self.score -= points
def Get_High_Score(self, position = 1):
return self.oldScores[position - 1]
def Get_Score(self):
return self.score
def Increase_Score(self, points = 1):
self.score += points
2019-12-11 23:31:19 -05:00
def New_High_Score(self):
for i, j in enumerate(self.oldScores):
if self.score > j: return i + 1
return None
def Update_Scores(self):
# Update the scores
for i, j in enumerate(self.oldScores):
if self.score > j:
2020-08-29 22:11:06 -04:00
# Move the old high score down the list
2020-08-30 01:23:32 -04:00
if i < 9:
2020-08-29 22:11:06 -04:00
self.oldScores[i + 1] = j
self.oldScores[i] = self.score
break
# Update the scoreboard section of the games config file.
for i, j in enumerate(self.oldScores):
localConfig.set("scoreboard", str(i + 1), str(j))
2019-12-02 08:45:03 -05:00
def write_config(writeGlobal = False):
if writeGlobal == False:
with open(gamePath + "/config.ini", 'w') as configfile:
2019-12-02 08:45:03 -05:00
localConfig.write(configfile)
else:
with open(globalPath + "/config.ini", 'w') as configfile:
2019-12-02 08:45:03 -05:00
globalConfig.write(configfile)
def read_config(readGlobal = False):
2019-12-02 08:45:03 -05:00
if readGlobal == False:
try:
with open(gamePath + "/config.ini", 'r') as configfile:
localConfig.read(configfile)
except:
pass
2019-12-02 08:45:03 -05:00
else:
try:
with open(globalPath + "/config.ini", 'r') as configfile:
globalConfig.read(configfile)
except:
pass
2019-12-02 08:45:03 -05:00
def speak(text, interupt = True):
if speechProvider == "speechd":
if interupt == True: spd.cancel()
spd.say(text)
else:
if speechProvider == "accessible_output2":
s.speak(text, interrupt=True)
2019-12-02 08:45:03 -05:00
def exit_game():
if speechProvider == "speechd": spd.close()
2019-12-02 08:45:03 -05:00
pygame.mixer.music.stop()
pygame.quit()
exit()
def initialize_gui(gameTitle):
# Check for, and possibly create, storm-games path
global globalPath
global gamePath
globalPath = BaseDirectory.xdg_config_home + "/storm-games"
gamePath = globalPath + "/" + str.lower(str.replace(gameTitle, " ", "-"))
2019-12-02 08:45:03 -05:00
if not os.path.exists(gamePath): os.makedirs(gamePath)
# Seed the random generator to the clock
random.seed()
# Set game's name
global gameName
gameName = gameTitle
2019-12-11 09:37:58 -05:00
setproctitle(str.lower(str.replace(gameTitle, " ", "")))
2019-12-02 08:45:03 -05:00
# start pygame
pygame.init()
# start the display (required by the event loop)
pygame.display.set_mode((320, 200))
pygame.display.set_caption(gameTitle)
2019-12-05 12:33:54 -05:00
# Set 32 channels for sound by default
pygame.mixer.init()
pygame.mixer.set_num_channels(32)
# Reserve the cut scene channel
pygame.mixer.set_reserved(0)
2019-12-02 08:45:03 -05:00
# 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':<soundobject>}
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 cut_scene(sounds, soundName):
pygame.event.clear()
pygame.mixer.stop()
c = pygame.mixer.Channel(0)
c.play(sounds[soundName])
while pygame.mixer.get_busy():
2019-12-05 12:33:54 -05:00
event = pygame.event.poll()
2019-12-06 09:40:36 -05:00
if event.type == pygame.KEYDOWN and event.key in [pygame.K_ESCAPE, pygame.K_RETURN, pygame.K_SPACE]:
pygame.mixer.stop()
pygame.event.pump()
2019-12-05 12:33:54 -05:00
def play_random(sounds, soundName, pause = False, interrupt = False):
key = []
for i in sounds.keys():
if re.match("^" + soundName + ".*", i):
key.append(i)
randomKey = random.choice(key)
2019-12-05 12:33:54 -05:00
if interrupt == False:
sounds[randomKey].play()
else:
cut_scene(sounds, randomKey)
# Cut scenes override the pause option
return
if pause == True:
time.sleep(sounds[randomKey].get_length())
2019-12-04 13:39:16 -05:00
2019-12-02 08:45:03 -05:00
def instructions():
# Read in the instructions file
try:
with open('files/instructions.txt', 'r') as f:
info = f.readlines()
except:
info = ["Instructions file is missing."]
display_text(info)
def credits():
2019-12-08 16:25:11 -05:00
# Read in the credits file.
try:
with open('files/credits.txt', 'r') as f:
info = f.readlines()
# Add the header
info.insert(0, gameName + ": brought to you by Storm Dragon")
except:
info = ["Credits file is missing."]
2019-12-02 08:45:03 -05:00
display_text(info)
def display_text(text):
i = 0
text.insert(0, "Press space to read the whole text. Use up and down arrows to navigate the text line by line. Press c to copy the current line to the clipboard or t to copy the entire text. Press enter or escape when you are done reading.")
text.append("End of text.")
speak(text[i])
while True:
event = pygame.event.wait()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN: return
if event.key == pygame.K_DOWN and i < len(text) - 1: i = i + 1
if event.key == pygame.K_UP and i > 0: i = i - 1
if event.key == pygame.K_SPACE:
speak(' '.join(text[1:]))
2019-12-02 08:45:03 -05:00
else:
speak(text[i])
if event.key == pygame.K_c:
try:
pyperclip.copy(text[i])
speak("Copied " + text[i] + " to the clipboard.")
except:
speak("Failed to copy the text to the clipboard.")
if event.key == pygame.K_t:
try:
pyperclip.copy(' '.join(text[1:-1]))
2019-12-02 08:45:03 -05:00
speak("Copied entire message to the clipboard.")
except:
speak("Failed to copy the text to the clipboard.")
event = pygame.event.clear()
time.sleep(0.001)
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"])]
# j keeps track of last spoken index so it isn't voiced on key up.
j = -1
while loop == True:
if i != j:
speak(soundFiles[i][:-4])
j = i
event = pygame.event.wait()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: return "menu"
if event.key == pygame.K_DOWN and i < len(soundFiles) - 1:
pygame.mixer.stop()
2019-12-02 08:45:03 -05:00
i = i + 1
if event.key == pygame.K_UP and i > 0:
pygame.mixer.stop()
2019-12-02 08:45:03 -05:00
i = i - 1
if event.key == pygame.K_RETURN:
try:
soundName = soundFiles[i][:-4]
pygame.mixer.stop()
2019-12-02 08:45:03 -05:00
sounds[soundName].play()
continue
except:
j = -1
speak("Could not play sound.")
continue
event = pygame.event.clear()
time.sleep(0.001)
def game_menu(sounds, *options):
2019-12-02 08:45:03 -05:00
loop = True
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)
i = 0
# j keeps track of last spoken index so it isn't voiced on key up.
j = -1
while loop == True:
if i != j:
speak(options[i])
j = i
event = pygame.event.wait()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: exit_game()
if event.key == pygame.K_DOWN and i < len(options) - 1:
i = i + 1
try:
sounds['menu-move'].play()
except:
pass
2019-12-02 08:45:03 -05:00
if options[i] != "donate": pygame.mixer.music.unpause()
if event.key == pygame.K_UP and i > 0:
i = i - 1
try:
sounds['menu-move'].play()
except:
pass
2019-12-02 08:45:03 -05:00
if options[i] != "donate": pygame.mixer.music.unpause()
if event.key == pygame.K_RETURN:
try:
j = -1
try:
sounds['menu-select'].play()
time.sleep(sounds['menu-select'].get_length())
except:
pass
2019-12-02 08:45:03 -05:00
eval(options[i] + "()")
continue
except:
j = -1
return options[i]
continue
event = pygame.event.clear()
time.sleep(0.001)
def donate():
pygame.mixer.music.pause()
2019-12-08 16:09:46 -05:00
webbrowser.open('https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=stormdragon2976@gmail.com&lc=US&item_name=Donation+to+Storm+Games&no_note=0&cn=&currency_code=USD&bn=PP-DonationsBF:btn_donateCC_LG.gif:NonHosted')