ufoSprite.move(ufoXSpeed, ufoYSpeed); checkBounds(ufoSprite);
Известный метод move() перемещает спрайт, а метод checkBounds() проверяет, не вышел ли НЛО за границы экрана. Проверка не изменилась, но ее код оформлен отдельным методом. Это очень важно, поскольку вам необходимо выполнить аналогичную проверку и для астероидов. Для этого нецелесообразно копировать код, если можно использовать существующий. Обновление спрайтов астероидов производится в цикле, который выполняет несколько функций. Ниже приведено начало цикла:
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)) {
// воспроизвести предупреждающий звук
AlertType.ERROR.playSound(display);
// вернуть спрайт в исходное положение и обнулить скорости
ufoSprite.setPosition((getWidth() – ufoSprite.getWidth()) / 2, //Спрайт выводится в центре игрового экрана, его скорость равна 0
(getHeight() – ufoSprite.getHeight()) / 2);
ufoXSpeed = ufoYSpeed = 0;
for (int j = 0; j < 3; j++)
roidSprite[j].setPosition(0, 0);
// нет необходимости обновлять спрайты астероидов
break;
}
}
Если столкновение произошло, то воспроизводится стандартный звук возникновения ошибки (он зависит от конкретной модели телефона), для чего используется объект AlertType. В главе 8 вы узнаете, как использовать разнообразные звуки в играх. В этой программе столкновение возвратит НЛО в исходное положение и обнулит его скорость. Если бы вы создавали полноценную игру, то в этом месте вы бы уменьшили число жизней и проверили, не закончена ли игра. Но в этой программе вы просто изменяете положение спрайтов, и анимация продолжается. По сравнению с мидлетом UFO в методе draw() есть только одно незначительное изменение – код, рисующий астероиды:
for (int i = 0; i < 3; i++) roidSprite[i].paint(g);
На этом весь новый код мидлета 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) //Индекс астероида определяет направление анимации
Читать дальше
Конец ознакомительного отрывка
Купить книгу