На этом весь новый код мидлета UFO 2 завершен. В листинге 6.1 приведен полный код нового класса UFOCanvas. Листинг 6.1. Класс UFOCanvas, выполняющий роль холста для мидлета UFO 2
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import java.util.*;
import java.io.*;
public class UFOCanvas extends GameCanvas implements Runnable {
private Display display;
private boolean sleeping;
private long frameDelay;
private Random rand;
private Sprite ufoSprite;
private int ufoXSpeed, ufoYSpeed;
private Sprite[] roidSprite = new Sprite[3]; //В игре UFO 2 есть 3 спрайта астероида
public UFOCanvas(Display d) {
super(true);
display = d;
// установить частоту кадров (30 fps)
frameDelay = 33;
}
public void start {
// установить холст как текущий экран
display.setCurrent(this);
// инициализировать генератор случайных чисел
rand = new Random;
// инициализировать спрайты НЛО и астероидов
ufoXSpeed = ufoYSpeed = 0;
try {
ufoSprite = new Sprite(Image.createImage("/Saucer.png"));
ufoSprite.setPosition((getWidth – ufoSprite.getWidth) / 2,
(getHeight – ufoSprite.getHeight) / 2);
Image img = Image.createImage("/Roid.png");
roidSprite[0] = new Sprite(img, 42, 35);
roidSprite[1] = new Sprite(img, 42, 35);
roidSprite[2] = new Sprite(img, 42, 35);
}
catch (IOException e) {
System.err.println("Failed loading images!");
}
// запустить поток анимации
sleeping = false;
Thread t = new Thread(this);
t.start;
}
public void stop {
// остановить анимацию
sleeping = true;
}
public void run {
Graphics g = getGraphics;
// игровой цикл
while (!sleeping) {
update;
draw(g);
try {
Thread.sleep(frameDelay);
}
catch (InterruptedException ie) {}
}
}
private void update {
// обработка пользовательского ввода, изменение скорости НЛО
int keyState = getKeyStates;
if ((keyState & LEFT_PRESSED) != 0) //Клавиши со стрелками изменяют скорость НЛО по всем четырем направлениям
ufoXSpeed–;
else if ((keyState & RIGHT_PRESSED) != 0)
ufoXSpeed++;
if ((keyState & UP_PRESSED) != 0)
ufoYSpeed–;
else if ((keyState & DOWN_PRESSED) != 0)
ufoYSpeed++;
ufoXSpeed = Math.min(Math.max(ufoXSpeed, -8), 8);
ufoYSpeed = Math.min(Math.max(ufoYSpeed, -8), 8);
// переместить спрайт НЛО
ufoSprite.move(ufoXSpeed, ufoYSpeed);
checkBounds(ufoSprite);
// обновить спрайты астероидов
for (int i = 0; i < 3; i++) {
// переместить спрайты астероидов
roidSprite[i].move(i + 1, 1 – i);
checkBounds(roidSprite[i]); //Эта строка кода отвечает за отрисовку астероида при достижении границ экрана
// изменить отображаемый фрейм астероида
if (i == 1) //Индекс астероида определяет направление анимации
roidSprite[i].prevFrame;
else
roidSprite[i].nextFrame;
// проверить столкновение НЛО с астероидом
if (ufoSprite.collidesWith(roidSprite[i], true)) { //Поскольку второй параметр метода collidesWith равен true, то выполняется пиксельное детектирование столкновения
// воспроизвести предупреждающий звук
AlertType.ERROR.playSound(display);
// восстановить исходные положения и скорости объектов
ufoSprite.setPosition((getWidth – ufoSprite.getWidth) / 2,
(getHeight – ufoSprite.getHeight) / 2);
ufoXSpeed = ufoYSpeed = 0;
for (int j = 0; j < 3; j++)
roidSprite[j].setPosition(0, 0);
// нет необходимости обновлять спрайты астероидов
break;
}
}
}
private void draw(Graphics g) {
// Clear the display
g.setColor(0x000000);
g.fillRect(0, 0, getWidth, getHeight);
// нарисовать спрайт НЛО
ufoSprite.paint(g);
// нарисовать спрайты астероидов
for (int i = 0; i < 3; i++)
roidSprite[i].paint(g);
// отобразить содержимое буфера на экране
flushGraphics;
}
private void checkBounds(Sprite sprite) {
// проверить положение спрайта
if (sprite.getX < -sprite.getWidth)
sprite.setPosition(getWidth, sprite.getY);
else if (sprite.getX > getWidth)
sprite.setPosition(-sprite.getWidth, sprite.getY);
if (sprite.getY < -sprite.getHeight)
sprite.setPosition(sprite.getX, getHeight);
else if (sprite.getY > getHeight)
sprite.setPosition(sprite.getX, -sprite.getHeight);
}
}