Программирование мобильных телефонов

         

Создание фонового изображения




С помощью класса TiledLayer можно создавать любое количество уровней, накладывая их друг на друга, а с помощью менеджера уровней, представленного классом LayerManager, отслеживать все имеющиеся уровни. В качестве примера будет создан фон на основе элементов разметки игрового поля. Фоновое изображение загружается из файла fon.png. Само изображение выполнено в виде шести ячеек размером 15x15 пикселей.

В листинге 8.1 находится код примера создающего фоновое изображение. Ознакомьтесь с листингом, а потом мы перейдем к анализу этого примера.



Рис. 8.2. Константы трансформации


/ * * Листинг 8.1 класс MainGame */ import javax.microedition.lcdui.* ; import javax.microedition.midlet.*; public class MainGame extends MIDlet implements CommandListener { //команда выхода private Command exitMidlet = new Command!"Выход", Command.EXIT, 0) ; // объект класса MyGameCanvas private MyGameCanvas mr; public void startApp.{} { // обрабатываем исключительную ситуацию try{ // инициализируем объект класса MyGameCanvas; mr = new MyGameCanvas() ; // запускаем поток mr.start(); // добавляем команду выхода mr.addCommand(exitMidlet); mr.setCommandListener(this) ; // отражаем текущий дисплей Display .getDisplay (this) . setCurrent (mr-) ; } catch (Java . io. ID-Exception zxz) {} ; } public void pauseApp() {} public void destroyApp(boolean unconditional) { // останавливаем поток if(mr != null) mr.stop'O; } public void coramandAction(Command c, Displayable d) {  if (c == exitMidlet) { destroyApp(false) ; notifyDestroyed() ; } }  } / * * Файл MyGameCanvas.Java класс MyGameCanvas */ import Java.io.IOException;  import javax.microedition.Icdui.*; import javax.microedition Nlcdui.game.* ; public class MyGameCanvas extends GameCanvas implements Runnable- { // создаем объект класса TiledLayer private TiledLayer fonPole; // создаем объект класса LayerManager private LayerManager im; // логическая переменная для выхода из цикла boolean z; public MyGameCanvas(), throws IOException { // обращаемся к конструктору суперклассаNCanvas super(true); // инициализируем fonPole fonPole = Fon () ; // создаем менеджер уровней 1m = new LayerManager(); // добавляем объект fonPole к уровню im.append (fonPole); } public void start() { z = true; // создаем и запускаем поток Thread t = new Thread(this); t.start(); } //* метод, создающий объект класса TiledLayer и загружающий фоновое изображение */  public TiledLayer Fon()throws IOException { // загрузка изображения из файла ресурса Image im = Image.createlmage("/fon.png"); // создаем объект класса TiledLayer fonPole = new TiledLayer(/*столбцы*/10,/*строки*/10, /*изображение*/lm,/*ширина*/15,/*высота*/15); // разметка игрового поля int[] pole = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 5, 5, 5, 1, 1, 5, 1, 1, 1, 1, 1, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 2, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3  }; // цикл, считывающий разметку поля for(int i = 0; i < pole.length; i + + ) { /* присваиваем каждому элементу игрового поля определенную ячейку изображения  im*/ fonPole.setCell(i % 10, i / 10, pole[i]); } return fonPole; } public void stop(){ z = false;  } public void run() { // получаем графический контекст Graphics g = getGraphics();  while (z) { // рисуем графические элементы init(g) ; // останавливаем цикл на 20 миллисекунд try { Thread.sleep(20);  } catch (Java.lang.InterruptedExceptlori zx.z) {};  }  } private void init(Graphics g) { // белый цвет фона для перерисовки экрана g.setColor(0xffffff); // размер перерисовки экрана g.fillRect(0, 0, getWidth(), getHeight()); // рисуем уровень с левого верхнего угла дисплея 1m.paint(g, 0, 0) ; // двойная буферизация flushGraphics(); } }

Листинг 8.1 состоит из двух классов MainCanvas и MyGameCanvas, находящихся в файлах MainCanvas.java и MyGameCanvas.java. Анализ листинга начнем с класса MyGameCanvas. В первых строках кода этого класса объявляются два объекта классов TiledLayer и LayerManager, атак же логическая переменная z.

private TiledLayer fonPole; private LayerManager lm, boolean z;

Объект fonPole класса TiledLayer будет отвечать за фоновое изображение. Объект im класса LayerManager является менеджером уровней. Логическая переменная z необходима для прерывания цикла в методе run () и для окончания системного потока, в котором происходит работа всего игрового цикла.



В конструкторе MyGameCanvas происходит инициализация объекта fonPole класса TiledLayer и объект im класса LayerManager. Инициализированный объект fonPole добавляется менеджером уровней к текущему уровню для представления на экране телефона. Обратите внимание, объект fonPole инициализируется с помощью метода Fon ().

Image im = Image.createlmage("/fon.png"); fonPole= new TiledLayer(/*столб*/10,/*строки*/10,im, /*ширина*/15,/*высота*/15);

В этих двух строках происходит загрузка исходного изображения из файла ресурса и создание объекта fonPole с помощью конструктора класса TiledLayer.

Вся разметка игрового поля выполнена в виде десяти строк и десяти столбцов. Первые два параметра конструктора класса TiledLayer как раз и отвечают за количество столбцов и строк. Третий параметр конструктора - это исходное изображение, выполненное в виде шести ячеек, каждая размером 15x15 пикселей. Два последних параметра конструктора класса TiledLayer определяют ширину и высоту ячейки. При создании объекта класса TiledLayer необходимо быть внимательным и указывать реальные размеры одной ячейки. Если размер одной ячейки будет, предположим 20x20 пикселей, а вы обозначите как 15x15 пикселей, то в итоге ячейки изображения загружены не будут.

Дальше в методе Fon () происходит разметка игрового поля выполненного в виде десяти столбцов и десяти строк.

int[] pole = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 5, 5, 5, 1, 1, 5, 1, 1, 1, 1, 1, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 2, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3, };

Все строки и столбцы состоят из элементов. Отсчет ячеек происходит от единицы и выше. Присвоение номера ячейки исходного изображения одному из элементов и организует разметку игрового поля, которое в последствии будет рисоваться на экране. Единственное О5чем нельзя забывать - это о размере дисплеев реальных телефонов. Если вы имеете десять столбцов и размер каждой ячейки 15 пикселей по ширине, то в итоге ваше игровое поле в ширину будет 10x15 = - 150 пикселей. Не каждый телефон может похвастаться таким разрешением, поэтому при создании игрового поля нужно учитывать эти нюансы. Вслед за разметкой игрового поля в методе Fon () происходит считывание всех элементов с помощью цикла for.

forfint i = 0; i < pole.length; i++) { fonPole.setCell(i % 10, i / 10, pole[i]); }

Присвоение номера ячейки определенному элементу происходит при помощи метода setCell (). В этом методе первый параметр-номер столбца, второй - номер строки и последний - номер ячейки изображения. Здесь главное не запутаться, потому что номера столбцов и строк начинаются с нуля из-за того, что это обычный массив данных, а все массивы, как вы знаете, ведут свой отсчет с нуля, тогда как ячейка исходного изображения начинается с единицы. Сразу возникает вопрос, а почему не произвести отсчет тоже с нуля, чтобы не было путаницы? Дело в том, что отсчет и производится с нуля, но число ноль - это своего рода зарезервированное значение для ячеек изображения. Нулевое значение может использоваться, но оно не. загружает ничего, поэтому отсчет ячеек ведется с единицы. С методом Fon () мы разобрались, перейдем к методу init ().

g.setColor(0xffffff); g.fillRect(0, 0, getWidth0, getHeight());

В этих строках кода происходит постоянная перерисовка фона экрана. Эти действия вы производили в главе 7, когда разбирали механизм отсечения.

С помощью метода paint () рисуется уровень. Начало точки вывода уровня задано точкой 0,0, что соответствует началу, системы координат.

И последний метод flushGraphics () осуществляет двойную буферизацию, копируя графические элементы из внеэкранного буфера на экран.

В методе run () происходит остановка игрового цикла. Перед тем как цикл создается с помощью оператора while, методом getGraphics () происходит получение графического контекста, что и является одним из достоинств механизма игрового цикла в профиле MIDP 2.0.

В файле MainGame.java создается основной класс мидлета MainGame. В методе startApp() производится создание объекта рассмотренного класса MyGameCanvas, добавляется команда выхода, запускается системный поток и отражается текущий дисплей. В методе destroyApp () происходит остановка потока методом stop () класса MyGameCanvas.



Содержание раздела