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

0

Напишем небольшую тестовую активность, демонстрирующую все вышеперечисленные методы. Я хочу, чтобы вы сначала проанализировали код в листинге 4.13. Представьте, что мы используем экран с разрешением 480 х 800 в портретном режиме, на котором будут рисоваться разные фигуры. При программировании графики очень важно представлять себе результат выполнения команд. Это требует некоторой практики, но оно того стоит.

Листинг 4.13. ShapeTest.Java; Безумное рисование фигур package com.badlogi с.androi dgames;

Вы уже нарисовали в воображении картинку? Тогда давайте быстро проанализируем метод RenderView.onDraw. Все остальное не изменилось с прошлого примера.

Начинаем с заполнения экрана белым цветом. Далее рисуем линию от начала до правого нижнего пиксела экрана. Мы используем Paint, чей цвет установлен в красный, поэтому линия будет такого же цвета.

Затем немного изменяем Paint, устанавливая его стиль как Sty 1 е. STROKE, цвет – зеленый и значение альфа – 255. В центре экрана рисуется окружность с радиусом 40 пикселов (использующая Paint, который мы только что изменили). Из-за установленного стиля окружность будет незаполненной.

Последний блок начинается с еще одной модификации Pai nt. Мы устанавливаем его стиль Sty 1 е. FILL, а цвет – синий. Обратите внимание – я задал альфа равной 0x77 в этот раз, что равно 119 в десятичном исчислении. Это означает, что фигура, которую мы рисуем, будет примерно на 50 % прозрачной.

Рисунок 4.13 показывает итог работы тестовой активности в портретном режиме в разрешениях 480 х 800 и 320 х 480.

Боже, что произошло? То, что случается при рисовании с абсолютными координатами и размерами на разных разрешениях. Единственный элемент, оставшийся неизменным на обеих картинках, – красная линия через весь экран (она реализована способом, не зависящим от разрешения).

Прямоугольнику установлено положение (100; 100). В зависимости от разрешения дисплея расстояния до центра экрана будет разным. Кроме того, размер прямоугольника задан равным 100 х 100 пикселов. Чем больше дисплей, тем меньше фигура будет занимать места относительно его площади.

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

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

Пока же помните, что означают разрешение экрана и его физический размер.

Рис. 4.13. Вывод ShapeTest на экране 480×800 (слева) и 320 х 480 (справа) (черная рамка добавлена позднее)

ПРИМЕЧАНИЕ

Классы Canvas и Paint предлагают гораздо больше, чем мы только что обсудили. На самом деле все стандартные View в Android используют для прорисовки этот API, так что можете представить, сколько там всего. Как всегда, читайте Android Developers для более подробной информации.

Использование битовых изображений

Хотя создание игр, состоящих только из базовых фигур, имеет право на жизнь, это не то, чего всем хочется. Нам нужен гениальный художник для создания спрайтов и фоновых изображений, которые потом сможем загружать из PNG- или JPEG файлов. В Android все это делается легко.

Загрузка и проверка изображений. Класс Bi tmap станет нашим лучшим другом. Мы загружаем битовое изображение из файла с помощью элемента BitmapFactory. Поскольку мы храним изображения в виде ресурсов, посмотрим, как мы можем загружать их из каталога assets/:

Класс Bitmap содержит несколько полезных для нас методов. Для начала мы хотим узнать его ширину и высоту в пикселах:

Затем нам полезно будет получить цветовую схему, в которой сохранен  Bitmap:

Bitmap.Config – перечисление со следующими значениями:

Вы должны помнить, что означают эти варианты.

Интересно, что в перечислении отсутствует формат RGB888. Формат PNG, в свою очередь, поддерживает только схемы ARGB8888, RGB888 и палитры. В какой цифровой формат будет загружен PNG типа RGB888?

Ответ – BitmapConf i g. RGB 565. Это происходит автоматически для любого RGB888 PNG-файла, загружаемого через Bi tmapFactory. Причина – настоящий фреймбуфер большинства устройств Android работает с этим цветовым форматом. Загрузка изображения с большей глубиной может быть пустой тратой памяти – все равно эти пикселы будут преобразованы в RGB565 при финальном рендеринге.

Тогда зачем присутствует Conf i g. ARGB 8888? Дело в том, что создание изображения может быть осуществлено процессором до его прорисовки во фреймбуфере. При использовании альфа-компоненты у нас также будет чуть большая глубина, чем при использовании Conf i g. ARGB 4444, что может быть необходимо для некоторых случаев высококачественной обработки изображения.

ARGB8888 PNG-файл может быть загружен в Bitmap с конфигурацией Config. ARGB 8888. Оставшиеся два формата используются редко. Однако мы можем указать Bi tmapFactory попытаться загрузить изображение в определенном цветовом формате, даже если его исходный формат отличается от него.

Мы используем перегруженный метод Bi tmapFactory .decodeStreamC для передачи указания в виде экземпляра ВitmapFactory .Options декодировщику изображения. Мы можем определить желаемый цветовой формат экземпляра Bitmap через Bi tmapFactory. Opti ons. i nPref erredConfig, как показано ранее. В этом гипотетическом примере формат файла bob. png будет ARGB8888 PNG, и мы хотим заставить

BitmapFactory загрузить его и конвертировать в ARGB4444. Однако наше указание может быть проигнорировано.

Вы также можете создать пустой Bitmap следующим статическим методом:

Вполне вероятно, что вы захотите вручную поработать с изображением, что называется, на лету. Класс Canvas работает с растровыми изображениями тоже:

Теперь вы можете изменять ваши изображения тем же способом, которым вы модифицировали содержимое View.

Уничтожение Bitmap. BitmapFactory может помочь нам уменьшить расход памяти при загрузке изображения. Как говорилось растры занимают много места в памяти. Уменьшение количества битов на пиксел за счет использования другого цветового формата помогает, но при загрузке одного изображения за другим мы в конечном итоге займем всю память. Поэтому мы должны уничтожать экземпляры Bitmap после потери необходимости в них с помощью этого метода:

Рисование Bitmap. После загрузки наших изображений мы можем рисовать их с помощью Canvas. Самый простой способ это сделать выглядит так:

Первый аргумент должен быть очевиден. Аргументы topLeftX и topLeftY определяют координаты размещения на экране левого верхнего угла изображения. Последний аргумент может принимать значение null. Мы могли бы определить дополнительные параметры рисования в классе Paint, но необходимости в этом нет.

Существует другая версия этого метода:

Это очень классный метод. Он позволяет нам определить через второй параметр часть изображения Bitmap, которую необходимо рисовать. Класс Rect хранит координаты верхнего левого и нижнего правого углов прямоугольника. Когда мы определяем часть изображения через переменную src, то делаем это в системе координат объекта Bitmap. Если мы укажем значение null, будет использован весь объект Bitmap. Третий параметр задает часть объекта Bitmap, в который должна происходить прорисовка, также в виде экземпляра Rect. Однако в данном случае координаты заданы относительно целевого объекта Canvas (либо View или другого Bitmap). Большой сюрприз состоит в том, что два этих прямоугольника не обязательно должны иметь одинаковые размеры. Если мы определим целевой прямоугольник с меньшим размером, чем исходный, Canvas автоматически масштабирует его (то же самое относится к случаю, когда целевой прямоугольник больше исходного). Последний параметр также обычно устанавливается в null. Хочу только заметить, что операция масштабирования – весьма дорогое с точки зрения ресурсов удовольствие. Использовать его стоит только при крайней необходимости.

Вас может заинтересовать еще один вопрос. Если у нас есть экземпляры Bitmap с различными цветовыми форматами, необходимо ли нам конвертировать их в какой-нибудь стандартный формат перед прорисовкой в Canvas? Нет, Canvas сделает это автоматически. Конечно, использовать цветовые форматы, близкие к родным форматам фреймбуфера, будет немного быстрее. Однако обычно мы просто игнорируем этот шаг.

Смешивание также по умолчанию включено, так что если наши изображения содержат для своих пикселов альфа-компоненты, они будут обрабатываться.

Все вместе

Со всей полученной информацией мы теперь можем загружать и прорисовывать несколько Бобов. Листинг 4.14 содержит исходный код активности BitmapTest, который я написал для демонстрации.

Листинг 4.14. Активность BitmapTest package com.bad.ogi с.androi dgames;

Метод onCreateO изучен нами вдоль и поперек, поэтому сосредоточимся на нашей реализации View. Этот класс содержит два члена типа Bitmap: один из них хранит картинку Боба  в формате RGB565, другой – Боба же в формате ARGB4444. Кроме того, у нас есть член типа Rect, в котором хранятся параметры целевого прямоугольника для рендеринга.

В конструкторе класса RenderView мы для начала загружаем Боба в объект ЬоЬ565. Обратите внимание – изображение загружается из RGB888 PNG-файла, Bi tmapFactory автоматически конвертирует его в формат RGB565. Чтобы в этом убедиться, мы также выводим содержимое Bitmap.Config в LogCat. RGB888-Bepcnn Боба имеет прозрачный белый фон, поэтому нет необходимости производить смешивание.

Далее мы загружаем Боба из ARGB8888 PNG-файла, находящегося в каталоге assets/. Для экономии памяти мы также даем Bi tmapFactory команду преобразовать это изображение в формат ARGB4444. Напоминаю – factory может не подчиниться этой команде (по неясным причинам). Чтобы увидеть, прошла ли операция, мы также выводим содержимое Bitmap. Config в LogCat.

Метод onDraw очень короткий. Все, что мы в нем делаем, – рисуем содержимое ЬоЬ565, растянутое до 250 х 250 пикселов (оригинальный размер – 160 х 183 пиксела), а поверх него рисуем ЬоЬ4444, не масштабируя, но смешивая (это делается автоматически объектом Canvas). Рисунок 4.14 демонстрирует нам Боба во всей красе.

Рис. 4.14. Два Боба: один поверх другого (при разрешении 480 х 800)

LogCat сообщает, что ЬоЬ565 действительно имеет формат Conf i g. RGB 565, a bob4444 конвертирован в Config.ARGB 444 – BitmapFactory не сплоховал.

Вот несколько моментов, на которые вы должны обратить внимание.

Используйте минимально допустимый формат цвета для сохранения памяти, но помните, что ценой этой экономии может стать худшее качество визуализации и некоторое уменьшение скорости перерисовки.

Без крайней необходимости не прибегайте к масштабированию изображений. Если вам известен необходимый размер картинки, измените исходное изображение заранее.

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

Использование LogCat для вывода текста довольно утомительно. Изучим возможности прорисовки текста с помощью Canvas.

ПРИМЕЧАНИЕ

Как и в случае с другими классами, в Bitmap содержится намного больше, чем я смог описать на этих нескольких страницах. Я дал вам необходимый для написания Мистера Нома минимум. Если хотите большего, добро пожаловать на Android Developers.

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

По теме:

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