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

         

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



С помощью класса 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.

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