- "да" - подтверждение действия
- "НОМЕР" - нажать на элемент #НОМЕР
- "НАЗВАНИЕ ТОВАРА" - поиск товара по названию и описанию
- "написать ФРАЗУ" - вводит ФРАЗУ в поле ввода
- "вниз | вверх | в начало | в конец" - прокрутка страницы
- "закрыть" - закрыть меню каталога
- "назад | вперед" - переход на предыдущую/следующую страницу
Приложение “Ассистент для игры в дартс”
Оглавление "Программирование для игр"
Игра в дартс неплохо развивает навыки устного счёта, но идея “подтянуть” смартфон для подсчёта остатка кажется неплохой идеей. Пусть, как пел Сыроежкин в фильме "Приключения Электроника" - вкалывают роботы. Смартфон - не робот, но тоже пусть отрабатывает вложения.
Задача. Создать приложение голосового помощника при игре в дартс, сообщающий остаток после голосовой команды.
На занятии Приложение ”Умный игральный кубик” мы создали приложение для Android с голосовым управлением для имитации игрального кубика. Используем его в качестве основы.
Распишем задачу по шагам.
В начале игры у нас есть 501 очко. Для простоты можно называть это начальный остаток. Голосовая команда будет состоять из префикса в биде буквы "o" и числа очков в текущем подходе: "o180", "о57" и т.п. После получения голосовой команды нужно выделить из данных команды число, вычесть его из остатка и сообщить новый остаток. Если остаток меньше нуля, то попытка не засчитывается из-за перебора. После окончания игры звучит фраза ”конец игры”.
Распишем алгоритм:
ВсегоОчков = 501 Функция ПриПолучениииКоманды Временный результат = Вызвать ПолучитьОстаток (Очки) Если ВременныйРезультат = 0 Тогда Сказать “конец игры” Если ВременныйРезультат > 0 Тогда ВсегоОчков = ВременныйРезультат и Сказать ВсегоОчков Если ВременныйРезультат < 0 Тогда Сказать “перебор” КонецФункции Функция ПолучитьОстаток (Очки) Вернуть Результат = ВсегоОчков – Очки КонецФункции
Все написанное выше можно просчитать в голове, но, когда алгоритм находится перед глазами, то наглядно видна последовательность действий и то, что нужно делать.
Многие разработчики создают алгоритмы из головы и не любят “лишнюю писанину”. В случае простого приложения такой подход похож на поход в продуктовый магазин без списка того, что нужно купить. Купил лишнее, не то или что-то забыл купить – ничего страшного. Но в при разработке сложного приложения ситуация станет похожа на попытку построить дом без плана. Что настроит прораб в этом случае многим известно.
Существует несколько рекомендаций при написании кода, одна из которых звучит так:
старайтесь делать самодокументирующийся код и писать функции для выполнения только одного действия.
В этом случае при необходимости можно будет легко отредактировать код в ней и не вспоминать через месяц, а что это я наворотил в этой паре десятков непонятных строк кода.
Ещё один момент - защита от некорректных данных. В образовательных целях для простоты данный момент исключают из рассмотрения, но это один из важнейших аспектов. Главной ошибкой начинающих разработчиков являются предположения о том, что компьютеры надёжны, в программном обеспечении нет ошибок, а пользователи всегда вводят корректные данные и если написано, введите свое имя и загрузите свою фотографию, то все и всегда вводят своё настоящее имя и загружают свою фотографию.
Полный код проекта для DroidScript показан ниже.
// значение громкости звонка и музыки var oldRingVolume = null; var oldMusicVolume = null; // остаток var totalPoints = 501; // при старте приложения function OnStart() { // выключаем вывод отладочной информации app.SetDebugEnabled( false ); // выключаем действие по умолчанию для системной кнопки Back app.EnableBackKey( false ); lay = app.CreateLayout( "linear", "VCenter,FillXY" ); btn = app.AddButton( lay, "Старт", 0.3 ); btn.SetOnTouch( initGame ); app.AddLayout( lay ); // создаём объект синтезатора речи speech = app.CreateSpeechRec( "NoBeep,Parxtial" ); // обработчик распознавания голосовой команды speech.SetOnResult( speech_OnResult ) // обработчик ошибок speech.SetOnError( speech_OnError ) // запоминаем значение громкости звонка и музыки oldRingVolume = app.GetVolume( 'ring' ); oldMusicVolume = app.GetVolume( 'music' ); // установка громкости app.SetVolume( 'ring', 0) ; app.SetVolume( 'music', 0.5); // выводим речь в поток для музыки app.TextToSpeech( "Для начала игры скажите старт", 1, 1.2, Listen, 'music' ) } // инициализация игры function initGame() { app.SetVolume( 'music', 0.5); app.TextToSpeech( "Игра началать", 1, 1.2, Listen, 'music' ); totalPoints = 501; btn.SetEnabled = false; } // включаем прослушивание эфира function Listen() { speech.Recognize(); } function say( text ){ app.SetVolume( 'music', 0.5 ); app.TextToSpeech( text, 1,1.3, Listen, 'music' ); } function checkPoints( points ) { if( points == 0 ){ say( "конец игры" ); btn.SetEnabled = true; } else if ( points < 0 ){ say( "перебор" ); } else { totalPoints = points; say( totalPoints ); } } function speech_OnResult( results, partial ) { var cmd = results[0].toLowerCase() app.ShowPopup( cmd ); if( cmd == "старт" ){ initGame(); } else if( cmd[0] == "о" || cmd[0] == "o" ){ // получение числа из строки var value = parseInt( cmd.match( /\d+/ ) ); if( isNaN(value) ) { say( "Повторите команду" ); } else { var tmpPoints = Number.parseInt( totalPoints - value ); checkPoints( tmpPoints ); } } else { speech.Recognize() } } // обработка ошибок голосового ввода function speech_OnError( error ) { if( !speech.IsListening() ){ speech.Recognize() } } // деактивация приложения function OnPause() { app.SetVolume( 'ring', oldRingVolume ) ; app.SetVolume( 'music', oldMusicVolume ); } // активация приложения function OnResume() { app.SetVolume( 'ring', 0) ; app.SetVolume( 'music', 0.5); } // выход из приложения по системной кнопке Back function OnBack() { app.SetVolume( 'ring', oldRingVolume ) ; app.SetVolume( 'music', oldMusicVolume ); app.Exit(); }
Для вывода речи используется поток "music" для воспроизведения мультимедиа, что позволило исключить из проекта таймер. Звуковые сигналы перед и после распознавания голоса выводятся через поток сингнала звонка, громкосчть которого убирается в 0. В базовой функциональности DroidScript отстствует обработчик события завершения работы приложения. Это не даёт возможность восстановить громкость звонка и мультимедиа на телефоне после закрытия приложения слайдом.
После проверки работоспособности основы можно подумать над расширением функциональности - добавить голосовые команды для расчёта удвоений и утроений, заменить команду "o" на что-то более подходящее, добавить вывод общего количества подходов и бросков. При желании можно ещё усложнить, добавив проект базу для сохранения данных, систему статистики с красивым выводом графиков и др.