libGDX. Урок 8. Анимация игровых объектов.

В этом уроке мы с вами узнаем, как сделать анимацию нашего зомби. Мы будем анимировать нашего зомби таким образом, чтобы пользователю казалось будто зомби вылезает и прячется обратно в яму. Этот процесс будет продолжаться не один раз.

 
Начнем с объявления переменных в классе Zombie:

public float scaleFactor; // коэффициент масштабирования зомби
public enum State {GOINGUP,GOINGDOWN}; // определение состояний зомби
public State state = State.GOINGUP; // переменная, описывающая текущее состояние зомби
public float currentHeight = 0.0f; // текущая величина высоты зомби относительно ямы
public float speed =2f; // скорость, с которой зомби будет двигаться вверх/вниз

Мы определили два состояния для зомби, в которых он может находиться (1. поднимается/2. опускается). Переменная state используется для хранения текущего значения состояния. Мы её инициализировали состоянием GOINGUP. Переменная currentHeight хранит в себе величину высоты зомби над ямой. И переменная speed хранит величину скорости, с которой будет двигаться зомби.

Мы добавим новый метод в класс Zombie. Назовем его update(). Он будет обрабатывать логику анимации:

public void update(){
    switch(state){
        // увеличиваем высоту до максимума, как только высота достигнет максимума - меняем состояние
        case GOINGUP:
            currentHeight+=speed;
            if(currentHeight>=height){
                currentHeight=height;
                state=State.GOINGDOWN;
            }
            break;
        // уменьшаем высоту до минимума(0), как только выоста достигнет минимума - меняем состояние
        case GOINGDOWN:
            currentHeight-=speed;
            if(currentHeight<=0.0){
                currentHeight=0.0f;
                state=State.GOINGUP;
            }
            break;
    }
    // рисуем только часть изображения зомби. Зависит от высоты над ямой
    zombieSprite.setRegion(0, 0, (int)(width/scaleFactor), (int)(currentHeight/scaleFactor));
    zombieSprite.setSize(zombieSprite.getWidth(), currentHeight);
}

Логика следующая: если зомби находится в состоянии GOINGUP мы рисуем только ту часть зомби, которая находится над ямой. Высота определяется переменной currentHeight. Мы увеличиваем эту переменную каждый раз, используя переменную speed. Итак, когда зомби вылезает из ямы, мы отрисовываем его спрайт согласно переменной currentHeight пока не достигнет своего максимума. После этого состояние меняется на GOINGDOWN и зомби опускается обратно в яму.

Для отображения части зомби мы используем следующий метод:

zombieSprite.setRegion(0, 0, (int)(width/scaleFactor), (int)(currentHeight/scaleFactor));

Этот метод позволяет нам установить прямоугольную часть внутри текстуры, которую собираемся нарисовать. В качестве параметров он принимает четыре аргумента. Первые два аргумента задают координаты x и y прямоугольника в текстуре (с левого верхнего угла). Следующие два аргумента определяют ширину и высоту прямоугольника. Все эти значения относятся к текстуре. Но так как мы масштабируем наш спрайт, нам нужно провести обратное преобразование с помощью переменной scaleFactor:

texture sprite libgdx

Затем мы устанавливаем высоту спрайта для отрисовки, чтобы она соответствовала высоте выбранного прямоугольника методом setSize().

Теперь нужно вызвать этот update() метод в методе renderGame() класса GameManager перед тем, как отрисовывать зомби:

// Нарисовать(отобразить) каждого зомби
for(Zombie zombie : zombies) {
    zombie.update();
    zombie.render(batch);
}

Запустив приложение сейчас, вы можете наблюдать, как зомби будут подниматься и опускаться из ям:

анимация android studio libgdx

 

Притаиться под землей

Наши зомби опускаются в яму и тут же вылезают обратно. Давайте заставим их немного посидеть под землей. Добавляем необходимые нам переменные в класс Zombie:

public float speed =2f; // скорость, с которой зомби будет двигаться вверх/вниз
public float timeUnderGround= 0.0f; // время с тех пор, как зомби спрятался под землю
public float maxTimeUnderGround= 0.8f; // максимальное время, разрешенное зомби оставаться под землей

Помимо этого нужно добавить новое состояние:

public enum State {GOINGUP,GOINGDOWN,UNDERGROUND}; // определение состояний зомби

Переменная timeUnderGround служит нам индикатором времени, которое зомби провел под землей с момента, как он там оказался полностью. Переменная maxTimeUnderGround используется как индикатор максимального количества времени, которое зомби может провести под землей перед тем, как начать выползать оттуда. Давайте внесем некоторые изменения в метод update() чтобы сымитировать этот эффект:

public void update(){
    switch(state){
        case UNDERGROUND:
            if(timeUnderGround>=maxTimeUnderGround){
                state=State.GOINGUP;
                timeUnderGround=0.0f;
            }
            else{
                timeUnderGround+= Gdx.graphics.getDeltaTime();
            }
            break;
        // увеличиваем высоту до максимума, как только высота достигнет максимума - меняем состояние
        case GOINGUP:
            currentHeight+=speed;
            if(currentHeight>=height){
                currentHeight=height;
                state=State.GOINGDOWN;
            }
            break;
        // уменьшаем высоту до минимума(0), как только выоста достигнет минимума - меняем состояние
        case GOINGDOWN:
            currentHeight-=speed;
            if(currentHeight<=0.0){
                currentHeight=0.0f;
                state=State.UNDERGROUND;
            }
            break;
    }
    // рисуем только часть изображения зомби. Зависит от высоты над ямой
    zombieSprite.setRegion(0, 0, (int)(width/scaleFactor), (int)(currentHeight/scaleFactor));
    zombieSprite.setSize(zombieSprite.getWidth(), currentHeight);
}

Если зомби находится в состоянии UNDERGROUND, то сперва мы проверяем не превышает ли время, которое зомби провел под землей максимально разрешенное время, которое ему доступно там проводить. В случае если превышает, то зомби начинает вылезать из ямы. Мы переходим в состояние GOINGUP и сбрасываем переменную timeUnderGround на ноль. Если время ожидания под землей не превысило максимально допустимое время ожидания, то увеличиваем значение переменной timeUnderGround используя функцию Gdx.graphics.getDeltaTime(). Переход в состояние UNDERGROUND происходит в тот момент, когда зомби опускается до самого конца (высота над землей равна 0). Запустив ваше приложение сейчас, вы увидите, что зомби немного ждут под землей перед тем как начать подниматься:

 
animation libgdx android studio

Если есть вопросы – задавайте их в комментариях. Исходный код на этот урок можете скачать ниже:

Скачать исходники