- "да" - подтверждение действия
- "НОМЕР" - нажать на элемент #НОМЕР
- "НАЗВАНИЕ ТОВАРА" - поиск товара по названию и описанию
- "написать ФРАЗУ" - вводит ФРАЗУ в поле ввода
- "вниз | вверх | в начало | в конец" - прокрутка страницы
- "закрыть" - закрыть меню каталога
- "назад | вперед" - переход на предыдущую/следующую страницу
Приложение “Ассистент для игры в дартс”
Оглавление "Программирование для игр"
Игра в дартс неплохо развивает навыки устного счёта, но идея “подтянуть” смартфон для подсчёта остатка кажется неплохой идеей. Пусть, как пел Сыроежкин в фильме "Приключения Электроника" - вкалывают роботы. Смартфон - не робот, но тоже пусть отрабатывает вложения.
Задача. Создать приложение голосового помощника при игре в дартс, сообщающий остаток после голосовой команды.
На занятии Приложение ”Умный игральный кубик” мы создали приложение для 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" на что-то более подходящее, добавить вывод общего количества подходов и бросков. При желании можно ещё усложнить, добавив проект базу для сохранения данных, систему статистики с красивым выводом графиков и др.
