Рис. 2.8. Игра Worm – хороший пример простого игрового мидлета
 
   Пример игры Worm – это вариация известной игры Snake, о которой вы узнали в предыдущей главе. Поиграйте немного в игру и поэкспериментируйте с эмулятором. Когда закончите и закроете окно эмулятора, попробуйте другую конфигурацию устройства, которую можно выбрать из выпадающего меню инструмента KToolbar. На рис. 2.9 показана игра PushPuzzle, эмулированная на устройстве с конфигурацией Qwerty.
   Рис. 2.9. Конфигурация устройства Qwerty позволяет эмулировать выполнение игр на устройстве, похожем на мобильный телефон с полной клавиатурой
 
   Как видно, эмулятор весьма гибок при имитации мобильных устройств, его можно эффективно использовать как базис для разработки мидлетов игр.
   В копилку Игрока
   Как и в случае любых инструментов из пакета J2ME, эмулятор можно запустить непосредственно из командной строки. Однако KToolbar делает использование эмулятора много проще и избавляет вас от необходимости использования командной строки.
   Хотя при выборе приложения вы можете попытаться щелкать мышью непосредственно по экрану эмулируемого телефона, помните, что вы должны управлять телефоном, используя только щелчки мыши по кнопкам на корпусе телефона и клавиши клавиатуры.
   В копилку Игрока
   Если вы хотите протестировать примеры игр на реальном мобильном телефоне, вам необходимо прочитать документацию к своему телефону. Не загружая игры через сеть (речь об этом пойдет чуть позже), для загрузки вы, вероятно, можете использовать USB-кабель или беспроводное Bluetooth-соединение. Но это зависит от вашей модели телефона.

Эмулятор J2ME и реальные устройства

   J2ME Wireless Toolkit создан как многоцелевой пакет инструментов разработки J2ME, предназначенный для программирования приложений для большого числа различных моделей телефонов. По этой причине вы не найдете ни одного названия компании производителя и ни одной модели телефона в J2ME Wireless Toolkit. Если говорить подробнее, то J2ME Wireless Toolkit поддерживает эмуляцию следующих типов устройств:
   ► телефон с черно-белым дисплеем;
   ► устройство Qwerty;
   ► телефон с цветным дисплеем;
   ► Media-обложка.
   Первые два типа устройств наиболее важны для эмуляции игр на мобильных телефонах, хотя, вероятно, вам понадобится протестировать игры на других типах устройств. В таблице 2.1 приведены характеристики каждого из типов устройств.
Таблица 2.1. Мобильные устройства, поддерживаемые J2ME Wireless Kit
   Таблица отражает возможности J2ME по эмуляции различных устройств. Обратите внимание, что все устройства, кроме поддерживающих Qwerty, имеют вертикально-ориентированный экран. Телефоны с черно-белыми экранами поддерживают отображение 256 оттенков серого цвета, а остальные устройства поддерживают 256 цветов. Также устройства отличаются и клавиатурами. Устройства типа Qwerty имеют полную клавиатуру Qwerty, похожую на клавиатуру обычного компьютера. Такие устройства имеют больший размер, по сравнению с обычным мобильным телефоном, подобные модели выпускаются фирмой Research In Motion (RIM). Клавиатура типа ITU-T – это типичная клавиатура мобильных телефонов.
   Хотя основные типы устройств, представленные в J2ME Wireless Toolkit, полезны для тестирования мидлетов игр, при этом не указываются конкретные модели и изготовители, но, вероятно, вам потребуется использовать телефон с более конкретными параметрами. Самый простой способ сделать это – запустить J2ME Wireless Toolkit, поставляемый конкретным производителем. Например, инструменты J2ME, предлагаемые Motorola или Nokia, содержат эмуляторы всех основных производимых устройств с поддержкой Java. Тестируя мидлеты игр в эмуляторах этих устройств, вы можете с большой степенью точности увидеть, как работает мидлет на реальном устройстве, как он смотрится на экране.

Резюме

   Перед тем как более детально погрузиться в J2ME Wireless Toolkit, вы познакомились с основами разработки компьютерных игр. Хотя они и не высечены на камне, ими полезно руководствоваться при начале работы над своим шедевром. В этой главе было уделено внимание пакету J2ME Wireless Toolkit, а также его специальным инструментам, дающим возможность собирать мобильные Java-игры.
   Вы узнали, что эмулятор J2ME – это особая часть пакета разработки J2ME, он позволяет тестировать мидлеты на настольном компьютере без необходимости загрузки в реальное устройство. Вам, конечно, придется проверять разработанное приложение и на настоящем устройстве, однако эмулятор позволяет ускорить процесс разработки и тестировать приложения на реальных устройствах в случаях крайней необходимости. Вы узнали о стандартном эмуляторе J2ME, который входит в состав пакета J2ME Wireless Toolkit, а также – как его можно усовершенствовать для эмуляции особых моделей мобильных телефонов.

Экскурсия

   Уделите немного времени и поиграйте с эмулятором J2ME и тремя играми, которые были включены в состав J2ME Wireless Toolkit. Если вы хотите чего-то большего, посетите сайт одного из производителей мобильных телефонов, например, Motorola или Nokia, и загрузите пакет J2ME SDK, разработанный для конкретных моделей производимых ими телефонов. Вы сможете эмулировать продаваемый телефон, что много интереснее, нежели эмулятор стандартных телефонов, входящий в состав J2ME Wireless Toolkit.

Глава 3
Создание мобильной игры Skeleton

   Архив Аркад
   Игра Galaxian, выпущенная компанией Namco в 1979 году, была первой игрой жанра «космический шутер», наследницей Space Invaders. Galaxian – предшественница игры Galaga, которая, вероятно, является самой успешной игрой всех времен в своем жанре. В Galaxian, как и в любой другой игре жанра «космического шутера», вы управляете космическим кораблем, перемещающимся вдоль нижнего края экрана и вверх при атаке кораблей противника. Galaxian занимает особое место в истории видеоигр, потому что это первая аркада с RGB-графикой.
   Разработка на языке Java связана со знанием Java и набора API, которые обеспечивают поддержку сервисов приложений (например, GUI-компоненты, работу в сетях, и ввод/вывод). В этом смысле разработка мобильных приложений на Java ничем не отличается, здесь также есть набор API для поддержки различных процессов, необходимых мидлетам игр для нормальной работы в беспроводной мобильной среде. Чтобы стать разработчиком мобильных игр, необходимо понять эти API и их назначение. В данной главе вы познакомитесь с API мобильного Java и пройдете стадию разработки «скелета» игры. Такой «скелет» мидлета послужит как шаблон для разработки игр во всей книге.
   Прочитав эту главу, вы узнаете:
   ► как программирование на J2ME разбивается на несколько различных API;
   ► о внутренней структуре мидлетов;
   ► как построить мидлет на основе шаблона, который отражает основную игровую информацию о мобильном телефоне;
   ► как подготовить мидлеты для распространения.

Знакомство с J2ME API

   Перед тем, как погрузиться в программирование вашего первого мобильного приложения, необходимо познакомится с API, которые будут использованы при сборке мидлетов. Спецификация MIDP (Mobile Information Device Profile) – это набор правил, описывающий возможности и ограничения Java в отношении мобильных телефонов. Важной особенностью этих возможностей и ограничений является то, что они представляют собой набор классов и API, доступных для программирования мидлетов. Хотя спецификация MIDP дает подробное описание пакета API, который можно использовать для программирования мидлетов, дополнительные API предоставляет CLDC (Connected Limited Device Configuration). MIDP API построен на основе CLDC API и предоставляет классы и интерфейсы, ориентированные на программирование для мобильных телефонов. О CLDC можно думать как о средстве, предоставляющем основные Java API для сетевых устройств, в то время как MIDP предлагает более специфичные API, дополняющие CLDC API для компактных беспроводных устройств как мобильные телефоны и пейджеры.
   Почему вы должны думать об этих спецификациях и API? Спецификации CLDC и MIDP очень важны, поскольку они явно определяют, какие классы и API можно использовать для создания мидлет. Мобильные устройства – это гибкие машины, не имеющие такой роскоши, как мегабайты памяти. По этой причине Sun пришлось найти способ создать базовый набор функций, выполняемых без потери производительности устройства. Решением стала разбивка конфигурации на более детализированные профили. CLDC API описывает базовые классы и интерфейсы, необходимые сетевым устройствам, в то время как MIDP API описывают интерфейсы и классы, необходимые мобильным информационным устройствам, например, сотовым телефонам. На рис. 3.1 показаны взаимосвязи между мидлетом, CLDC API и MIDP API.
   Рис. 3.1. Чтобы выполнять большинство функций, мидлет должен делать вызовы CLDC API и MIDP API
 
   Помните, что хотя CLDC API и MIDP API были тщательно подобраны с учетом необходимости компромисса между производительностью и необходимым размером памяти и ограничениями мобильных устройств, их в определенных случаях недостаточно.
   Это означает, что в ряде случаев вам придется более тщательно прорабатывать мидлет игры, поскольку в вашем распоряжении нет широкого набора API, такого как в случае обычного программирования.

CDLC API

   Большинство классов, включенных в CDLC API, происходят непосредственно из стандартного J2SE API. Эти классы и интерфейсы практически идентичны тем, которые вы, вероятно, использовали при обычном программировании на Java. Эта часть CLDC API находится в пакете со знакомыми из J2SE именами java.lang и java.util. Кроме классов и интерфейсов, заимствованных у J2SE, есть ряд особых классов CLDC API. Эти интерфейсы, главным образом, предназначены для работы с сетями, это касается той части J2SE API, которую практически очень сложно изменить в соответствии с потребностями сетевых устройств.
   CLDC определяет ряд интерфейсов, способствующих функционированию устройства в сети, а решение специальных задач возлагается на MIDP API. В связи с этим CLDC API логически делится на две составляющие:
   ► набор пакетов, которые служат как подмножество J2SE API;
   ► набор основных сетевых интерфейсов.
   Большая часть классов и интерфейсов, входящих в состав CLDC API, напрямую наследованы от J2SE API. J2ME требует, чтобы классы и интерфейсы, наследованные от J2SE, были неизменными. Это означает, что все методы и поля этих классов совпадают с методами и полями таких классов J2SE, что заметно облегчает обучение программированию в J2ME, а также делает код переносимым между J2SE и J2ME.
   Но CLDC уходит в сторону от J2SE API в вопросах, касающихся работы в сети, и формирует сетевую оболочку, известную как Generic Connection Framework (GCF, Настраиваемая сетевая оболочка). GСF предназначен для определения общей архитектуры сети, поддерживающей сетевой ввод/вывод. Это весьма гибкая, а следовательно, расширяемая архитектура. Оболочка GCF разрабатывалась как функциональное подмножество сетевых классов J2SE, поэтому возможности GCF доступны в J2SE. GCF состоит из набора интерфейсов соединений, а также класса Connector, используемого для установления различных соединений. Класс Connector и интерфейсы соединений находятся в пакете javax.microedition.io. В главе 14 вы подробнее познакомитесь с программированием сетевых мобильных игр.

MIDP API

   Профиль устройства выходит на первый план, когда отступает конфигурация и наступает черед более детального описания функций конкретного типа устройства. В случае Mobile Information Device Profile (MIDP) тип устройства – это беспроводное мобильное устройство, например, мобильный телефон или пейджер. Следовательно, MIDP должен взять CLDC API и надстроить необходимые классы и интерфейсы, позволяющие написание собираемых мидлетов, например, игровых.
   MIDP API можно разделить на две части, подобно CLDC API:
   ► два класса, непосредственно наследованных от J2SE API;
   ► ряд пакетов, которые включают классы и интерфейсы, уникальные для разработки MIDP.
   Подобно CLDC API, MIDP API также наследует от J2SE API. Неудивительно, что большая часть MIDP API – это новые классы и интерфейсы, специально разработанные для программирования мидлетов. Хотя эти классы и интерфейсы могут выполнять те же функции, что и некоторые классы и интерфейсы J2SE API, в целом они уникальны для MIDP API, а следовательно, тщательно проработаны для решения специфичных для мидлетов задач. Эта часть MIDP API разделена на несколько пакетов, каждый из которых следует за именем javax.microedition:
   ► javax.microedition.midlet;
   ► javax.microedition.lcdui;
   ► javax.microedition.lcdui.game;
   ► javax.microedition.media;
   ► javax.microedition.media.control;
   ► javax.microedition.io;
   ► javax.microedition.pki;
   ► javax.microedition.rms.
   Пакет javax.microedition.midlet – это центральный пакет в MIDP API, он включает в себя единственный класс MIDlet. Класс MIDlet содержит основные функции, необходимые для MIDP-приложения (мидлета), которые могут выполняться на мобильном устройстве. По мере прочтения книги и построения более сложных мидлетов вы более подробно познакомитесь с этим классом.
   Пакеты javax.microedition.lcdui и javax.microedition.lcdui.game включают классы и интерфейсы, которые поддерживают GUI-компоненты, специально предназначенные для маленьких экранов мобильных устройств. Кроме того, в этих пакетах содержатся классы и интерфейсы, специально разработанные для создания мобильных игр. Уникальные возможности, такие как, например, анимация спрайтов и управление слоями, делают эти пакеты чрезвычайно ценными для программирования мобильных игр. Чуть позже в этой главе вы начнете свое знакомство с некоторыми из этих классов и пакетов, а при дальнейшем прочтении книги будете углублять свои знания.
   В копилку Игрока
   Если вам доводилось работать с J2ME ранее, то вам, вероятно, будет интересно узнать, что пакет javax.microedition.ldui.game появился только в MIDP 2.0. Вот почему MIDP 2.0 представляет собой значительное продвижение вперед и укрепление позиций J2ME как технологии мобильных игр.
   Пакеты javax.microedition.media и javax.microedition.media.control содержат классы и интерфейсы для управления звуком в мидлете. Эти пакеты представляют MIDP 2.0 Media API, который является подмножеством более обширного Mobile Media API. Полный Mobile Media API поддерживает большое число медиа-объектов, например, изображения, звуки, музыку и видео. Возможности по работе с медиа-данными в MIDP 2.0 API ограниченны и сведены к генерации тонов и воспроизведению цифровых звуковых эффектов через wave-файлы. О специфике воспроизведения звука я расскажу в главе 8.
   Ранее вы узнали, что CLDC служит основой для работы в сетях и ввода/вывода с помощью Generic Connection Framework (GCF). Надстройкой MIDP API над этим является пакет javax.microedition.io, который включает в себя ряд интерфейсов и классов для установления беспроводных соединений с сетями и обмена данными. Пакет javax.microedition.pki используется в сочетании с пакетом javax.microedition.io для выполнения защищенных соединений. В главе 14 вы узнаете, как выполнять основные сетевые задачи.
   Поскольку мобильные телефоны не имеют жестких дисков или явной файловой системы (пока), вы, вероятно, не станете полагаться на файлы для хранения постоянных данных мидлетов. Вместо этого MIDP API предлагает другой вариант сохранения и доступа к постоянным данным мидлета – Record Management System (RMS, Система управления записями). MIDP RMS реализует простой API базы данных (основанный на записях) для постоянного хранения данных, например, список лучших достижений или данных сохраненных игр. Классы и интерфейсы, составляющие RMS, содержатся в пакете javax.microedition.rms.

Понятие о мидлетах

   Sun Microsystems использует суффикс «let» для обозначения различных типов программ, создаваемых с помощью Java. Апплеты (applet), сервлеты (servlet), спотлеты (spotlet) и теперь мидлеты (MIDlet) – это лишь часть из них. Мидлеты – это программы, разработанные с использованием J2ME API, которые запускаются в мобильной среде. Мидлетам требуется особая среда выполнения. Эта среда главным образом состоит из менеджера приложений (application manager), который выполняет функции выбора и запуска мидлетов на мобильном устройстве. Этот менеджер приложений для мидлетов отвечает за создание обрамляющего окна мидлета.

Внутри мидлета

   Пожалуй, не столь удивительно, что каждый мидлет должен быть производным от стандартного класса, являющегося частью MIDP API. Этот класс расположен в пакете javax.microedition.midlet и носит название MIDlet. Хотя этот класс определяет несколько методов, три из них очень важны для разработки собственных мидлетов:
   ► startApp() – запустить мидлет;
   ► pauseApp() – приостановить выполнение мидлета;
   ► destroyApp() – удалить мидлет.
   Чтобы лучше понять, как эти методы влияют на мидлет, важно уяснить, что мидлет имеет три различных состояния, определяющих его работу: Active (Активное), Paused (Приостановленное) и Destroyed (Разрушенное). Этим трем состояниям соответствуют три метода, которые обычно напрямую вызываются менеджером приложения среды выполнения. В некоторых случаях вы можете вызывать их самостоятельно, особенно метод destroyApp(). Эти методы объединены термином «методы жизненного цикла» (life cycle methods), потому что они управляют жизненным циклом мидлета. Именно эти методы позволяют менеджеру приложений управлять несколькими мидлетами и предоставлять каждому из них доступ к ресурсам устройства.
Жизненный цикл мидлета
   Жизненный цикл состоит из трех частей, о которых вы только что узнали. В обычном мидлете большая часть времени проходит в состояниях Active и Paused, а при закрытии мидлета он переходит в состояние Destroyed до тех пор, пока не будет полностью удален из памяти. В большинстве случаев вы переопределяете методы жизненного цикла мидлета, потому как важно выделять и высвобождать ресурсы мобильного телефона в соответствии с каждым из состояний. Например, при запуске игрового мидлета, вероятно, возникает необходимость создать объекты и/или загрузить данные. Когда выполнение мидлета приостанавливается, целесообразно высвободить часть ресурсов, закрыть соединения с сетью и приостановить воспроизведение музыки в игре. И, наконец, при условии разрушения мидлета необходимо высвободить память, а также сохранить нужные данные.
   Помните, что мидлет может входить и выходить из состояний Active и Paused не один раз в течение жизненного цикла. Но если мидлет войдет в состояние Destroyed, он уже не сможет вернуться обратно. С этой точки зрения, отдельный игровой мидлет может прожить лишь одну жизнь.
Команды мидлета
   Кроме переопределения методов жизненного цикла, большинство мидлетов реализуют метод commandAction(), обработчик событий, определенный интерфейсом javax.microedition.ldui.CommandListener. Команды используются для контроля игровых мидлетов и инициализации таких действий, как приостановка игры, сохранение данных, изменение настроек и выход из игры. Команды мидлета доступны через экранные кнопки (soft button) или меню и должны обрабатываться методом commandAction().
   В копилку Игрока
   Экранные кнопки (soft buttons) – это специальные кнопки, расположенные на дисплее мобильного телефона. Они предназначены для выполнения специальных команд мидлетов. Щелчок по кнопке выполняет команду, с которой эта кнопка связана. Щелчки по кнопкам для управления игрой обрабатываются иначе, чем нажатия экранных кнопок. Подробнее вы узнаете об этом из главы 6.
Дисплей, экраны и холсты
   Одна из важнейших концепций мидлетов, которой стоит уделить внимание, – это класс Display, представляющий собой менеджер экрана мобильного устройства. Класс Display определен в пакете javax.microedition.lcdui, как и GUI-классы. Этот класс отвечает за управление экраном и вводом пользователя.
   Вам не придется создавать объект Display, обычно вы получаете ссылку на объект Display в методе startApp() игрового мидлета, после чего настраиваете экран и пользовательский интерфейс. Для каждого мидлета, выполняемого на устройстве, существует только одно представление Display.
   Другой важный класс, имеющий отношение к экрану устройства, – это javax.miccroedition.lcdui.Canvas, который представляет собой абстрактную поверхность для рисования, размер которой равен размеру экрана. Холст (canvas) используется для выполнения прямых операций рисования, например, рисования линий и кривых или отображения картинок. Как вы, вероятно, можете догадаться, холсты формируют основу для вывода игровых изображений. На самом деле существует специальный класс javax.microedition.lcdui.GameCanvas, который предназначен для создания графики для игр. Класс GameCanvas отличается от класса Canvas тем, что поддерживает высокоэффективные средства отображения анимации, часто применяемой в играх.
   В копилку Игрока
   Если вы создаете игру с возможностью изменения настроек, или вам необходимо получить информацию от пользователя, используйте класс javax.microedition.lcdui.Screen. Экран (screen) – это настраиваемый GUI-компонент мидлета, который служит базовым классом для других важных компонентов. Значимость экранов заключается в том, что они отображают всю экранную информацию. Несколько экранов не могут отображаться одновременно. Вы можете представить несколько экранов как карты, которые берете одну за другой. Большинство мидлетов используют классы javax.miroedition.lcdui.Form, javax.miroedition.lcdui.TextBox, или javax.miroedition.lcdui.List, поскольку они предоставляют широкие возможности. Экраны можно использовать в совокупности с объектами класса Canvas, в результате чего для игрового мидлета можно создать полноценный GUI. Нельзя отображать экран и холст одновременно, однако вы можете переключаться между отображениями.

Основы разработки мидлетов

   Прежде чем приступить к разработке мидлетов, необходимо установить J2ME Wireless Toolkit, который находится на прилагаемом компакт-диске. Вы также можете использовать инструменты для разработки мобильных приложений, выпускаемые другими компаниями, если вашей целью является написание приложения для конкретной модели телефона. Но если вы хотите эмулировать мобильные телефоны с поддержкой Java на компьютере, можно использовать J2ME Wireless Toolkit.
   Чтобы воплотить концепцию мидлета в реальность, необходимо:
   1. разработать файлы кода;
   2. скомпилировать файлы с исходным кодом в классы байт-кода;
   3. выполнить предварительную верификацию классов байт-кода;
   4. упаковать файлы байт-кода в файл JAR, добавить необходимые ресурсы и файлы манифеста (подробнее об этом чуть позже);
   5. разработать JAD-файл (описатель приложения), сопровождающий JAR-файл;
   6. протестировать и отладить мидлет.
   Шаг 1 выполняется в обычном текстовом редакторе. Если у вас нет специального редактора кода, можно воспользоваться, например, текстовым редактором Notepad. Шаг 2 подразумевает использование стандартного компилятора Java для компиляции файлов мидлета с исходным кодом. На шаге 3 необходимо выполнить предварительную верификацию скомпилированного кода, для чего используйте специальный инструмент предварительной верификации. На шаге 4 выполняется упаковка файлов кода мидлета в Java-архив (JAR). Шаг 5 требует создания специального файла описания – текстового файла, содержащего информацию о вашем мидлете. И, наконец, на шаге 6 вы можете протестировать мидлет в эмуляторе J2ME.
   Хотя вы можете выполнить каждый из этих шагов, используя инструменты J2ME Wireless Toolkit, вызываемые из командной строки, в предыдущей главе вы увидели, как просто собираются и тестируются приложения в среде Sun KToolbar.

Создание примера игры Skeleton

   Я бы хотел рассказать вам о создании трехмерной игры в реальном времени для нескольких игроков, однако из-за большой сложности это затруднит понимание того, как устроен и написан мидлет. Для начала вы узнаете, как построить простейший мидлет, который называется Skeleton. Этот мидлет отображает текстовую информацию о мобильном телефоне. Поскольку эта информация содержит очень важные параметры телефона (размер игрового экрана и глубина цвета), полезно выполнять такую проверку на реальных устройствах.
   При построении мидлета Skeleton вы пройдете через последовательность шагов, обозначенную в предыдущем разделе. Этот процесс практически идентичен для построения любых мидлетов. Ниже перечислены этапы построения мидлета Skeleton:
   1. написание кода мидлета;
   2. компиляция мидлета;
   3. предварительная верификация мидлета;
   4. упаковка мидлета;
   5. тестирование мидлета.
   В последующих разделах подробно рассматривается каждый из этапов, а кульминацией будет полная разработка первого J2ME-мидлета.

Написание программного кода

   В этом разделе вы создадите код мидлета Skeleton. Первая часть создаваемого кода – это импорт нескольких важных пакетов J2ME. Вы можете не импортировать пакеты, а ссылаться на них через полное имя (например, javax.microedition.midlet.MIDlet), но это очень неудобно и делает код плохо читаемым. Поэтому первые две строки кода вашего мидлета импортируют два главных пакета, необходимых для разработки:
 
   import javax.microedition.midlet.*;
   import javax.microedition.lcdui.*;
 
   Совет Разработчику
   Многие Java-программисты не одобряют импортирование целых пакетов с использованием группового символа * (звездочка), поскольку при этом не содержится информация об особых классах, которые вы импортируете. Однако это очень простой и быстрый способ импортировать все классы пакета, а для целей этой книги я буду использовать самый простой подход, чтобы сделать код как можно более понятным. Не бойтесь импортировать классы при написании собственного кода, это поможет вам сделать код более ясным.