Страница:
Рис. 4.3. В стандартной программе Windows Paint вы можете определить значения компонентов нужного цвета
Работа с графикой в J2ME
Рисование графических примитивов
Вывод текста
Вывод изображений
Создание программы Olympics
Написание программного кода
Тестирование готового приложения
Создание слайд-шоу
Написание программного кода
В копилку Игрока
Чтобы увидеть еще одну точку зрения на RGB-цвета, посетите сайт http://www.rgb-game.com/.
Работа с графикой в J2ME
Если у вас уже есть опыт программирования на стандартном Java, вы, несомненно, знакомы с классом Graphics, который дает возможность вывода графических примитивов (линий, прямоугольников и т. п.), текста и изображений как на дисплей, так и в буфер. Для выполнения операций с графикой вы вызываете методы объекта Graphics, параметра метода мидлета paint(). Объект Graphics() передается в метод paint(), а затем используется для вывода графики на экран мидлета или в буфер. Поскольку объект Graphics() автоматически передается в метод paint(), нет необходимости создавать его вручную.
Этот метод принимает три целочисленных параметра, которые соответствуют трем цветовым компонентам. Подобно setColor() работает метод setGrayScale(), который принимает один целочисленный параметр из диапазона от 0 до 255. Если оттенок серого создается на цветном экране, то всем трем компонентам присваивается одинаковое значение, результатом чего является оттенок серого.
Объекты Graphics также имеют атрибут шрифта, который определяет размер выводимого текста. Метод setFont() принимает в качестве параметра объект Font и применяется для настройки шрифта выводимого текста. Подробнее о выводе текста речь пойдет позже в этой главе.
► рисование графических примитивов;
► вывод изображений.
► вывод текста;
В последующих разделах вы более подробно изучите эти операции и узнаете, как они выполняются.
Совет РазработчикуКласс Graphics имеет несколько атрибутов, которые определяют, как будут выполняться различные графические операции. Наиболее важные из этих атрибутов – это атрибуты цвета, которые определяют цвета, используемые при выполнении операций с графикой (например, рисование линий). Этот атрибут устанавливается вызовом метода setColor(), определенного в классе Graphics.
Метод paint() является членом класса Canvas, который представляет абстрактную поверхность для рисования. Чтобы использовать класс Graphics для отображения графики, вы должны создать объект класса Canvas и определить его как экран вашего мидлета, подобно тому, как это было сделано в предыдущей главе для мидлета Skeleton.
Этот метод принимает три целочисленных параметра, которые соответствуют трем цветовым компонентам. Подобно setColor() работает метод setGrayScale(), который принимает один целочисленный параметр из диапазона от 0 до 255. Если оттенок серого создается на цветном экране, то всем трем компонентам присваивается одинаковое значение, результатом чего является оттенок серого.
Объекты Graphics также имеют атрибут шрифта, который определяет размер выводимого текста. Метод setFont() принимает в качестве параметра объект Font и применяется для настройки шрифта выводимого текста. Подробнее о выводе текста речь пойдет позже в этой главе.
Совет РазработчикуБольшинство операций с графикой, выполняемых классом Graphics, можно свести к следующим трем категориям:
Другая версия метода setColor() принимает единственный целочисленный параметр, определяющий цвет. Отдельные цветовые компоненты (красный, зеленый и синий) определены внутри значения цвета в соответствии со следующим шестнадцатеричным форматом: 0x00RRGGBB. Иначе говоря, красный (RR), зеленый (GG) и синий (BB) компоненты хранятся в трех младших байтах 32-битной целой величины.
► рисование графических примитивов;
► вывод изображений.
► вывод текста;
В последующих разделах вы более подробно изучите эти операции и узнаете, как они выполняются.
Рисование графических примитивов
Графические примитивы состоят из линий, прямоугольников и дуг. Вы можете создавать весьма сложные объекты, используя эти примитивы. Класс Graphics содержит методы рисования примитивов. Также методы этого класса можно использовать для заполнения внутренних областей примитивов. Хотя графика, созданная при помощи примитивов, не сравнится с растровыми изображениями, добавив немного воображения, можно творить чудеса!
void drawLine(int x1, int y1, int x2, int y2)
Первые два параметра x1 и y1 определяют первую точку линии, другие два параметра – конечную. Важно понять, что эти координаты определяют границы начала и конца отрезка. Предположим, что вы рисуете линию в положительном направлении осей X и Y, тогда x1 и y1 указывают на верхний левый угол первой точки линии, а x2 и y2 указывают на нижний правый угол последней точки прямой. Чтобы нарисовать линию в мидлете, вызовите функцию drawLine() в методе мидлета paint(), как показано в примере:
public void paint(Graphics g) {
g.drawLine(5,10,15,55);
}
Этот код проводит линию из точки с координатами (5,10) в точку с координатами (15,55). Вы можете изменить стиль линии, воспользовавшись методом setStrokeStyle(). Этот метод принимает одну из двух констант Graphics.SOLID или Graphics.DOTTED, определяющих вид линии: сплошная или точечная. Если вы явно не укажете стиль линии, то по умолчанию будет использоваться Graphics.SOLID.
void drawRect(int x, int y, int width, int height)
Параметры x и y определяют положение верхнего левого угла прямоугольника, а параметры width и height определяют размеры прямоугольника в пикселях. Чтобы использовать метод drawRect(), вызовите метод paint():
public void paint(Graphics g) {
g.drawRect(5, 10, 15, 55);
}
В результате выполнения этого кода будет нарисован прямоугольник шириной 15 пикселей и высотой 55 пикселей, верхний левый угол которого имеет координаты (5,10). Существует также метод drawRoundRect(), который позволяет рисовать прямоугольники с округленными углами:
void drawRoundRect(int x, int y, int width, int height, int arcWidth,
int arcHeight)
Метод drawRoundRect() требует два дополнительных параметра по сравнению с drawRect(): arcWidth и arcHeight. Эти параметры определяют ширину и высоту дуги, округляющей углы прямоугольника. Если вы хотите нарисовать овал, то параметры arcWidth и arcHeight должны быть равны половине ширины и высоты прямоугольника соответственно. Ниже приведен пример вызова метода drawRoundRect(), результатом выполнения кода будет овал:
public void paint(Graphics g) {
g.drawRoundRect(5, 10, 15, 55, 6, 12);
}
В этом примере представлен прямоугольник, ширина которого 15 пикселей, а высота 55 пикселей, левый верхний угол в точке с координатами (5,10). Углы округлены дугами, высотой 12 пикселей и шириной 6 пикселей. Также в классе Graphics есть методы для рисования прямоугольников, которые заливают внутреннюю область примитива текущим цветом: fillRect() и fillRoundRect().
void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
Первые четыре параметра метода drawArc() определяют эллипс, частью которого является дуга. Оставшиеся два параметра определяют дугу как часть овала. На рис. 4.4 показана дуга.
Рис. 4.4. В MIDP-графике дуга – это часть эллипса
Как видно из рисунка, дуга эллипса определяется начальным углом (в градусах), а также градусной мерой в определенном направлении. Положительное направление – по часовой стрелке, а отрицательное – против. Дуга, показанная на рис. 4.4, начинается с угла 95° и величины дуги 115°, в результате получается угол 210°.
Ниже приведен пример использования метода drawArc():
public void paint(Graphics g) {
g.drawArc(5, 10, 150, 75, 95, 115);
}
В результате будет нарисована дуга, являющаяся частью эллипса шириной 150° пикселей и высотой 75° пикселей. Она расположена в точке с координатами (5,10) и простирается в положительном направлении на 115°.
Вы, вероятно, будете удивлены, узнав, что в классе Graphics нет метода drawOval(). Чтобы нарисовать эллипс, вы должны использовать метод drawArc(), для чего в качестве последнего параметра передайте 360°. Это означает, что дуга будет не частью эллипса, а полностью эллипсом.
Метод для рисования дуги с заливкой называется fillArc(). Эта функция очень удобна, поскольку с ее помощью вы можете рисовать заполненные круговые или эллиптические сегменты. Например, если вы захотите создать мобильную версию аркады Food Fight, удобно использовать метод fillArc().
Линии
Линия – это простейший графический примитив, а следовательно, его проще всего создать. Тем не менее даже самые популярные аркады, например, Asteroids, используют векторную графику, которая состоит только из линий. Метод drawLine() строит линии, он объявлен так:void drawLine(int x1, int y1, int x2, int y2)
Первые два параметра x1 и y1 определяют первую точку линии, другие два параметра – конечную. Важно понять, что эти координаты определяют границы начала и конца отрезка. Предположим, что вы рисуете линию в положительном направлении осей X и Y, тогда x1 и y1 указывают на верхний левый угол первой точки линии, а x2 и y2 указывают на нижний правый угол последней точки прямой. Чтобы нарисовать линию в мидлете, вызовите функцию drawLine() в методе мидлета paint(), как показано в примере:
public void paint(Graphics g) {
g.drawLine(5,10,15,55);
}
Этот код проводит линию из точки с координатами (5,10) в точку с координатами (15,55). Вы можете изменить стиль линии, воспользовавшись методом setStrokeStyle(). Этот метод принимает одну из двух констант Graphics.SOLID или Graphics.DOTTED, определяющих вид линии: сплошная или точечная. Если вы явно не укажете стиль линии, то по умолчанию будет использоваться Graphics.SOLID.
Совет Разработчику
MIDP API не поддерживает рисование многоугольников. Вы должны рисовать многоугольники самостоятельно, используя команду drawLine().
Прямоугольники
Прямоугольники также очень просто нарисовать в мидлете. Метод drawRect() позволяет рисовать прямоугольники, указывая координаты верхнего левого угла, высоту и ширину прямоугольника. Этот метод объявлен так:void drawRect(int x, int y, int width, int height)
Параметры x и y определяют положение верхнего левого угла прямоугольника, а параметры width и height определяют размеры прямоугольника в пикселях. Чтобы использовать метод drawRect(), вызовите метод paint():
public void paint(Graphics g) {
g.drawRect(5, 10, 15, 55);
}
В результате выполнения этого кода будет нарисован прямоугольник шириной 15 пикселей и высотой 55 пикселей, верхний левый угол которого имеет координаты (5,10). Существует также метод drawRoundRect(), который позволяет рисовать прямоугольники с округленными углами:
void drawRoundRect(int x, int y, int width, int height, int arcWidth,
int arcHeight)
Метод drawRoundRect() требует два дополнительных параметра по сравнению с drawRect(): arcWidth и arcHeight. Эти параметры определяют ширину и высоту дуги, округляющей углы прямоугольника. Если вы хотите нарисовать овал, то параметры arcWidth и arcHeight должны быть равны половине ширины и высоты прямоугольника соответственно. Ниже приведен пример вызова метода drawRoundRect(), результатом выполнения кода будет овал:
public void paint(Graphics g) {
g.drawRoundRect(5, 10, 15, 55, 6, 12);
}
В этом примере представлен прямоугольник, ширина которого 15 пикселей, а высота 55 пикселей, левый верхний угол в точке с координатами (5,10). Углы округлены дугами, высотой 12 пикселей и шириной 6 пикселей. Также в классе Graphics есть методы для рисования прямоугольников, которые заливают внутреннюю область примитива текущим цветом: fillRect() и fillRoundRect().
Совет Разработчику
Если вы хотите нарисовать идеальный квадрат с помощью одного из методов рисования прямоугольников, просто введите одинаковые ширину и высоту.
Дуги
Дуги намного сложнее, чем линии и прямоугольники. Дуга – это часть эллипса. Удалите часть эллипса – и вы получите дугу. Если вы не можете представить себе дугу, представьте колобка из игры Pac-Man, когда он съедает очередную точку. Дуга является частью эллипса. Чтобы задать дугу, вы должны задать эллипс и указать его часть. Метод рисования дуги объявлен так:void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
Первые четыре параметра метода drawArc() определяют эллипс, частью которого является дуга. Оставшиеся два параметра определяют дугу как часть овала. На рис. 4.4 показана дуга.
Рис. 4.4. В MIDP-графике дуга – это часть эллипса
Как видно из рисунка, дуга эллипса определяется начальным углом (в градусах), а также градусной мерой в определенном направлении. Положительное направление – по часовой стрелке, а отрицательное – против. Дуга, показанная на рис. 4.4, начинается с угла 95° и величины дуги 115°, в результате получается угол 210°.
Ниже приведен пример использования метода drawArc():
public void paint(Graphics g) {
g.drawArc(5, 10, 150, 75, 95, 115);
}
В результате будет нарисована дуга, являющаяся частью эллипса шириной 150° пикселей и высотой 75° пикселей. Она расположена в точке с координатами (5,10) и простирается в положительном направлении на 115°.
Вы, вероятно, будете удивлены, узнав, что в классе Graphics нет метода drawOval(). Чтобы нарисовать эллипс, вы должны использовать метод drawArc(), для чего в качестве последнего параметра передайте 360°. Это означает, что дуга будет не частью эллипса, а полностью эллипсом.
Метод для рисования дуги с заливкой называется fillArc(). Эта функция очень удобна, поскольку с ее помощью вы можете рисовать заполненные круговые или эллиптические сегменты. Например, если вы захотите создать мобильную версию аркады Food Fight, удобно использовать метод fillArc().
Совет Разработчику
Чтобы нарисовать идеальную окружность с помощью методов drawArc() или fillArc(), просто введите одинаковые значения ширины и высоты, и задайте угол 360°.
Вывод текста
Хотя текст занимает не центральное место в играх, полезно познакомиться с его выводом. По крайней мере, в любых играх выводится количество набранных очков, и графический код должен отображать эту информацию. В мидлете текст выводится с применением текущего выбранного шрифта. По умолчанию используется шрифт среднего размера, но может возникнуть необходимость в шрифте другого размера, полужирного или курсива. Для этого вы должны создать шрифт и выбрать его перед тем, как применять. Метод setFont() используется для выбора шрифта, он объявлен так:
void setFont(Font font)
Объект Font моделирует текстовый шрифт и определяет вид, стиль и его размер. Объект Font поддерживает четыре разных стиля, которые определяются следующими константными членами класса: STYLE_PLAIN, STYLE_BOLD, STYLE_ITALIC и STYLE_UNDERLINED. Эти стили действительно являются константами, а последние три можно использовать в совокупности. Стиль STYLE_PLAIN отменяет все примененные к шрифту стили. Чтобы создать объект класса Font, вызовите статический метод getFont() и передайте в него вид, стиль и размер текста, каждый из этих параметров представляет собой целое число:
static Font getFont(int face, int style, int size)
Поскольку шрифты ограниченны в мидлетах, вы должны использовать целочисленные константы для определения каждого параметра. Например, вид шрифта должен быть определен одним из следующих значений: FACE_SYSTEM, FACE_MONOSPACE или FACE_PROPORTINAL. Аналогично, стиль шрифта должен быть определен одной из констант, о которых я упоминал ранее: STYLE_PLAIN или комбинацией STYLE_BOLD, STYLE_ITALIC и STYLE_UNDERLINED. Наконец, размер шрифта задается одной из предопределенных констант: SIZE_SMALL, SIZE_MEDIUM или SIZE_LARGE. Ниже приведен пример создания крупного полужирного подчеркнутого шрифта:
Font myFont = Font.getFont(Font.MONOSPACE, Font.LARGE,
Font.BOLD | Font.UNDERLINED);
Обратите внимание, что в MIDP-графике вы не можете создавать собственные шрифты, что вполне обоснованно ввиду ограниченных возможностей дисплея мобильного устройства. Также помните, что тот или иной шрифт доступен на мобильном телефоне, это хороший довод тестировать приложение на реальном устройстве.
После того как вы определили шрифт методом getFont(), вы должны применить его к выводимому тексту, для чего используйте метод setFont():
g.setFont(myFont);
Теперь вы готовы к тому, чтобы вывести текст с нужными настройками. Метод drawString(), определенный в классе Graphics, – это как раз то, что нужно. Этот метод объявлен так:
void drawstring(String str, int x, int y, int anchor)
Метод drawString() в качестве первого параметра принимает объект класса String, который содержит выводимый текст. Следующие два параметра x и y определяют точку вывода текста. Особое значение этой точке придает параметр anchor. Чтобы упростить вывод текста и изображений, MIDP API предусматривает анкеры, которые помогают сэкономить массу сил при выводе текста и изображений и избавляют от излишних вычислений. Анкер (или точка привязки) ассоциирован с горизонтальной и вертикальной константами, каждая из которых определяет соответственно горизонтальное и вертикальное положения текста по отношению к анкеру. Горизонтальные константы, используемые для описания анкера, – это LEFT, RIGHT и HCENTER. Одна из этих констант в сочетании с вертикальной константой полностью описывает положение выводимого объекта. Вертикальные константы – это TOP, BASELINE и BOTTOM.
В качестве примера использования анкеров рассмотрим, как можно вывести текст и разместить его по центру у верхней границы экрана. Для этого нужно вызвать метод drawString() со следующими параметрами:
g.drawStirng(«Look up here!», getWidth() / 2, 0, Graphics.HCENTER | Graphics.TOP);
В этом коде текст выводится на точке экрана, расположенной в его верхней части в середине, – getWidth() / 2. Я предположил, что этот код помещен внутри класса, производного от Canvas, поэтому я смог воспользоваться методом getWidth() и получить значение ширины экрана. Это положение дополняется анкером, который является комбинацией двух констант Graphics.HCENTER и Graphics.TOP. Это означает, что выводимый текст форматируется по центру в горизонтальном направлении, а также, что верхняя граница текста имеет координату y.
Кроме метода drawString(), есть еще ряд методов, предназначенных для вывода текста. Методы drawChar() и drawChars() используются для вывода отдельных символов:
void drawChar(char character, int x, int y, int anchor)
void drawChars(char[] data, int offset, int length, int x, int y,
int anchor)
Оба метода работают аналогично методу drawString(), они запрашивают координаты точки вывода и анкер. Существует метод drawSubString(), с помощью которого можно выводить часть строки:
void drawSubString(String str, int offset, int len, int x, int y,
int anchor)
Этот метод содержит дополнительные параметры offset и len, определяющие подстроку в строке, передаваемой через параметр str.
void setFont(Font font)
Объект Font моделирует текстовый шрифт и определяет вид, стиль и его размер. Объект Font поддерживает четыре разных стиля, которые определяются следующими константными членами класса: STYLE_PLAIN, STYLE_BOLD, STYLE_ITALIC и STYLE_UNDERLINED. Эти стили действительно являются константами, а последние три можно использовать в совокупности. Стиль STYLE_PLAIN отменяет все примененные к шрифту стили. Чтобы создать объект класса Font, вызовите статический метод getFont() и передайте в него вид, стиль и размер текста, каждый из этих параметров представляет собой целое число:
static Font getFont(int face, int style, int size)
Поскольку шрифты ограниченны в мидлетах, вы должны использовать целочисленные константы для определения каждого параметра. Например, вид шрифта должен быть определен одним из следующих значений: FACE_SYSTEM, FACE_MONOSPACE или FACE_PROPORTINAL. Аналогично, стиль шрифта должен быть определен одной из констант, о которых я упоминал ранее: STYLE_PLAIN или комбинацией STYLE_BOLD, STYLE_ITALIC и STYLE_UNDERLINED. Наконец, размер шрифта задается одной из предопределенных констант: SIZE_SMALL, SIZE_MEDIUM или SIZE_LARGE. Ниже приведен пример создания крупного полужирного подчеркнутого шрифта:
Font myFont = Font.getFont(Font.MONOSPACE, Font.LARGE,
Font.BOLD | Font.UNDERLINED);
Обратите внимание, что в MIDP-графике вы не можете создавать собственные шрифты, что вполне обоснованно ввиду ограниченных возможностей дисплея мобильного устройства. Также помните, что тот или иной шрифт доступен на мобильном телефоне, это хороший довод тестировать приложение на реальном устройстве.
Совет Разработчику
Если возникнет необходимость вернуться к настройкам шрифта, принятым по умолчанию, воспользуйтесь методом getDefaultFont() класса Font.
После того как вы определили шрифт методом getFont(), вы должны применить его к выводимому тексту, для чего используйте метод setFont():
g.setFont(myFont);
Теперь вы готовы к тому, чтобы вывести текст с нужными настройками. Метод drawString(), определенный в классе Graphics, – это как раз то, что нужно. Этот метод объявлен так:
void drawstring(String str, int x, int y, int anchor)
Метод drawString() в качестве первого параметра принимает объект класса String, который содержит выводимый текст. Следующие два параметра x и y определяют точку вывода текста. Особое значение этой точке придает параметр anchor. Чтобы упростить вывод текста и изображений, MIDP API предусматривает анкеры, которые помогают сэкономить массу сил при выводе текста и изображений и избавляют от излишних вычислений. Анкер (или точка привязки) ассоциирован с горизонтальной и вертикальной константами, каждая из которых определяет соответственно горизонтальное и вертикальное положения текста по отношению к анкеру. Горизонтальные константы, используемые для описания анкера, – это LEFT, RIGHT и HCENTER. Одна из этих констант в сочетании с вертикальной константой полностью описывает положение выводимого объекта. Вертикальные константы – это TOP, BASELINE и BOTTOM.
В качестве примера использования анкеров рассмотрим, как можно вывести текст и разместить его по центру у верхней границы экрана. Для этого нужно вызвать метод drawString() со следующими параметрами:
g.drawStirng(«Look up here!», getWidth() / 2, 0, Graphics.HCENTER | Graphics.TOP);
В этом коде текст выводится на точке экрана, расположенной в его верхней части в середине, – getWidth() / 2. Я предположил, что этот код помещен внутри класса, производного от Canvas, поэтому я смог воспользоваться методом getWidth() и получить значение ширины экрана. Это положение дополняется анкером, который является комбинацией двух констант Graphics.HCENTER и Graphics.TOP. Это означает, что выводимый текст форматируется по центру в горизонтальном направлении, а также, что верхняя граница текста имеет координату y.
Кроме метода drawString(), есть еще ряд методов, предназначенных для вывода текста. Методы drawChar() и drawChars() используются для вывода отдельных символов:
void drawChar(char character, int x, int y, int anchor)
void drawChars(char[] data, int offset, int length, int x, int y,
int anchor)
Оба метода работают аналогично методу drawString(), они запрашивают координаты точки вывода и анкер. Существует метод drawSubString(), с помощью которого можно выводить часть строки:
void drawSubString(String str, int offset, int len, int x, int y,
int anchor)
Этот метод содержит дополнительные параметры offset и len, определяющие подстроку в строке, передаваемой через параметр str.
Вывод изображений
Изображения очень важны для программирования игр, если, конечно, речь не идет о текстовых играх или играх, в которых применяется векторная графика. Изображения – это прямоугольные графические объекты, составленные из цветных пикселей. Каждый пиксель изображения описывает цвет определенной части изображения. Пиксели имеют уникальные цвета, описываемые цветовой системой RGB. Цветные изображения в MIDP-графики – это 24-битные изображения, следовательно, каждый пиксель изображения описывается 24 битами. Красный, зеленый и синий компоненты хранятся внутри этих четырех битов как самостоятельные 8-битовые значения.
public static Image createImage(String name) throws IOException
Чтобы создать изображения, используя метод createImage(), необходимо передать название файла с изображением:
Image img = Image.createImage(«Explosion.png»);
Метод createImage() возвращает объект класса Image, который впоследствии можно использовать для работы с изображением в MIDP API. Также можно создать пустое изображение, вызвав другую версию метода createImage(), который принимает ширину и высоту изображения. Класс Image представляет графические изображения (файлы форматов PNG, GIF или JPEG) и предоставляет ряд методов для определения размеров изображения. Также этот класс реализует метод, с помощью которого вы можете создать объект Graphics для картинки и рисовать на существующем изображении.
boolean drawImage(Image img, int x, int y, int anchor)
Вероятно, этот метод покажется вам знакомым, поскольку в нем, также как и в методе drawString(), используются анкеры. Подобно drawString() метод drawImage() выводит изображение в точке с координатами (x,y) и с учетом параметра anchor. Для вывода изображений можно использовать те же константы, что и при выводе текста.
Итак, чтобы нарисовать изображение, сначала необходимо вызвать статический метод Image.createImage() и создать и загрузить изображение. Затем следует вызвать метод drawImage() и вывести изображение на экран. Ниже приведен код, который загружает и выводит изображение:
public void paint(Graphics g) {
//очистить экран
g.setColor(255,255,255); //белый
g.FillRect(0, 0, getWidth(), getHeight());
//создать и загрузить изображение
Image img = Image.createImage("Splash.png");
//вывести изображение
g.drawImage(img, getWidth() / 2, getHeight() / 2, //Поскольку используются атрибуты HCENTER и VCENTER,
Graphics.HCENTER | Graphics.VCENTER); //изображение выводится в центре экрана
}
В этом примере сначала очищается дисплей, для чего выбирается белый цвет, которым заполняется весь экран. Перед рисованием необходимо получить чистую поверхность. Затем с помощью метода createImage() загружается и создается изображение Splash.png. После того как изображение создано, вызывается метод drawImage(), и картинка выводится на дисплей, константы HCENTER и VCENTER определяют анкер.
В копилку ИгрокаПеред тем как вернуться к подробному изучению вывода изображений, вы должны научиться загружать картинки. Поскольку обычно изображения хранятся во внешних файлах, для начала их необходимо загрузить. Для этого используется специальный статический метод createImage() класса Image, его объявление выглядит так:
Вы, вероятно, слышали о 32-битной графике, где дополнительные 8 бит используются альфа-компонентами цвета, определяющих прозрачность пикселя. MIDP поддерживает прозрачность, а, следовательно, может использовать дополнительные 8 бит для альфа-компонентов на телефонных аппаратах, поддерживающих 8-битовую альфа-прозрачность. Если вы вспомните, мидлет Skeleton, который мы создали в предыдущей главе, сообщал о количестве альфа-уровней, поддерживаемых телефоном. При работе с книгой вы научитесь эффективно использовать 1-битовую альфа-прозрачность, т. е. простую прозрачность цвета изображения.
public static Image createImage(String name) throws IOException
Чтобы создать изображения, используя метод createImage(), необходимо передать название файла с изображением:
Image img = Image.createImage(«Explosion.png»);
Метод createImage() возвращает объект класса Image, который впоследствии можно использовать для работы с изображением в MIDP API. Также можно создать пустое изображение, вызвав другую версию метода createImage(), который принимает ширину и высоту изображения. Класс Image представляет графические изображения (файлы форматов PNG, GIF или JPEG) и предоставляет ряд методов для определения размеров изображения. Также этот класс реализует метод, с помощью которого вы можете создать объект Graphics для картинки и рисовать на существующем изображении.
В копилку ИгрокаВ классе Graphics есть единственный метод для вывода изображения на экран – drawImage():
Если вы не знаете, формат изображений PNG (Portable Network Graphics – Переносимая сетевая графика) – это улучшение формата GIF, постепенно распространяющегося как альтернатива GIF. Изображения в формате PNG сжимаются лучше GIF-изображений, в результате их файлы имеют меньший размер. Также, PNG-изображения удобнее использовать при создании игр, поскольку они поддерживают переменные альфа-уровни. Класс Image полностью поддерживает формат PNG.
boolean drawImage(Image img, int x, int y, int anchor)
Вероятно, этот метод покажется вам знакомым, поскольку в нем, также как и в методе drawString(), используются анкеры. Подобно drawString() метод drawImage() выводит изображение в точке с координатами (x,y) и с учетом параметра anchor. Для вывода изображений можно использовать те же константы, что и при выводе текста.
Итак, чтобы нарисовать изображение, сначала необходимо вызвать статический метод Image.createImage() и создать и загрузить изображение. Затем следует вызвать метод drawImage() и вывести изображение на экран. Ниже приведен код, который загружает и выводит изображение:
public void paint(Graphics g) {
//очистить экран
g.setColor(255,255,255); //белый
g.FillRect(0, 0, getWidth(), getHeight());
//создать и загрузить изображение
Image img = Image.createImage("Splash.png");
//вывести изображение
g.drawImage(img, getWidth() / 2, getHeight() / 2, //Поскольку используются атрибуты HCENTER и VCENTER,
Graphics.HCENTER | Graphics.VCENTER); //изображение выводится в центре экрана
}
В этом примере сначала очищается дисплей, для чего выбирается белый цвет, которым заполняется весь экран. Перед рисованием необходимо получить чистую поверхность. Затем с помощью метода createImage() загружается и создается изображение Splash.png. После того как изображение создано, вызывается метод drawImage(), и картинка выводится на дисплей, константы HCENTER и VCENTER определяют анкер.
Создание программы Olympics
Теперь у вас есть представление о MIDP-графике и, вероятно, вам не терпится посмотреть, как это все работает в контексте мидлета. Вы узнали, что графика обрабатывается методом paint(). Однако класс мидлета не содержит этого метода, поэтому для выполнения операций с графикой вы должны использовать класс Canvas. Класс Canvas представляет собой абстрактную поверхность и должен быть включен в класс мидлета. Графические операции выполняются с помощью класса Graphics. Класс, производный от Canvas, можно использовать для вывода изображений на экран.
Чтобы начать работу над графическим мидлетом, вы должны выполнить следующее:
1. создать класс, производный от Canvas и ассоциированный с мидлетом;
2. создать объект класса Canvas как член-переменную класса мидлета;
3. установить объект класса Canvas как текущий экран мидлета, для чего вызвать метод setCurrent().
Самый лучший способ понять этот процесс – создать пример программы. Хороший пример простой программы с MIDP-графикой – программа, рисующая олимпийский символ, состоящий из пяти пересекающихся колец.
Чтобы начать работу над графическим мидлетом, вы должны выполнить следующее:
1. создать класс, производный от Canvas и ассоциированный с мидлетом;
2. создать объект класса Canvas как член-переменную класса мидлета;
3. установить объект класса Canvas как текущий экран мидлета, для чего вызвать метод setCurrent().
Самый лучший способ понять этот процесс – создать пример программы. Хороший пример простой программы с MIDP-графикой – программа, рисующая олимпийский символ, состоящий из пяти пересекающихся колец.
Написание программного кода
Давайте начнем с класса OCanvas, который создаст холст для использования в мидлете Olympics. Код класса OCanvas приведен в листинге 4.1.
public class OCanvas extends Canvas {
private Display display;
public OCanvas(Display d) {
super();
display = d;
}
void start() {
display.setCurrent(this);
repaint();
}
public void paint(Graphics g) {
// Clear the display
g.setColor(255, 255, 255); // White
g.fillRect(0, 0, getWidth(), getHeight());
// Draw the first row of circles //Дуги выводятся как идеальные окружности, если задать одинаковые значения высоты и ширины, а также изменение угла от 0° до 360°
g.setColor(0, 0, 255); // Blue
g.drawArc(5, 5, 25, 25, 0, 360);
g.setColor(0, 0, 0); // Black
g.drawArc(35, 5, 25, 25, 0, 360);
g.setColor(255, 0, 0); // Red
g.drawArc(65, 5, 25, 25, 0, 360);
// Draw the second row of circles
g.setColor(255, 255, 0); // Yellow
g.drawArc(20, 20, 25, 25, 0, 360);
g.setColor(0, 255, 0); // Green
g.drawArc(50, 20, 25, 25, 0, 360);
}
}
Этот класс расширяет класс Canvas и устанавливает себя как экран мидлета. Конструктор вызывает конструктор родительского класса Canvas и инициализирует переменную display. Метод start() устанавливает холст текущим экраном мидлета и обновляет изображение. Наиболее важный код содержится в методе paint(), он вызывает функции setColor() и drawArc() и рисует олимпийский символ. Обратите внимание, что все аргументы углов в функциях drawArc() равны 0 0 и 360°, в результате чего будут нарисованы полные эллипсы.
Когда вы определили класс OCanvas, можно объявить член-переменную класса мидлета OlympicsMIDlet:
private OCanvas canvas;
Член-переменная класса должна быть инициализирована конструктором класса:
canvas = new Ocanvas (Display.getDisplay(this));
Это весь код для обработки графики, который необходим в мидлете Olympics. В листинге 4.2 представлен полный код класса OlympicsMIDlet.
import javax.microedition.lcdui.*;
public class OlympicsMIDlet extends MIDlet implements CommandListener {
private OCanvas canvas;
public void startApp() {
if (canvas == null) {
canvas = new OCanvas(Display.getDisplay(this));
Command exitCommand = new Command("Exit", Command.EXIT, 0);
canvas.addCommand(exitCommand);
canvas.setCommandListener(this);
}
// инициализация
canvas.start(); //Метод start() холста запускает мидлет
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) {
if (c.getCommandType() == Command.EXIT) {
destroyApp(true);
notifyDestroyed();
}
}
}
По мере прочтения книги вы поймете, что приведенный код можно рассматривать как шаблон для построения любого игрового мидлета. Большая часть специального игрового кода размещается в классе, наследованном от Canvas, или в других поддерживающих классах.
Листинг 4.1. Класс OCanvas служит настраиваемым холстом для мидлета Olympics
import javax.microedition.lcdui.*;public class OCanvas extends Canvas {
private Display display;
public OCanvas(Display d) {
super();
display = d;
}
void start() {
display.setCurrent(this);
repaint();
}
public void paint(Graphics g) {
// Clear the display
g.setColor(255, 255, 255); // White
g.fillRect(0, 0, getWidth(), getHeight());
// Draw the first row of circles //Дуги выводятся как идеальные окружности, если задать одинаковые значения высоты и ширины, а также изменение угла от 0° до 360°
g.setColor(0, 0, 255); // Blue
g.drawArc(5, 5, 25, 25, 0, 360);
g.setColor(0, 0, 0); // Black
g.drawArc(35, 5, 25, 25, 0, 360);
g.setColor(255, 0, 0); // Red
g.drawArc(65, 5, 25, 25, 0, 360);
// Draw the second row of circles
g.setColor(255, 255, 0); // Yellow
g.drawArc(20, 20, 25, 25, 0, 360);
g.setColor(0, 255, 0); // Green
g.drawArc(50, 20, 25, 25, 0, 360);
}
}
Этот класс расширяет класс Canvas и устанавливает себя как экран мидлета. Конструктор вызывает конструктор родительского класса Canvas и инициализирует переменную display. Метод start() устанавливает холст текущим экраном мидлета и обновляет изображение. Наиболее важный код содержится в методе paint(), он вызывает функции setColor() и drawArc() и рисует олимпийский символ. Обратите внимание, что все аргументы углов в функциях drawArc() равны 0 0 и 360°, в результате чего будут нарисованы полные эллипсы.
Когда вы определили класс OCanvas, можно объявить член-переменную класса мидлета OlympicsMIDlet:
private OCanvas canvas;
Член-переменная класса должна быть инициализирована конструктором класса:
canvas = new Ocanvas (Display.getDisplay(this));
Это весь код для обработки графики, который необходим в мидлете Olympics. В листинге 4.2 представлен полный код класса OlympicsMIDlet.
Листинг 4.2. Код класса OlympicsMIDlet содержится в файле OlympicsMIDlet.java
import javax.microedition.midlet.*;import javax.microedition.lcdui.*;
public class OlympicsMIDlet extends MIDlet implements CommandListener {
private OCanvas canvas;
public void startApp() {
if (canvas == null) {
canvas = new OCanvas(Display.getDisplay(this));
Command exitCommand = new Command("Exit", Command.EXIT, 0);
canvas.addCommand(exitCommand);
canvas.setCommandListener(this);
}
// инициализация
canvas.start(); //Метод start() холста запускает мидлет
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) {
if (c.getCommandType() == Command.EXIT) {
destroyApp(true);
notifyDestroyed();
}
}
}
По мере прочтения книги вы поймете, что приведенный код можно рассматривать как шаблон для построения любого игрового мидлета. Большая часть специального игрового кода размещается в классе, наследованном от Canvas, или в других поддерживающих классах.
Тестирование готового приложения
Чтобы собрать и протестировать мидлет Olympics, скопируйте папку Olympics в папку apps, расположенную в папке установки J2ME Wireless Toolkit. Чтобы собрать мидлет, щелкните по кнопке Build (Собрать), а чтобы запустить эмулятор J2ME, щелкните по кнопке Run (Запустить). На рис. 4.5 показан мидлет The Olympics MIDlet.
Рис. 4.5. Мидлет The Olympics MIDlet демонстрирует построение основных геометрических фигур
Рис. 4.5. Мидлет The Olympics MIDlet демонстрирует построение основных геометрических фигур
Создание слайд-шоу
Хотя мидлет Olympics очень интересен и полезен для знакомства с программированием графики мидлета, вы, вероятно, хотите большего. Например, увидеть, как выводится текст и графика в контексте мидлета. В этой части книги вы разработаете слайд-шоу, что поможет вам попрактиковаться в выводе изображений и текста. Очевидно, слайд-шоу – не игра, однако этот мидлет поможет вам изучить основные приемы создания графики игр, например, комбинирование изображений и текста, а также обработку пользовательского ввода.
Написание программного кода
Мидлет Slideshow загружает несколько изображений и текст, после чего выводится на экран. Пользователь может пролистывать страницы слайд-шоу, используя клавиши со стрелками. Поскольку слайд-шоу относится к графической части мидлета, большая часть кода сосредоточена в классе SSCanvas, который хранит изображения и подписи под ними:
private Display display;
private Image[] slides;
private String[] captions = { "Love Circle Bowl", "Double Wide Spine",
"Flume Zoom Over-vert", "Kulp De Sac Bowl",
"Louie's Ledge" };
private int curSlide = 0;
Переменная sliders – это массив объектов Image, она инициализируется в конструкторе класса SSCanvas. Ниже приведен код этого конструктора:
public SSCanvas(Display d) {
super();
display = d;
// загрузить изображения слайд-шоу
try {
slides = new Image[5];
slides[0] = Image.createImage("/LoveCircle.jpg");
slides[1] = Image.createImage("/DoubleWide.jpg");
slides[2] = Image.createImage("/FlumeZoom.jpg");
slides[3] = Image.createImage("/KulpDeSac.jpg");
slides[4] = Image.createImage("/LouiesLedge.jpg");
}
catch (IOException e) {
System.err.println("Failed loading images!");
}
}
Этот код понять очень просто, он создает массив объектов Image и инициализирует каждый элемент, загружая с помощью метода Image.createImage() соответствующее изображение. Важно отметить, что имя каждого файла изображения начинается с символа / (Косой слеш), обозначающего, что файл расположен в корневой директории мидлета. Это важно, так как эти изображения упакованы в JAR-архив вместе с классом мидлета, а следовательно, они должны быть доступны для чтения.
public void paint(Graphics g) {
// очистить экран
g.setColor(255, 255, 255); // белый
g.fillRect(0, 0, getWidth(), getHeight());
// вывести текущее изображение
g.drawImage(slides[curSlide], getWidth() / 2, getHeight() / 2, //Текущее изображение выводится в центре экрана
Graphics.HCENTER | Graphics.VCENTER);
private Display display;
private Image[] slides;
private String[] captions = { "Love Circle Bowl", "Double Wide Spine",
"Flume Zoom Over-vert", "Kulp De Sac Bowl",
"Louie's Ledge" };
private int curSlide = 0;
Переменная sliders – это массив объектов Image, она инициализируется в конструкторе класса SSCanvas. Ниже приведен код этого конструктора:
public SSCanvas(Display d) {
super();
display = d;
// загрузить изображения слайд-шоу
try {
slides = new Image[5];
slides[0] = Image.createImage("/LoveCircle.jpg");
slides[1] = Image.createImage("/DoubleWide.jpg");
slides[2] = Image.createImage("/FlumeZoom.jpg");
slides[3] = Image.createImage("/KulpDeSac.jpg");
slides[4] = Image.createImage("/LouiesLedge.jpg");
}
catch (IOException e) {
System.err.println("Failed loading images!");
}
}
Этот код понять очень просто, он создает массив объектов Image и инициализирует каждый элемент, загружая с помощью метода Image.createImage() соответствующее изображение. Важно отметить, что имя каждого файла изображения начинается с символа / (Косой слеш), обозначающего, что файл расположен в корневой директории мидлета. Это важно, так как эти изображения упакованы в JAR-архив вместе с классом мидлета, а следовательно, они должны быть доступны для чтения.
В копилку ИгрокаОсновные действия выполняются в методе paint() класса SSCanvas, который выводит текущее изображение слайд-шоу и подпись на экран. Ниже приведен код метода paint():
Если вам интересно, что за изображения помещены в слайд-шоу, то это фотографии общественного скейт-парка, строящегося в моем городе, Нэшвилле, штат Теннеси. Я помогал с оформлением документов на строительство парка нашему сообществу скейтбордистов.
public void paint(Graphics g) {
// очистить экран
g.setColor(255, 255, 255); // белый
g.fillRect(0, 0, getWidth(), getHeight());
// вывести текущее изображение
g.drawImage(slides[curSlide], getWidth() / 2, getHeight() / 2, //Текущее изображение выводится в центре экрана
Graphics.HCENTER | Graphics.VCENTER);