Главная » Программирование игр под Android » Обработка событий клавиатуры – РАЗРАБОТКА ИГР ДЛЯ ОС ANDROID

0

После безумия прошлого пункта стоит сделать передышку и заняться чем-нибудь попроще. Добро пожаловать в мир обработки нажатий клавиш.

Для отслеживания событий клавиш мы реализуем другой интерфейс, названный OnKeyLi stener. У него есть лишь один метод опКеу  со следующей сигнатурой:

View определяет вид, получающий событие нажатия клавиши; аргумент keyCode – одна из констант, определенных в классе KeyEvent; последний аргумент – собственно код клавиши с дополнительной информацией.

Что такое код клавиши? Каждая клавиша экранной (или физической) клавиатуры и все системные кнопки имеют присвоенный им уникальный номер. Эти коды клавиш определены в классе KeyEvent как статические, открытые, финальные, целочисленные переменные. Например, код клавиши KeyEvent. KEYC0DE A назначен клавише А. Тут все ясно – при нажатии клавиши на клавиатуре в текстовом поле появляется символ, имеющий определенный код.

Класс KeyEvent похож на класс MotionEvent. У него есть два необходимых нам метода.

KeyEvent. getActi on  – возвращает значения KeyEvent. ACTI0N D0WN, KeyEvent. ACTI0N  UP и KeyEvent. ACTION MULTI PLE. Для наших целей мы можем игнорировать последнее из указанных типов событий. Другие два события генерируются, когда клавиша нажата и отпущена соответственно.

KeyEvent.getUnicodeCharО – возвращает символ в кодировке Юникод, который появляется в текстовом поле. Это может быть похоже на событие с кодом клавиши KeyEvent. KEYC0DEA, но в Юникод. Мы можем использовать данный метод, если хотим осуществлять текстовый ввод самостоятельно. Для получения событий от клавиатуры на View должен быть установлен фокус.

Это можно сделать принудительно, вызвав следующие методы:

Первый метод гарантирует, что на View может быть установлен фокус. Второй запрашивает получение фокуса определенным представлением.

Создадим небольшую тестовую активность, чтобы понаблюдать за комбинацией этих методов. Нам необходимо будет получать события от клавиш и показывать последнее полученное нами в TextVi ew. В качестве информации будет выводиться тип клавиатурного события, а также код клавиши и ее Юникод-символ (если он будет сгенерирован) Обратите внимание – некоторые клавиши не создают символы Юникод сами по себе, а только в комбинации с другими символами. Листинг 4.5 показывает способ достижения всех этих целей в нескольких строках кода.

Листинг 4.5. KeyTest.Java; тестирование API обработки клавиатурных событий package com.bad.ogi с.androi dgames;

Начинаем с декларации реализации нашей активностью интерфейса OnKeyLi stener. Далее определяем два члена, с которыми мы уже знакомы: Stri ngBuider для создания строки, выводимой в TextView, и самого TextVi ew для показа текста.

В методе onCreateO удостоверяемся в том, что фокус установлен в TextView (иначе он не сможет получать события клавиатуры). Кроме того, регистрируем активность в качестве OnKeyLi stener методом TextView.setOnKeyLi stener.

Метод опКеу довольно прямолинеен. Мы обрабатываем два типа событий в опесаторе swi ten, добавляя соответствующую строку в Stri ngBui  der. После этого мы добавляем код клавиши (а также Юникод-символ) из KeyEvent и выводим его в LogCat так же, как и в TextVi ew.

Последнее выражение if весьма интересно: если нажата клавиша back, мы возвращаем falsen3 метода опКеу,заставляя TextView обрабатывать событие. В другом случае мы возвращаем true. Для чего нужно это разделение?

Вернув true при нажатии клавиши back, мы слегка вмешаемся в жизненный цикл активности. Она не будет закрыта, поскольку мы взяли на себя обработку клавиши back. Конечно, существуют сценарии, в которых нам как раз необходимо перехватывать нажатие back, чтобы активность не закрывалась. Однако я настоятельно рекомендую не делать этого без необходимости.

Рисунок 4.8 иллюстрирует вывод активности при удерживании клавиш Shift+A на клавиатуре моего Droid.

Рис. 4.8. Одновременное нажатие Shift+A

Стоит отметить еще пару вещей.

Если вы посмотрите на вывод LogCat, то заметите, что обработка одновременного нажатия нескольких клавиш не составляет никаких проблем.

Нажатие джойстика и повороты трекбола воспринимаются как клавиатурные события.

Как и в случае с событиями касания, события обработки клавиатуры отъедают немалый процент мощностей процессора на старых версиях Android и устройствах первого поколения.

Это было довольно расслабляющее чтиво по сравнению с предыдущим пунктом, не так ли?

ПРИМЕЧАНИЕ

На самом деле API по обработке клавиатуры немного сложнее, чем я вам рассказал. Но для наших игровых объектов полученной в этом разделе информации более чем достаточно. Если вам хочется чего-нибудь посложнее, обратитесь к официальной документации на сайте Android Developers.

Чтение состояния акселерометра. Акселерометр – очень интересный способ ввода для игр. Все устройства Android должны оснащаться трехосевым акселерометром.

Все, что нам будет нужно для ее реализации, – получить текущее состояние акселерометра.

Как же получить эту информацию? Вы угадали – регистрируя слушателя. Интерфейс, который нам необходимо реализовать, называется SensorEventLi stener. Он заключает в себе два метода:

Первый метод вызывается при возникновении события акселерометра. Второй срабатывает при изменении точности акселерометра (для наших целей мы спокойно можем его игнорировать).

Как же мы зарегистрируем SensorEventLi stener? Для этого сначала необходимо проделать некоторую предварительную работу. Нужно проверить, имеется ли вообще в аппарате акселерометр. Только что я говорил вам, что все устройства на Android должны им оснащаться. Это все еще соответствует истине, но вдруг в будущем что-то изменится? Нам необходимо быть на 100 % уверенными, что этот метод ввода нам доступен.

Первое, что нам необходимо сделать, – получить экземпляр так называемого SensorManager. Эта штука расскажет нам, установлен ли акселерометр, а еще именно в нем мы зарегистрируем наш слушатель. Для получения SensorManager мы используем метод интерфейса Context:

SensorManager – это так называемый системный сервис, предоставляемый системой. Android состоит из множества системных сервисов, каждый из которых предлагает различные сегменты информации каждому, кто об этом вежливо попросит.

Теперь, когда у нас есть сервис, мы можем проверить доступность акселерометра:

Этот кусочек кода запрашивает у менеджера все установленные датчики типа акселерометр. Предполагается, что в устройстве может быть несколько акселерометров, хотя в реальности метод всегда возвращает одну запись.

Если акселерометр установлен, мы можем получить его данные от SensorManager и зарегистрировать наш SensorEventLi stener:

Аргумент SensorManager. SENSOR DELAY GAME определяет частоту получения состояния акселерометра. Это специальная константа, разработанная для игр, поэтому было бы глупо ее не использовать. Обратите внимание – метод SensorManager. regi sterLi stener  возвращает значение boolean, по которому можно судить, успешно ли завершился процесс регистрации. Это значит, что нам необходимо проверять это значение для уверенности в том, что мы получаем события от акселерометра.

После регистрации слушателя мы можем получать события SensorEvents в методе SensorEventListener.onSensorChangecK. Имя этого метода намекает, что он вызывается только при изменении состояния датчика. Это может смутить – ведь состояние акселерометра изменяется постоянно. При регистрации слушателя мы определяем частоту, с которой хотим получать обновления состояния датчика.

Как же мы обрабатываем SensorEvent? Довольно просто. SensorEvent включает в себя открытый массив значений типа float, названный SensorEvent. values. В нем хранятся текущие значения для каждой из трех осей акселерометра. SensorEvent. values[0] содержит значение по осих, SensorEvent. values[l] – по оси у и, наконец, SensorEvent. va 1 ues [2] – по оси г.

Вооружившись всей этой информацией, мы можем приступить к созданию простой тестовой активности. Все, что нам нужно, – выводить значения акселерометра по каждой оси в элементе TextVi ew. В листинге 4.6 написано, как это делается.

Листинг 4.6. AccelerometerTest.Java: тестирование API акселерометра package com.bad. ogiс.androidgames;

Мы начали с проверки доступности датчика акселерометра. После успешного тестирования получаем датчик от SensorManager и пытаемся зарегистрировать нашу активность, реализующую интерфейс SensorEventListener. Если какая-то из этих операций заканчивается неудачей, в TextVi ew отображается соответствующее сообщение.

Метод onSensorChanged просто считывает значения координат по разным осям от SensorEvent и обновляет соответствующим образом содержимое TextVi ew.

Метод onAccuracyChanged присутствует здесь только потому, что входит в реализуемый нами интерфейс SensorEventLi stener. Других реальных целей у него здесь нет.

На рис. 4.9 показано, какие значения осей принимает акселерометр в портретном и ландшафтном режимах (телефон находится перпендикулярно земле). Два финальных замечания по акселерометру.

Как вы видите в правой части рис. 4.9, значения акселерометра иногда могут выходить за рамки определенного для них диапазона. Это происходит из-за небольших неточностей в работе сенсора; вам необходимо будет учитывать это, чтобы полученные вами значения были как можно более точными.

Значения координат осей акселерометра всегда выводятся в одном и том же порядке вне зависимости от текущей ориентации устройства.

Вот теперь мы обсудили все необходимые для разработки игр классы Android API, связанные с обработкой ввода.

Рис. 4.9. Значения осей акселерометра в портретном (слева) и ландшафтном (справа) состоянии

ПРИМЕЧАНИЕ

Как понятно из названия, класс SensorManager1 может предоставить доступ и к другим датчикам (например, компасу и сенсору освещенности). Если вы хотите придумать что-то новое, то можете попробовать написать игру, использующую их, – обработка таких событий весьма похожа на работу с акселерометром. Документация на сайте Android Developers даст вам больше информации.

Источник: Mario Zechner / Марио Цехнер, «Программирование игр под Android», пер. Егор Сидорович, Евгений Зазноба, Издательство «Питер»

По теме:

  • Комментарии