Статьи

Разработка игр для Android — перемещение изображений на экране

В предыдущем посте мы отобразили изображение и реализовали очень простую функцию перетаскивания. Вещи, которые мы должны знать уже после серии:

  • запустить приложение Android на весь экран
  • использовать отдельный поток, который контролирует приложение (игровой цикл)
  • загрузить изображение из ресурсов
  • приобрести холст и нарисовать на нем изображение
  • обрабатывать основные сенсорные жесты

Задача, которую я ставлю для этой записи, проста: заставить дроида путешествовать по экрану. Он никогда не должен покидать поверхность и должен отскакивать назад, когда он ударяется о стену, которая является краем экрана.

Если вы помните, изображение это просто представление дроида. Поэтому мы изменим объект дроида и добавим некоторые способности. Только один на данный момент. Наш дроид подвижный. Это может двигаться. Это подразумевает, что у него есть скорость . Мы наденем его способностью двигаться. Чтобы добиться этого, мы добавим метод move (), и этот метод просто обновит координаты X и Y в зависимости от его скорости . Скорость будет классом сама по себе, и Дроид будет содержать его. Сейчас я сделаю конкретную реализацию, но позже я буду использовать шаблон стратегии .

Создайте класс Speed.java .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package net.obviam.droidz.model.components;
 
public class Speed {
 
    public static final int DIRECTION_RIGHT = 1;
    public static final int DIRECTION_LEFT  = -1;
    public static final int DIRECTION_UP    = -1;
    public static final int DIRECTION_DOWN  = 1;
 
    private float xv = 1;   // velocity value on the X axis
    private float yv = 1;   // velocity value on the Y axis
 
    private int xDirection = DIRECTION_RIGHT;
    private int yDirection = DIRECTION_DOWN;
 
    public Speed() {
        this.xv = 1;
        this.yv = 1;
    }
 
    public Speed(float xv, float yv) {
        this.xv = xv;
        this.yv = yv;
    }
 
    public float getXv() {
        return xv;
    }
    public void setXv(float xv) {
        this.xv = xv;
    }
    public float getYv() {
        return yv;
    }
    public void setYv(float yv) {
        this.yv = yv;
    }
 
    public int getxDirection() {
        return xDirection;
    }
    public void setxDirection(int xDirection) {
        this.xDirection = xDirection;
    }
    public int getyDirection() {
        return yDirection;
    }
    public void setyDirection(int yDirection) {
        this.yDirection = yDirection;
    }
 
    // changes the direction on the X axis
    public void toggleXDirection() {
        xDirection = xDirection * -1;
    }
 
    // changes the direction on the Y axis
    public void toggleYDirection() {
        yDirection = yDirection * -1;
    }
}

Мы будем использовать константы направления, чтобы определить направление движения на оси. Дроид имеет вертикальную и горизонтальную скорость, и при каждом обновлении игры координаты устанавливаются с учетом направления движения.
Дроиду будет разрешено перемещаться только по области холста. Это прямоугольник и наша 2D система координат. В отличие от математических классов, источник находится в верхнем левом углу. Поэтому для запуска дроида из верхнего левого угла экрана его координаты будут 0,0. Для перемещения по диагональной линии скорость будет равна 1 для обоих компонентов X и Y вектора скорости. Для перемещения вниз вправо направления будут: 1 (справа) для оси X и 1 (вниз) для оси Y.

Система координат холста

Чтобы дроид двигался горизонтально, скорость вектора Y должна быть 0 . Значение 0,5 для Y и 1 для X заставит дроида двигаться под углом 22,5 градуса к оси X. Простая геометрия.

В Speed у нас есть векторные компоненты (x и y) и направления вместе с геттерами и сеттерами. Два метода ( toggleXDirection () и toggleYDirection () ) просто меняют направление одним вызовом. Позже мы увидим при обнаружении столкновений (со стеной экрана), что это довольно полезно.

Игровой цикл ( MainThread.java ) получает важную модификацию, поскольку вводится метод обновления игры. Следующий фрагмент кода представляет собой обновленный метод run (), в который добавлена ​​только одна строка:

1
this.gamePanel.update();

Метод run () :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void run() {
    Canvas canvas;
    Log.d(TAG, "Starting game loop");
    while (running) {
        canvas = null;
        // try locking the canvas for exclusive pixel editing
        // in the surface
        try {
            canvas = this.surfaceHolder.lockCanvas();
            synchronized (surfaceHolder) {
                // update game state
                this.gamePanel.update();
                // render state to the screen
                // draws the canvas on the panel
                this.gamePanel.render(canvas);
            }
        } finally {
            // in case of an exception the surface is not left in
            // an inconsistent state
            if (canvas != null) {
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }   // end finally
    }
}

Мы создадим соответствующий метод в MainGamePanel . Этот метод отвечает за обновление состояния всех объектов в приложении. На данный момент только дроид. Поскольку дроид движется, мы введем базовое обнаружение столкновений со стенами. Логика проста. Проверьте, движется ли дроид влево, затем проверьте, находится ли положение дроида на стене, и затем измените его направление. Имейте в виду, что положение дроида является центром изображения, поэтому нам нужно использовать ширину и высоту изображения, чтобы получить правильную точность.
Мы также обновляем положение дроида. Для простоты метода обновления мы делегируем обновление позиции дроида самому дроиду. Таким образом, дроид получит метод обновления, который будет обновлять свою позицию, если дроид не будет подхвачен жестом касания. Проверьте предыдущий пост для этого.

Проверьте код: MainGamePanel.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void update() {
    // check collision with right wall if heading right
    if (droid.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
            && droid.getX() + droid.getBitmap().getWidth() / 2 >= getWidth()) {
        droid.getSpeed().toggleXDirection();
    }
    // check collision with left wall if heading left
    if (droid.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
            && droid.getX() - droid.getBitmap().getWidth() / 2 <= 0) {
        droid.getSpeed().toggleXDirection();
    }
    // check collision with bottom wall if heading down
    if (droid.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
            && droid.getY() + droid.getBitmap().getHeight() / 2 >= getHeight()) {
        droid.getSpeed().toggleYDirection();
    }
    // check collision with top wall if heading up
    if (droid.getSpeed().getyDirection() == Speed.DIRECTION_UP
            && droid.getY() - droid.getBitmap().getHeight() / 2 <= 0) {
        droid.getSpeed().toggleYDirection();
    }
    // Update the lone droid
    droid.update();
}

getWidth () и getHeight () возвращают ширину и высоту представления. Панель — это вид, помнишь?

Метод update () файла Droid.java :

1
2
3
4
5
6
public void update() {
    if (!touched) {
        x += (speed.getXv() * speed.getxDirection());
        y += (speed.getYv() * speed.getyDirection());
    }
}

Я также изменил имя рендера в MainThread.java, так что теперь он отображается вместо onDraw . Просто мне больше нравится, как следует за обновлением -> рендеринг имен.

Запустите приложение, и вы увидите экран, подобный следующему: дроид двигается под углом 45 градусов и отскакивает от стен, когда он ударяется о них. Вы также можете перетащить дроида.
Для выхода из приложения нажмите (коснитесь) нижнюю часть экрана.

Движущийся дроид

Загрузите полный исходный код и проект затмения здесь .

Ссылка: перемещение изображений на экране с Android от нашего партнера JCG Тамаса Яно из блога « Против зерна ».

Не забудьте проверить нашу новую Android игру ArkDroid (скриншоты ниже) . Ваш отзыв будет более чем полезным!
Статьи по Теме: