Как стать автором
Обновить

Доступность игр на pygame

Python *Accessibility *
Из песочницы

Всем привет.

В статье Звуковые игры: невидимый рынок ждёт героев были рассмотрены звуковые игры с крутым объемным звуком, и библиотеки для его создания.

Ну а я решил начать с малого, и для начала организовать озвучивание синтезатором действий в пошаговых играх на pygame.

Конечно не для всех игр подходит такой прием, но в некоторых очень даже.



Создадим модуль speech.

В нем организуем два варианта работы:

  • подключение к экранному диктору NVDA через его Controller dll;
  • напрямую на синтезатор windows через SAPI5;



Сначала импортируем все необходимые модули.
Для подключения nvdaControllerClient32.dll нам нужен ctypes.

import ctypes

А при отсутствии NVDA на компьютере, работаем напрямую с синтезатором SAPI через win32api.

import win32com.client


Создаем класс для нашей говорилки.

class Speech:

    def __init__(self, config):
        """Initialize speech class."""
        self.config = config

Здесь наверно надо пояснить про config. В общем классе Game, который занимается инициализацией всех модулей игры и крутит основной цикл, идет загрузка настроек игры.

Настройки можно загружать откуда удобнее: ini файлы, json, sqlite, или любой другой удобный вариант.


Но продолжим инициализацию нашего Speech.

        # подключаем синтезатор как COM объект.
        self.speaker = win32com.client.Dispatch("Sapi.SpVoice")
        # Получаем все доступные синтезаторы в системе и сохраняем в списке
        self.voices = self.speaker.GetVoices()
        # Создаем список имен полученных голосов
        self.voices_names = [voice.GetDescription() for voice in self.voices]

Настроим подключенный синтезатор некоторыми параметрами из настроек.
В данном примере я беру просто индекс установленного голоса (установленный по умолчанию имеет индекс 0), но можно сделать настройки с выбором из выпадающего списка по имени, полученных как описывалось выше.

Скорость голоса устанавливается в диапозоне от -10 до +10. Но не думаю, что кто-то захочет слушать голос со скоростью ниже 5. Можете самостоятельно поэкспериментировать, меняя значение в настройках.

Ну и конечно громкость голоса. Тут стандартно от 0 до 100.

        self.set_voice(self.config.voice)
        self.speaker.Rate = self.config.rate
        self.speaker.Volume = self.config.volume

Ну и наконец инициализируем nvda.

        self.nvda = self.config.nvda
        self.nvda_error = False
        self.sLib = ctypes.windll.LoadLibrary('./nvdaControllerClient32.dll')

Сразу проверяем может ли наша программа подключиться к работающей программе NVDA.

        nvda_error = self.sLib.nvdaController_testIfRunning()
        errorMessage = str(ctypes.WinError(nvda_error))
        if 0 != nvda_error:
            print('NVDA error: ' + errorMessage)
            self.nvda_error = True

После того как проинициализировали и синтезатор SAPI, и nvda dll можно запустить функцию выбора аудио вывода речи.
        self.set_speak_out()
        


Добавим функцию установки голоса из списка доступных по индексу.

    def set_voice(self, index):
        """Set voice for speak."""
        try:
            self.speaker.Voice = self.voices[index]
            self.speak_sapi(self.voices_names[index])
        except:
            print('error: do not set voice')


А теперь функция по выбору аудио вывода речи. Тут мы собственно и выбираем, что будем использовать для работы: nvda или синтезатор напрямую.

Выбор заключается в двух параметрах:

  • Флаг в настройках, хочет ли пользователь вообще чтоб игра использовала NVDA;
  • Возможные ошибки при подключении к NVDA;

    def set_speak_out(self):
        """Set speak out: nvda or sapi."""
        if self.nvda and not self.nvda_error:
            self.speak = self.speak_nvda
        else:
            self.speak = self.speak_sapi


Ну и конечно пропишем функции произношения.

Для NVDA:

    def speak_nvda(self, phrase):
        self.sLib.nvdaController_speakText(phrase)

А это функция для произношения напрямую на синтезатор:
    def speak_sapi(self, phrase):
        self.speaker.Speak(phrase)


Вот и все. Теперь в любом месте игровой логики отправляем нужную информацию на speech.speak().

Надеюсь данная статья кому-то окажется полезной и будет появляться больше доступных игр.

Теги:
Хабы:
Всего голосов 10: ↑10 и ↓0 +10
Просмотры 3.8K
Комментарии Комментарии 13

Работа

Django разработчик
102 вакансии
Data Scientist
124 вакансии
Python разработчик
227 вакансий