libGDX. Урок 3. Игровая логика

Теперь добавим немного логики в нашу игру: -поиск дверей, за которыми стоят козы; -добавление состояний игры для облегчения управления кодом.

 

Поиск дверей, за которыми стоят козы

В первую очередь необходимо объявить переменную типа boolean в нашем классе DoorClass с названием isGoat для определения, находится ли коза за дверью:

public boolean isGoat = false; // указывает, стоит ли коза за дверью
public Vector2 position = new Vector2(); // позиция двери
//размеры двери
public float height; //высота двери

Далее мы должны присвоить значение этой переменной для каждой двери соответственно в методе initDoors() класса GameManager:

//установка текстур для открытых дверей
doors.get(0).openSprite.setRegion(goatTexture);
doors.get(0).isGoat= true;
doors.get(1).openSprite.setRegion(carTexture);
doors.get(1).isGoat= false;
doors.get(2).openSprite.setRegion(goatTexture);
doors.get(2).isGoat= true;

Когда пользователь выберет дверь касанием по ней, другая дверь (с козой) откроется. Если за обеими оставшимися дверьми скрываются козы – одна из них выберется случайно. Чтобы сделать это, напишем метод getGoatIndices(). В этом методе мы будем находить индексы дверей с козами и хранить их в массиве целых чисел (IntArray), который будет объявлен в классе GameManager:

static Texture goatTexture; // текстура для изображения козы
static Vector3 temp = new Vector3(); // временный вектор для хранения входных координат
static IntArray goatIndices; // массив целых чисел для хранения индексов дверей с козами

Создадим объект этого класса в методе initialize() класса GameManager:

goatIndices = new IntArray();

Теперь создадим метод getGoatIndices() в классе GameManager. Этот метод в качестве аргумента будет принимать индекс двери, которая была выбрана:

/* Поиск двери с козой среди оставшихся невыбранных */
public static IntArray getGoatIndices(int selectedDoorIndex){
    goatIndices.clear(); // удаляем все предыдущие значения из массива
    for(int i=0;i<doors.size;i++){
        // исключаем выбранную пользователем дверь
        if(i!=selectedDoorIndex && doors.get(i).isGoat) {
            goatIndices.add(i);
        }
    }
    return goatIndices;
}

Проверяем все элементы массива дверей и добавляем индекс в массив goatIndices, если за дверью находится коза. После чего возвращаем массив goatIndices.

 

Добавляем состояния игры (enum)

У нас будет три состояния в игре: START, CONFIRM, END:

  • START: Исходное состояние нашей игры, при которой все двери закрыты. Как только пользователь касанием выбирает дверь – откроется другая дверь с козой. Состояние игры меняется на CONFIRM;
  • CONFIRM: В этом состоянии у пользователя есть выбор: оставить свой вариант (выбрать ту же дверь, которую он указал в первый раз) или сменить своё решение и выбрать другую дверь. После того, как пользователь выберет дверь, она откроется. В этот момент игровая логика проверяет выиграл ли пользователь или проиграл. После чего состоянием игры меняется на END;
  • END: В этом состоянии игра окончена и происходит вывод сообщения о том, выиграл он или нет.

enum android studio

Мы объявим три состояния через enum и переменную level в классе GameManager (изменения в коде выделены):

static float width,height;

public static enum Level {
    START,
    CONFIRM,
    END
}
static Level level;

public static void initialize(float width,float height){

А в методе initialize() класса GameManager инициализируем переменную level состоянием START:

level = Level.START;

Теперь нам нужно слегка изменить объявление метода handleDoor() в классе InputManager и включить в список параметров индекс двери, которую хотим проверить:

public static boolean handleDoor(DoorClass door,float touchX,float touchY,int doorIndex){

Этот индекс будет передаваться методу handleDoor() в теле метода handleInput():

if (!door.isOpen) {
    if (handleDoor(door, touchX,touchY,i)) {
        break;

Для реализации задуманной нами игровой логики потребуется изменить код внутри метода handleDoor():

    public static boolean handleDoor(DoorClass door,float touchX,float touchY,int doorIndex){

        // Проверяем, находятся ли координаты касания экрана
        // в границах позиции двери
        if((touchX>=door.position.x) && touchX<=(door.position.x+ door.width) && (touchY>=door.position.y) && touchY<=(door.position.y+door.height) ){

            switch (GameManager.level) {
                case START:
                    //открыть случайную дверь из оставшихся
                    //после того, как пользователь выбрал предполагаемую им дверь
                    GameManager.doors.get(GameManager.getGoatIndices(doorIndex).random()).isOpen = true;
                    //меняем состояние нашей игры на CONFIRM
                    GameManager.level = GameManager.Level.CONFIRM;
                    break;

                case CONFIRM:
                    door.isOpen = true; //открыть выбранную дверь
                    GameManager.level = GameManager.Level.END;
                    //меняем состояние нашей игры на END
                    break;
            }
            return true;
        }
        return false;
    }

}

Через switch мы проверяем состояние игры в данный момент. Если игра находится в состоянии START, значит пользователь еще не выбрал ни одну из дверей. После того, как пользователь сделает свой выбор, мы используем метод getGoatIndices(), чтобы получить индексы дверей с козами. Затем, случайным образом выбирается одна из них и открывается пользователю. Состояние игры меняется на CONFIRM. Если игра находится в состоянии CONFIRM, то пользователь должен или подтвердить свой выбор или поменять его. После чего, открывается дверь, которую он выбрал и состояние игры меняется на END.

 
Состояние START:

android studio libgdx game

Состояние CONFIRM:

android studio libgdx game

Состояние END:

android studio libgdx game

В следующем уроке научимся отображать текст и реализуем кнопку restart. А исходный код для всех классов на данный момент можно скачать внизу:

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