Майкл Моррисон - Создание игр для мобильных телефонов
В копилку Игрока
То, как телефон хранит данные, зависит от конкретной модели. В современных мобильных телефонах обычно используется память устройства, но в будущем телефоны могут иметь и микро жесткие диски или какие-либо другие средства хранения информации. Хорошо, что, с точки зрения программирования, способ хранения данных не важен.
Понятие о записях и хранилищах записей
Хранилище записей – это упрощенная база данных. Запись – это единица информации, имеющая уникальный числовой идентификатор (ID). Хранилище записей можно представить как таблицу, состоящую из двух колонок (рис. 19.1).
Рис. 19.1. Хранилище записей состоит из отдельных записей, имеющих уникальный ID
Каждое хранилище записей в RMS ассоциировано с пакетом мидлета и имеет текстовое имя, идентифицирующее ее. Так, например, хранилище списка рекордов для игры Space Out может называться HiScores, доступ к нему может быть получен только через приложение Space Out. Если вы распространяете другие игры вместе со Space Out в одном пакете, то остальные игры также будут иметь доступ к этому хранилищу.
...В копилку Игрока
Пакет мидлетов определяется JAR-файлом. Чтобы создать пакет мидлетов, просто упакуйте несколько мидлетов в один JAR-файл и создайте необходимый дескриптор (JAD) для каждого из них. Все примеры игр и программы, приведенные в книге, упакованы в отдельные JAR-файлы.
Данные, находящиеся в хранилище, – это массив байтов. Независимо от того, сохраняете ли вы строку текста или целые числа, они сохраняются в виде последовательности байтов.
Позже в этой главе вы узнаете, что любые стандартные данные Java очень легко конвертировать в массив байтов и обратно, и научитесь делать это.
Изучаем класс RecordStore
MIDP API поддерживает RMS через пакет javax.microedition.rms. В этом пакете находятся класс и несколько интерфейсов, поддерживающих создание и работу с хранилищами данных. Эти функции выполняет класс RecordStore, он предоставляет программируемый интерфейс для одного хранилища данных. Этот класс выполняет чтение и запись хранилищ записей.
Использование класса RecordStore обычно подразумевает выполнение следующих шагов:
1. открытие/создание хранилища записей;
2. запись/чтение данных в/из хранилища записей;
3. закрытие хранилища записей.
Вам также может потребоваться выполнить особые задачи, например, удалить определенную запись или целое хранилище, эти действия также можно выполнить, используя класс RecordState.
Ниже перечислены некоторые методы класса RecordState, используемые для работы с записями:
► openRecordStore() – открывает хранилище данных для чтения/записи;
► getNumRecords() – возвращает число записей в хранилище;
► getRecordSize() – возвращает размер определенной записи;
► getRecord() – возвращает данные определенной записи;
► addRecord() – добавляет данные в хранилище;
► deleteRecord() – удаляет определенную запись;
► deleteRecordStore() – удаляет хранилище данных;
► closeRecordStore() – закрывает хранилище данных.
Как вы видите, эти методы выполняют основные задачи по управлению записями в хранилище. Конечно, в классе RecordStore есть и другие методы, но перечисленных методов вполне достаточно для хранения и управления списком рекордов.
Чтобы начать работу с хранилищем записей, необходимо создать экземпляр класса RecordStore:
RecordStore rs = null;
Чтобы создать сам объект REcordStore, необходимо вызывать статический метод openRecordStore():
try {
rs = RecordStore.openRecordStore("HiScores", true);
}
catch (Exception e) {
System.err.println("Failed creating hi score record store!");
}Первый параметр, передаваемый в метод, – это название хранилища записей, в данном случае – хранилища списка рекордов. Второй параметр определяет, нужно ли создать новое хранилище записей, если указанного хранилища не существует. Значение true говорит о том, что хранилище записей будет открыто или создано, если значение параметра равно false, то хранилище будет открыто, только если оно существует. Вот почему переменная rs инициализируется значением null – вы сможете проверить, было ли открыто хранилище. Когда хранилище открыто, вы готовы начать чтение и/или запись данных. Если вы вспомните, о чем шла речь ранее, то запись состоит из уникального числового ID и массива байтов. Давайте рассмотрим, как можно добавить данные в хранилище, используя метод addRecord() класса RecordStore:
try {
rs.addRecord(recordData, 0, recordData.length);
}
catch (Exception e) {
System.err.println("Failed writing hi scores!");
}В приведенном коде переменная recordData – это массив байтов, содержащий помещаемые в хранилище данные. Метод recordData() принимает три параметра: байтовый массив данных, смещение, с которого начинаются данные в массиве, а также число байт записываемых данных. Если вы хотите записать весь массив данных, то вторым параметром передайте 0, а третьим – длину массива байтов, как показано в примере.
Чтение данных из хранилища несколько сложнее, чем запись, потому что вы не знаете, сколько данных находится в хранилище. Чтобы прочитать данные из хранилища, необходимо выполнить следующие ходы:
1. пройти по всем записям хранилища;
2. получить размер текущей записи;
3. при необходимости изменить указатель записи, чтобы вместить всю запись;
4. прочитать запись.
Я мог бы вам показать, как прочитать одну запись, однако в большинстве случаев необходимо считать все содержимое хранилища. Описанные выше шаги уже дают представление о том, как это реализовать, – пройти по всем записям хранилища. Ниже приведен код, выполняющий это:try {
int len;
byte[] recordData = new byte[8]; //В размере записи (8 байт) нет ничего магического – это просто предположение о среднем размере записи
for (int i = 1; i <= rs.getNumRecords(); i++) {
// выделить память при необходимости
if (rs.getRecordSize(i) > recordData.length) //Если размер записи больше 8 байт, этот код выделяет необходимый объем памяти
recordData = new byte[rs.getRecordSize(i)];
// считать данные в массив
len = rs.getRecord(i, recordData, 0);
// Do something with the record data
... //Здесь вы напишете игровой код, конвертирующий и сохраняющий данные в обычный формат, например, int
}
}
catch (Exception e) {
System.err.println("Failed reading hi scores!");
}Этот код показывает, как пройти по всем записям хранилища, считывая по одной записи. Важно отметить, что при необходимости выделяется память для записи. Обычно этого не требуется при работе со списком рекордов, поскольку все записи в данном случае имеют приблизительно одинаковый размер, но осторожность не повредит. Есть ряд ситуаций, когда может потребоваться удалить все хранилище записей. К счастью, в классе RecordStore для этого есть статический метод deleteRecordStore(). Все, что необходимо сделать, – это передать ему название хранилища записей, например, так:
try {
Rs.deleteRecordStore("HiScores");
}
catch (Exception e) {
System.err.println("Failed deleting record store!");
}Метод deleteRecordStore() полезен в тех случаях, когда вам не нужны данные старого хранилища, а вы хотите записать новое. Этот прием будет использован дальше в этой главе, когда вы будете обновлять содержимое списка рекордов игры Space Out. Вместо того чтобы искать и изменять конкретную запись в хранилище, игра Space Out 2 удаляет старое хранилище и записывает новое. Об этом вы узнаете чуть позже в этой главе. Тем временем метод closeRecord() – последний метод класса RecordStore, который интересен с точки зрения программирования мобильных игр. Этот метод необходим для закрытия хранилища записей по окончании работы с ним:
try {
rs.closeRecordStore();
}
catch (Exception e) {
System.err.println("Failed closing hi score record store!");
}Хотя про хранилища записей и поддержку MIDP API Системы управления записями можно сказать намного больше, вам необходимо знать лишь то, что поможет добавить интересные штрихи в создаваемые вами мобильные игры. Поэтому оставшаяся часть главы посвящена добавлению списка рекордов в игру Space Out, разработанную в предыдущей главе.
Подготовка списка рекордов к хранению
Я бы хотел научить вас создавать список рекордов (одну из особенностей классических аркад), в который можно вводить ваше имя или инициалы. К сожалению, эта задача достаточно сложна с точки зрения программирования. Если быть более точным, то необходимо отступить от темы повествования, не углубляясь в детали. Поэтому вместо списка рекордов, хранящего имена и счет лучших пяти игроков, вы создадите список рекордов, содержащий лишь лучшие 5 результатов. Хотя при этом имена рекордсменов будут неизвестны, тем не менее такой способ хорош для отражения лучших достижений.
...В копилку Игрока
Поскольку мы имеем дело с мобильными телефонами – персональными устройствами, в списке рекордов в большинстве случаев будете присутствовать только вы. Поэтому ввод имени рекордсмена не столь необходим.
Поскольку нет необходимости сортировать имена, вам придется сортировать лишь счет игры. Если вы вспомните, то в игре Space Out счет– это четырехразрядное число (то есть меньше 10000), что означает, переменная типа int хорошо подходит для его хранения. Однако вы знаете, что данные в хранилище записей хранятся как массивы байтов. Следовательно, необходимо конвертировать данные в массив байтов и обратно.