Из предыдущей статьи мы научились рисовать картинки на сцене и заставлять их двигаться, если Вы не читали как мы это делали то прочитать можно здесь, так как без тех навыков которые я там описываю понять дальнейший урок у Вас не получиться.
Статьи по теме:
И так теперь начнем.
Спрайт является частично прозрачным 2D растровым изображением, которое обычно помещается на фоновое изображение. Спрайты используются в видео-играх. Обычно существует более одного спрайта на экране в одно и то же время. Они могут представлять ИИ (искусственный интеллект) или главного героя которого контролирует игрок.
Спрайт имеет (х, у) координаты положения и (х, у) — скорости. Он может содержать свою собственную анимацию и звуки. Далее вы можете увидеть изображения нашего спрайта персонажа:
Сделать похожий спрайт можно здесь. Сайт сам по себе корейский, но то не беда, Google переведет все :)
Растровое изображение создано, и нам нужно вставить его в наш проект. Создаем класс Sprite.java
Пишем в него вот такую красоту:
Sprite.java
Как вы видите, весь код, о положении и скорости был перенесен (в том числе и границы экрана) в наш новый класс Sprite. Я сделал несколько маленьких изменений в скорости, предыдущие не совсем подходили.
Теперь у нас есть референт нашего спрайта внутри этого класса. В конструкторе мы вызываем ссылки на отслежку растровых тактов в минуту. Отслежка ударов в минуту необходимы, для того что бы получить их ширину для обнаружения границы изображения.
Bitmap используем для рисования на холсте.
Открываем наш GameView.java выделяем старый код, удаляем (потому что я изменил сам класс приходится переделывать и Вам) и пишем следующий код:
GameView.java
Если сделали все правильно то у Вас должно получиться что то похожее на это:
Изображение движется, все хорошо, но нам нужно из 12 изображений сделать одно, которое будет ходить по сцене. Каждая строка представляет собой различные анимации. Проще говоря, мы начнем анимацию со второй строки, следовательно будем идти справа — налево.
Добавляем вот эти переменные в Sprite.java
Обновляем метод update():
Sprite.java
Обновляем метод onDraw():
Sprite.java
И обновляем конструктор:
В конструкторе мы рассчитываем ширину и высоту спрайта. В методе update() фиксируем границы и добавляем текущие изменения значения кадра. В текущем кадре может быть только значения 0, 1 или 2.
В методе OnDraw() мы используем метод canvas.drawBitmap (BMP, SRC, DST, NULL);
SRC является прямоугольником внутри точечного рисунка, который будет описан и по которому будет совершаться переход с одного спрайта на другой. Вот что должно выйти если Вы сделали все правильно:
Статьи по теме:
- Пишем игру под Android: Часть 1 — Рисуем картинки на SurfaceView
- Пишем игру под Android: Часть 2 — Создаем первый спрайт
- Пишем игру под Android: Часть 3 — Спрайтовая анимация, работа с несколькими спрайтами
- Пишем игру под Android: Часть 4 — onTouchEvent и определение столкновений
- Пишем игру под Android: Часть 5 — Создание полноценной 2D игры
- Пишем игру под Android: Часть 6: Добавление звука
- Пишем игру под Android: Часть 7: Меню для игры и окно приветствия
- Пишем игру под Android: Часть 8: Фоновая музыка в игре
И так теперь начнем.
Спрайт является частично прозрачным 2D растровым изображением, которое обычно помещается на фоновое изображение. Спрайты используются в видео-играх. Обычно существует более одного спрайта на экране в одно и то же время. Они могут представлять ИИ (искусственный интеллект) или главного героя которого контролирует игрок.
Спрайт имеет (х, у) координаты положения и (х, у) — скорости. Он может содержать свою собственную анимацию и звуки. Далее вы можете увидеть изображения нашего спрайта персонажа:
Сделать похожий спрайт можно здесь. Сайт сам по себе корейский, но то не беда, Google переведет все :)
Рисуем спрайт на сцене
Растровое изображение создано, и нам нужно вставить его в наш проект. Создаем класс Sprite.java
Пишем в него вот такую красоту:
Sprite.java
import android.graphics.Bitmap;
import android.graphics.Canvas;
public class Sprite {
/**Объект класса GameView*/
private GameView gameView;
/**Картинка*/
private Bitmap bmp;
/**Позиция по Х=0*/
private int x = 5;
/**Скорость по Х=5*/
private int xSpeed = 5;
private int ySpeed = 5;
/**Текущий кадр = 0*/
private int currentFrame = 0;
/**Ширина*/
private int width;
/**Ввыоста*/
private int height;
/**Конструктор*/
public Sprite(GameView gameView, Bitmap bmp)
{
this.gameView=gameView;
this.bmp=bmp;
}
/**Перемещение объекта, его направление*/
private void update()
{
if (x > gameView.getWidth() - bmp.getWidth() - xSpeed) {
xSpeed = -5;
}
if (x + xSpeed< 0) {
xSpeed = 5;
}
x = x + xSpeed;
}
/**Рисуем наши спрайты*/
public void onDraw(Canvas canvas)
{
update();
canvas.drawBitmap(bmp, x , 10, null);
}
}
Как вы видите, весь код, о положении и скорости был перенесен (в том числе и границы экрана) в наш новый класс Sprite. Я сделал несколько маленьких изменений в скорости, предыдущие не совсем подходили.
Теперь у нас есть референт нашего спрайта внутри этого класса. В конструкторе мы вызываем ссылки на отслежку растровых тактов в минуту. Отслежка ударов в минуту необходимы, для того что бы получить их ширину для обнаружения границы изображения.
Bitmap используем для рисования на холсте.
Открываем наш GameView.java выделяем старый код, удаляем (потому что я изменил сам класс приходится переделывать и Вам) и пишем следующий код:
GameView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
/**Загружаем спрайт*/
private Bitmap bmp;
/**Поле рисования*/
private SurfaceHolder holder;
/**объект класса GameView*/
private GameManager gameLoopThread;
/**Объект класса Sprite*/
private Sprite sprite;
/**Конструктор*/
public GameView(Context context)
{
super(context);
gameLoopThread = new GameManager(this);
holder = getHolder();
/*Рисуем все наши объекты и все все все*/
holder.addCallback(new SurfaceHolder.Callback()
{
/*** Уничтожение области рисования */
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry)
{
try
{
gameLoopThread.join();
retry = false;
} catch (InterruptedException e)
{
}
}
}
/** Создание области рисования */
public void surfaceCreated(SurfaceHolder holder)
{
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
/** Изменение области рисования */
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height)
{
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.bad1);
sprite = new Sprite(this,bmp);
}
/**Функция рисующая все спрайты и фон*/
protected void onDraw(Canvas canvas)
{
canvas.drawColor(Color.BLACK);
sprite.onDraw(canvas);
}
}
Если сделали все правильно то у Вас должно получиться что то похожее на это:
Превращаем спрайт в анимацию
Изображение движется, все хорошо, но нам нужно из 12 изображений сделать одно, которое будет ходить по сцене. Каждая строка представляет собой различные анимации. Проще говоря, мы начнем анимацию со второй строки, следовательно будем идти справа — налево.
Добавляем вот эти переменные в Sprite.java
/**Рядков в спрайте = 4*/
private static final int BMP_ROWS = 4;
/**Колонок в спрайте = 3*/
private static final int BMP_COLUMNS = 3;
Обновляем метод update():
Sprite.java
private void update()
{
if (x > gameView.getWidth() - width - xSpeed) {
xSpeed = -5;
}
if (x + xSpeed < 0) {
xSpeed = 5;
}
x = x + xSpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
Обновляем метод onDraw():
Sprite.java
public void onDraw(Canvas canvas)
{
update();
int srcX = currentFrame * width;
int srcY = 1 * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
И обновляем конструктор:
public Sprite(GameView gameView, Bitmap bmp)
{
this.gameView = gameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
}
В конструкторе мы рассчитываем ширину и высоту спрайта. В методе update() фиксируем границы и добавляем текущие изменения значения кадра. В текущем кадре может быть только значения 0, 1 или 2.
В методе OnDraw() мы используем метод canvas.drawBitmap (BMP, SRC, DST, NULL);
SRC является прямоугольником внутри точечного рисунка, который будет описан и по которому будет совершаться переход с одного спрайта на другой. Вот что должно выйти если Вы сделали все правильно:
В первом листинге класса GameView.java
ОтветитьУдалитьстрочки:
private GameView gameLoopThread;
и
gameLoopThread = new GameView(this);
нужно заменить на
private GameManager gameLoopThread;
и
gameLoopThread = new GameManager(this);
соответственно.
Помимо этого, первые четыре переменные, объявленные в классе того же листинга далее переопределяются по второму разу.
Спасибо изменил. Не заметил ошибки.
УдалитьПотеряли переменную y в public void onDraw(Canvas canvas) класса Sprite
ОтветитьУдалитьвсе правильно, спрайт находится на 10 пикселей ниже границы по У
УдалитьRect dst = new Rect(x, y, x + width, y + height);
УдалитьЗдесь используется не объявленная переменная.
y ? если он то объявите его рядом с x
УдалитьДа, у. В следующих уроках он есть ;) Попытался замедлить скорость анимации, но пока что не выходит... Пробовал менять FPS в GameManager.java. Даже пробовал явно задать время сна
УдалитьsleepTime = ticksPS-(System.currentTimeMillis() - startTime);
sleepTime = 1000;
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(1000);
} catch (Exception e) {}
все равно слишком быстро...
Замедлить частоту проигыша кадров? Или скорость движения объекта? Если частоту проигрыша кадров то там нужно по колдовать с методов onDraw(), а если не можешь убрать скорость движения объекта то это в xSpeed нужно заменить 5 на 10 или 15.
УдалитьЯ про частоту проигрыша кадров. Сейчас попробую currentFrame менять реже.
УдалитьТут немного не правильно обозван FPS. У нас поток спит это время, а должна отрисовка спать. Понижая FPS мы замедляем всю игру. При низких ФПС, как я понимаю, мы должны получить в итоге ту же скорость перемещения персонажа, но рывками (телепортироваться персонаж наш должен по экрану :) ).
ОтветитьУдалитьИнтересно. А что если Вам еще перевести следующую книгу
ОтветитьУдалитьGet started with game apps development
for the Android platform
Beginning
Android Games
Mario Zechner
Сайт между прочим не корейский, а японский :)
ОтветитьУдалить