Майкл Моррисон - Создание игр для мобильных телефонов
В копилку Игрока
Поскольку мы имеем дело с мобильными телефонами – персональными устройствами, в списке рекордов в большинстве случаев будете присутствовать только вы. Поэтому ввод имени рекордсмена не столь необходим.
Поскольку нет необходимости сортировать имена, вам придется сортировать лишь счет игры. Если вы вспомните, то в игре Space Out счет– это четырехразрядное число (то есть меньше 10000), что означает, переменная типа int хорошо подходит для его хранения. Однако вы знаете, что данные в хранилище записей хранятся как массивы байтов. Следовательно, необходимо конвертировать данные в массив байтов и обратно.
Давайте рассмотрим конвертирование целых чисел в байтовый массив с точки зрения создания одной записи. Идея заключается в том, чтобы одно целое число преобразовать в массив типа byte. Ниже приведен код, выполняющий это:
byte[] recordData = Integer.toString(hiScore).getBytes();
В этом примере рекорд хранится в переменной hiScore, которая сначала преобразуется в строку, для чего вызывается метод Integer.toString(). Затем эта строка преобразуется в массив байтов методом getBytes(). Все, что необходимо, – это одна строка кода, и целое число преобразовано в массив байтов. На рис. 19.2 представлена графическая иллюстрация этого процесса.
Рис. 19.2. Чтобы преобразовать целое число в массив байтов, сначала необходимо конвертировать его в строкуПреобразование данных о рекордах в нужный формат – это важная задача, которая решается обратным конвертированием. Используя тип string как промежуточный тип, массив байтов преобразуется в целое число. Приведенный ниже код выполняет это:
hiScore = (Integer.parseInt(new String(recordData, 0, len)));
Конструктор String(), используемый в этом коде, принимает массив байтов, смещение и число конвертируемых байтов. Переменная len, которая хранит число конвертируемых данных, содержит число, возвращенное методом getRecord(), считывающим запись. Затем строка передается в статический метод Integer.parseInt(), преобразующий строку в целое число. Рисунок 19.3 иллюстрирует процесс обратного конвертирования (массива байтов в целое число).
Рис. 19.3. Чтение записи рекорда их хранилища записей требует обратного конвертированияКогда вы не работаете с хранилищем записей, рекорды – это обычные целые числа. Иначе говоря, все эти сложности необходимы лишь для преобразования данных при работе с хранилищем записей. Еще один случай, в котором необходимо конвертировать числа в строку, – вывод рекордов на экран, для чего необходимо использовать метод drawString().
Помните, что предыдущая строка кода считывает лишь одну запись из хранилища. В реальных мобильных играх список рекордов состоит из нескольких записей. Поэтому чтение и запись данных в хранилище должны выполняться в цикле. В этом случае вы сможете с легкостью выполнить все необходимые задачи, написав минимум кода.
Создание игры Space Out 2
Игра Space Out, созданная в предыдущей главе, идеально подходит для того, чтобы добавить в нее список рекордов. Оставшаяся часть главы будет посвящена добавлению списка рекордов в игру, и не только. Список рекордов будет выводиться на экран вместе с названием игры – растровым изображением.
Разработка игровых дополнений
Заставка видео появляется при запуске игры, а также между уровнями. Заставки могут быть очень занятными или простыми, они могут нести такую информацию, как название игры, иллюстрации, информация об авторских правах, инструкции по игре, и рекорды. В игре Space Out 2 вы создадите заставку, состоящую из названия игры и списка рекордов. На рис. 19.4 показано растровое изображение Space Out 2.
Рис. 19.4. Заставка игры Space Out 2 состоит из растрового изображения названия игры...Совет Разработчику
В играх на заставку целесообразно выносить информацию об авторских правах, чтобы четко установить свои права на игру.
Такая простая заставка игры объясняется тем, что игра работает в условиях ограниченных ресурсов мобильного устройства. Конечно, вы можете вынести больше информации на экран, однако иногда лучше меньше, чем больше. Кроме того, необходимо оставить место для вывода списка рекордов.
Написание игрового кода
Игра Space Out 2 содержит список из 5 рекордов, которые помещаются в хранилище записей. Хотя хранилище используется для постоянного хранения информации о рекордах, в игре они являются целыми числами. Ниже приведено объявление переменных игры Space Out 2, хранящих игровую заставку и массив рекордов:
private Image splash; private int[] hiScores = new int[5];
...Совет Разработчику
Вам ничего не мешает при желании расширить список рекордов. Просто помните, чтобы отобразить больший список рекордов, требуется больше места на экране.
Добавление списка рекордов в игру Space Out прежде всего ведет к изменениям метода start(), который, как вы знаете, отвечает за инициализацию игры и ее запуск. Этот метод как нельзя лучше подходит для чтения списка рекордов из хранилища записей. В методе start() чтение из хранилища записей выполняется одной строкой:
readHiScores();
Метод readHiScores() отвечает за открытие хранилища записей и последовательного чтения данных в целочисленный массив hiScores. В листинге 19.1 приведен код метода readHiScores(): Листинг 19.1. Метод readHiScores() считывает список рекордов из хранилища записей
private void readHiScores()
{
// открыть хранилище записей
RecordStore rs = null;
try {
rs = RecordStore.openRecordStore("HiScores", false); //Хранилище записей называется «HiScores»
}
catch (Exception e) {
}
if (rs != null) {
// считать список рекордов
try {
int len;
byte[] recordData = new byte[8];
for (int i = 1; i <= rs.getNumRecords(); i++) { //Пройти по всем записям хранилища
// при необходимости изменить размер выделенной памяти
if (rs.getRecordSize(i) > recordData.length)
recordData = new byte[rs.getRecordSize(i)];
// считать рекорд, преобразовать в число и записать в массив
len = rs.getRecord(i, recordData, 0);
hiScores[i – 1] = (Integer.parseInt(new String(recordData, 0, len))); //Преобразовать массив байтов в целое число и сохранить в массив рекордов
}
}
catch (Exception e) {
System.err.println("Failed reading hi scores!");
}
// закрыть хранилище данных
try {
rs.closeRecordStore();
}
catch (Exception e) {
System.err.println("Failed closing hi score record store!");
}
}
else {
// The record store doesn't exist, so initialize the scores to 0
for (int i = 0; i < 5; i++)
hiScores[i] = 0;
}
}Метод readHiScores() начинается попыткой открытия хранилища записей, которое называется «HiScores». Второй параметр метода (false) означает, что новое хранилище не нужно создавать, если хранилище с указанным именем не найдено. Если хранилище открыто успешно, то метод readHiScores() продолжает работу с хранилищем и считывает последовательно данные в массив целых чисел. После того как список рекордов считан, хранилище записей закрывается. Обратите внимание, что если хранилища с указанным именем не существует, то массив hiScores инициализируется 0. Этот вариант работает только при первом запуске игры.
Другое, но очень важное изменение метода start() игры Space Out 2 касается работы метода в случае ранее наступившего окончания игры. В исходной версии игры Space Out игра начинается сразу при запуске мидлета.
В игре Space Out 2 заставка и список рекордов отображаются при первом запуске игры. Иначе говоря, игра Space Out 2 начинается в режиме «окончания игры». Поэтому в методе start() больше не вызывается метод newGame(), а переменной gameOver присваивается значение true:gameOver = true;
Подобно тому, как список рекордов считывается в методе start(), он записывается в методе stop():
writeHiScores();
Метод writeHiScores() записывает целочисленный массив в хранилище записей. В листинге 19.2 приведен код этого метода: Листинг 19.2. Метод writeHiScores() записывает целочисленный массив HiScores в хранилище данных
private void writeHiScores()
{
// удалить предыдущее хранилище записей
try {
RecordStore.deleteRecordStore("HiScores"); //Сначала удаляется хранилище записей
}
catch (Exception e) {
}
// создать новое хранилище записей
RecordStore rs = null;
try {
rs = RecordStore.openRecordStore("HiScores", true); //Значение true говорит о том, что если хранилище записей с указанным именем не будет найдено, то будет создано новое хранилище
}
catch (Exception e) {
System.err.println("Failed creating hi score record store!");
}
// записать рекорды
for (int i = 0; i < 5; i++) {
// подготовить данные для записи
byte[] recordData = Integer.toString(hiScores[i]).getBytes(); //Преобразовать целое число в массив байтов, чтобы записать его в хранилище
try {
// записать данные в хранилище
rs.addRecord(recordData, 0, recordData.length);
}
catch (Exception e) {
System.err.println("Failed writing hi scores!");
}
}
// закрыть хранилище
try {
rs.closeRecordStore();
}
catch (Exception e) {
System.err.println("Failed closing hi score record store!");
}
}Метод writeHiScores() использует уникальную методику записи рекордов. Вместо того чтобы заменить отдельную запись в хранилище, заменяется все хранилище целиком. Хотя такой подход может показаться грубым, он значительно упрощает код игры. Это и объясняет, почему в начале метода writeHiScores() удаляется хранилище записей.
После того как хранилище записей удалено, метод writeHiScores() создает новое хранилище, для чего вторым параметром при вызове метода openRecordStore() передается true. Затем выполняется цикл по всем элементам массива hiScores, каждый из элементов записывается в хранилище. Когда все рекорды записаны, хранилище закрывается, для чего вызывается метод closeRecordStore().