Шрифт:
Последний элемент головоломки с названием UFOCanvas – это метод draw, который вызывается для рисования анимации:
private void draw(Graphics g) {
// очистить экран
g.setColor(0x000000);
g.fillRect(0, 0, getWidth, getHeight);
// нарисовать спрайт UFO
ufoSprite.paint(g);
// сменить буфер
flushGraphics;
}В этом методе экран сначала очищается и заполняется черным цветом, а затем вызывается метод paint, который и рисует спрайт. В завершении созданная графика выводится на экран, для чего вызывается метод flushGraphics. В этом и состоит вся прелесть двухбуферной анимации: вы создаете графику, а затем выводите ее на экран. Без этого игры были бы не столь привлекательными, поверьте.
Теперь, чтобы объединить все вышесказанное, посмотрите листинг 5.1.
Листинг 5.1. Класс UFOCanvas – это класс холста мидлета UFOimport 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;
public UFOCanvas(Display d) {
super(true);
display = d;
// установить частоту кадров 30 кадров/с
frameDelay = 33;
}
public void start {
// установить холст как текущий экран
display.setCurrent(this);
// инициализация генератора случайных чисел
rand = new Random;
// инициализация спрайта НЛО
ufoXSpeed = ufoYSpeed = 3;
try {
ufoSprite = new Sprite(Image.createImage("/Saucer.png"));
ufoSprite.setPosition(0, 0); //НЛО стартует в верхнем левом углу экрана
}
catch (IOException e) {
System.err.println("Failed loading image!");
}
// запуск потока анимации
sleeping = false;
Thread t = new Thread(this);
t.start;
}
public void stop {
// Stop the animation
sleeping = true;
}
public void run {
Graphics g = getGraphics;
// The main game loop
while (!sleeping) {
update;
draw(g);
try {
Thread.sleep(frameDelay);
}
catch (InterruptedException ie) {}
}
}
private void update {
// Randomly alter the UFO\'s speed
if (rand.nextInt % 5 == 0) { //Изменить случайным образом компоненты скорости по осям Х и Y в интервале от -8 до 8
ufoXSpeed = Math.min(Math.max(ufoXSpeed + rand.nextInt % 2, -8), 8);
ufoYSpeed = Math.min(Math.max(ufoYSpeed + rand.nextInt % 2, -8), 8);
}
// Move the sprite
ufoSprite.move(ufoXSpeed, ufoYSpeed);
// Wrap the UFO around the screen if necessary
if (ufoSprite.getX < -ufoSprite.getWidth)
ufoSprite.setPosition(getWidth, ufoSprite.getY);
else if (ufoSprite.getX > getWidth)
ufoSprite.setPosition(-ufoSprite.getWidth, ufoSprite.getY);
if (ufoSprite.getY < -ufoSprite.getHeight)
ufoSprite.setPosition(ufoSprite.getX, getHeight);
else if (ufoSprite.getY > getHeight)
ufoSprite.setPosition(ufoSprite.getX, -ufoSprite.getHeight);
}
private void draw(Graphics g) {
// Clear the display
g.setColor(0x000000);
g.fillRect(0, 0, getWidth, getHeight);
// Draw the UFO sprite //Спрайт очень просто вывести на экран, используя метод paint
ufoSprite.paint(g);
// Flush the offscreen graphics buffer
flushGraphics;
}
}Когда код UFOCanvas полностью разработан, можно перейти к встраиванию этого класса в мидлет. В листинге 5.2 приведен код класса UFOMIDlet. Листинг 5.2. Код класса UFOMIDlet, хранящийся в файле UFOMIDlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class UFOMIDlet extends MIDlet implements CommandListener {
private UFOCanvas canvas;
public void startApp {
if (canvas == null) {
canvas = new UFOCanvas(Display.getDisplay(this)); //Настраиваемый холст – это то, что отличает класс мидлета от созданных ранее примеров
Command exitCommand = new Command("Exit", Command.EXIT, 0);
canvas.addCommand(exitCommand);
canvas.setCommandListener(this);
}
// Start up the canvas
canvas.start;
}
public void pauseApp {}
public void destroyApp(boolean unconditional) {
canvas.stop;
}
public void commandAction(Command c, Displayable s) {
if (c.getCommandType == Command.EXIT) {
destroyApp(true);
notifyDestroyed;
}
}
}Как видно из приведенного кода, класс UFOMIDlet состоит из стандартного кода мидлета, который вы видели ранее. Класс мидлета отвечает за создание холста, запуск и остановку выполнения программы. Вы должны привыкнуть к тому, что большая часть специального игрового кода ваших игр будет реализовываться в классе холста и других обслуживающих классах.
Тестирование программы
Как только мидлет UFO собран, вы можете протестировать его в эмуляторе J2ME. В результате летающая тарелка немедленно начинает перемещаться по экрану (рис. 5.7).
Рис. 5.7. Когда мидлет запускается, по экрану немедленно начинает летать НЛО
Поскольку на картинке сложно отобразить анимацию, то на рис. 5.8 показан летающий объект в другом месте экрана.
Все, чего не хватает в мидлете UFO, – это пара астероидов и возможность управления НЛО. Не беспокойтесь, мы восполним этот пробел в следующей главе.
Резюме
В этой главе вы познакомились с анимацией и ее применением в мобильных играх. Вы узнали, что анимация широко используется при создании фильмов, телевизионных передач и видеоигр. При разработке компьютерных игр применяются два основных типа анимации, и в этой главе рассказывалось, как они работают. Затем вы узнали об основах спрайтовой анимации, поддерживаемой MIDP API. Глава завершилась созданием анимационного мидлета, который демонстрирует основы спрайтовой анимации.
В следующей главе вы примените свои знания в области создания анимации для программирования управляемого объекта.
Еще немного об играх
Рассматривая мидлет UFO как первый пример работы с анимацией, полезно поработать еще с рядом ее свойств. Я имею в виду частоту кадров и скорость НЛО. Ниже приведены шаги, которые дают возможность изменить анимацию:
1. попробуйте увеличить значение переменной frameDelay, например, до 100 (10 кадров/с), а потом уменьшить до 20 (50 кадров/с). Обратите внимание на то, как работает анимация в каждом из случаев, а также – насколько она плавная;
2. измените частоту изменения скорости летающего объекта так, чтобы она изменялась чаще. Например, для этого измените код rand.nextInt % 5 на rand.nextInt % 2;
3. измените границу скорости НЛО так, чтобы он мог двигаться быстрее. Для этого необходимо изменить вызовы методов min и max и установить большую границу.
Приведенные шаги могут значительно изменить скорость и производительность анимации, особенно первый шаг. Так что не пожалейте времени и поэкспериментируйте с различными настройками, посмотрите, как они влияют на анимацию.Глава 6 Обработка ввода пользователя
Архив Аркад
Выпущенная в 1980 году компанией Stern игра Berzerk – простой шутер в лабиринте, в ней вы управляете героем-гуманоидом, проводите его через комнаты и сражаетесь с роботами. Berzerk – это одна из первых игр, в которой в конце каждого уровня необходимо было сражаться с «главным монстром». В этой игре «главный монстр» – Злой Отто (Evil Otto), который заставляет героя войти в определенную комнату. Игра Berzerk известна тем, что роботы в ней могут совершать ошибки, например, случайно убить друг друга. Также эта игра известна гибелью игроков: в 1981 году мужчина скончался от сердечного приступа, случившегося после игры; в 1982 году еще один человек также скончался от сердечного приступа, при этом он возглавил список лучших результатов. Играйте в Berzerk на свой страх и риск!
Неважно, сколько времени и сил вы потратите на создание сюжета игры и графики, если в итоге игрой нельзя будет управлять. Чтобы в игру можно было играть, необходимо предоставить пользователю возможность ввода. С точки зрения программирования, это одновременно и сложно, и просто. С одной стороны, в мобильных телефонах управление значительно проще по сравнению с компьютерами, с другой – это ограничивает возможности ввода, делает ввод менее гибким. В этой главе рассказывается, как обрабатывать пользовательский ввод в мидлетах.
Из этой главы вы узнаете:
► почему пользовательский ввод так важен в мобильных играх;
► как эффективно определять и обрабатывать нажатия клавиш;
► как управлять анимационным объектом, используя клавиатуру;
► как определять столкновения спрайтов;
► как создать спрайты, вид которых изменяется с течением времени.
Обработка пользовательского ввода
Пользовательский ввод – это средство взаимодействия пользователя с мобильной игрой. Поскольку пользовательский ввод – это взаимодействие пользователя с приложением, вы должны понять, что создание интуитивно понятного и эффективного интерфейса должно стоять на первом месте в списке ключевых элементов разработки. Несмотря на все достижения современной индустрии компьютерных игр (игры в реальном времени, трехмерная графика и звук), в большинстве случаев вопрос разработки эффективного пользовательского ввода остается без внимания. Простой ввод позволяет пользователю легко и эффективно управлять ходом игры.
В копилку Игрока
Я – игрок старой закалки, помню те времена, когда я платил дань богам игр, желая поиграть во что-то еще. Это было в те времена, когда на домашнем компьютере можно было поиграть только в Pong. В ответ на пожертвованные четвертаки боги разрешали мне поиграть в увлекательные игры. Поскольку аппаратные средства того времени не могли обеспечить высокого уровня графики и звука, разработчики игр были вынуждены компенсировать этот недостаток за счет самой игры. Конечно, они не ставили своей задачей разработку удобного ввода, но в условиях ограниченных аппаратных возможностей, у них просто не было другого выбора.