Путь Java

Чтобы принять участие в соревновании, используя язык программирования Java, вы можете cкачать готовый Maven проект по этой ссылке:

https://vesnasoft.org/downloads/vesnasoft-ai-2016-java-sdk.zip

Этот проект нужно импортировать в вашей IDE или cкачать .jar файл:

https://vesnasoft.org/downloads/vesnasoft-ai-2016-java-sdk.jar

со всем необходимым, и подключить его к проекту как библиотеку.

В проекте вы увидите следующие Java классы:

XY - простенький класс, который в себе несет всего две переменные типа float : х и y.

С помощью него мы можем назначать вектор движения, или направление пушки, а также узнать свои координаты, или координаты других игроков.

public class XY {
        public float x; //  координата X
        public float y; //  координата Y
}

Работать с XY очень легко. Нужно просто создать новый объект:

XY someVector = new XY(1.0, 0,3); // Можно создать вектор, сразу присвоив значения

XY nextVector = new XY(); // Можно создавать вектор вот так, но тогда вектор будет (0,0)

Player - класс, который описывает каждый танк, и ваш в том числе ;)

В этом классе есть переменные типа String - на пример имя игрока, типа int - на пример время перезарядки орудия, и класса XY - которые описывают положение игрока на поле, или направление движения.

public class Player {
        public String mType; // тип обьекта - в данном случае - игрок
        public int mId; // уникальный номер обьекта - этот номер не повторяется
        public String mUser; // имя игрока (указывается при создании клиента)
        public int mClientTick; // какой последний тик видел этот игрок
        public int mCreated; // тик создания объекта
        public XY mXy; // где находится игрок
        public int mHealthMax; // начальноe значение брони
        public int mHealth; // текущее значение брони
        public XY mMoveXy; // куда едет танк
        public float mMoveSpeedMax; // максимальная скорость танка
        public float mMoveSpeed; // текущая скорость, для простоты: 0 или 50
        public XY mGunXy; // куда смотрит пушка
        public int mGunDamage; // урон от попадания
        public int mGunReloadMax; // максимальное время перезарядки пушки
        public int mGunReload; // Текущее время перезарядки
        public float mBodyRadius; // радиус танка
 }

Shell - класс, который описывает снаряд. На пример его положение, скорость и направление - все что нужно, что вовремя увернуться.

Игроки и снаряды - основные объекты нашего игрового мира. Анализируя их положение, уровень брони, направление и скорость, мы можем совершать ответные действия - на пример двигаться в определенном направлении или стрелять.

public class Shell {
        public String mType; // тип обьекта - снаряд
        public int mId; // уникальный номер объекта
        public String mUser; // имя игрока, который запустил снаряд
        public int mCreated; // тик, в который был произведен выстрел
        public XY mXy; // текущее положение снаряда
        public XY mMoveXy; // вектор направления снаряда
        public float mMoveSpeed; // скорость снаряда
        public float mDamage; // урон от попадания
        public int mBodyRadius; // радиус снаряда
}

Bonus - полезная штука. Через определенные периоды времени на поле появляются бонусы, обозначенные иконками.

public class Bonus {
       public String mType; // тип объекта - бонус
       public String mBonus; // тип бонуса
       public XY mXy; // расположение на поле
       public int mCreated; // тик, в который был показан бонус
       public int mId; // уникальный номер объекта
}

WorldState - один из самых главных классов. Этот класс содержит всю информацию о игровом поле - положение каждого противника, каждого снаряда и бонуса, размер карты, текущее время в игре.

public class WorldState {
        public int mTick; // текущее игровое время
        public XY mSize; // размер карты
        public ArrayList<Player> mPlayerList; // список всех игроков
        public ArrayList<Shell> mShellList; // список всех летящих снарядов.
      public ArrayList<Bonus> mBonusList; // список всех бонусов
}

Input - это наш игровой джойстик. В нем всего три переменные: куда двигаться, куда направить пушку и стрелять ли.

public class Input {
    public XY move; // вектор движения танка
    public XY gun;  // вектор направления пушки
    public boolean fire; // true, если мы хотим выстрелить
}
Вот и все :)

С помощью этих простых штук вы обязательно победите. Но сначала нужно узнать, как же присоединиться к соревнованию?

Если вы скачали Maven-проект, в начале нужно распаковать .rar архив в любое удобное место, а затем импортировать его в среде разработки.

Откройте класс Example. В нем вы видите функцию main, в которой будет самое интересное.

Если же вы скачали не Мавен-проект, а .jar файл, то функция main() по содержанию изначально должна быть такой как в примере ниже, чтобы все заработало.

public class Example {

    public static void main(String[] args) throws InterruptedException {
         // Чтобы начать соревнование, нужно создать клиент:
         //                                        Ваш логин пароль роль в игре
         final VesnaSoftClient client = new VesnaSoftClient("John", "123", "player");
         client.addPlayer(new Play() {

                         // Реализация этой функции - и есть "интеллект" вашего танка
                @Override// Возвращает она новый объект Input() - ввод "джойстика"
                public Input doSomething(WorldState state) {//<- state - состояние мира
                   Input i = new Input();

                   i.move.x = (float) Math.random(); // вектор(направление) движения
                   i.move.y = (float) Math.random(); //

                   i.gun.x = (float) Math.random(); // направление пушки
                   i.gun.y = (float) Math.random(); //

                   i.fire = true; // стрелять ли
                   return i; // Ура! Теперь танк что-то сделает
                   }
               }
            );
            new CountDownLatch(1).await(); // Эта штука не даст программе закончить работу слишком рано :)
    }
}
final VesnaSoftClient client = new VesnaSoftClient("John", "123", "player");

Этот код создает объект клиента для соревнования. Там где сейчас John - введите свой логин (но помните, что он не должен совпадать с логином других игроков), вместо “123” - укажите свой пароль. “player” - это ваша роль в игре. Пусть останется “player”.

Важно:

VesnaSoftClient client = new VesnaSoftClient("John", "123", "player");

client.mThisPlayer - таким образом мы можем получить наш танк в любой точке программы. Очень удобно. Например:

XY someCoordinates = client.mThisPlayer.mXy; // Таким образом узнаем наши координаты
@Override
public Input doSomething(WorldState state) {
    Input inp = new Input();
    // ваш код будет тут ;)
    return inp;
}

Эта функция - самая важная для вас, в ней вы напишите свой код.

WorldState state - параметр, который получает функция.

Вы уже знакомы с этим классом, он содержит всю информацию о игровом мире. Анализируя это состояние, вы напишите интеллект для танков.

Возвращает функция объект Input - ввод джойстика. На основе анализа состояния мира, можно указать направление движение танка, направление орудия и стрелять ли.

Далее - примеры кода:

“Как двигаться”

@Override
public Input doSomething(WorldState state) {
    Input i = new Input(); // создаем новый ввод
    i.move = new XY(1.0f, 0.0f); //двигаемся точно вправо, x = 1.0, y = 0
    //i.move = new XY(0.0f, 1.0f); //двигаемся точно вниз x = 0.0, y = 1.0
    //i.move = new XY(0.0f, -1.0f); //двигаемся точно вверх x = 0.0, y = -1.0
    i.fire = true; // а по ходу движения стреляем
    return i; // возвращаем новый ввод
 }

“Как двигаться к другому танку?”

@Override
public Input doSomething(WorldState state) {
    Input i = new Input();
    //Чтобы двигаться в нужную точку, нужно узнать вектор - просто
    //От координат пункта назначения, отобрать свои координаты.
    //На пример, хотим двигаться к первому танку в списке
    if (state.mPlayerList.size() > 1){ // А на поле вообще больше одного танка?
        Player other = state.mPlayerList.get(0); // получаем первого игрока из списка игроков
        if (other.mUser.equals(client.mThisPlayer.mUser)) // Если это - мы, то получаем второго
            other = state.mPlayerList.get(1);
            // цель.x - наш танк.x, цель.y - наш танк.y
        i.move = new XY (other.mXy.x - client.mThisPlayer.mXy.x, other.mXy.y - client.mThisPlayer.mXy.y);
    }
    return i;
 }

“Как двигаться и стрелять в другой танк?”

@Override
public Input doSomething(WorldState state) {
   Input i = new Input();
    if (state.mPlayerList.size() > 1){ // А на поле вообще больше одного танка?
        Player other = state.mPlayerList.get(0); // получаем первого игрока из списка игроков
        if (other.mUser.equals(client.mThisPlayer.mUser)) // Если это - мы, то получаем второго
            other = state.mPlayerList.get(1);
        XY vec = new XY (other.mXy.x - client.mThisPlayer.mXy.x, other.mXy.y - client.mThisPlayer.mXy.y);
        // нашли vec - направление к другому танку
        i.move = vec; // движемся в этом направлении
        i.gun = vec; // стреляем в этом направлении
        i.fire = true; // стреляем
    }
   return i;
 }

Пример “Как двигаться по кругу?”

Объявляем статическую переменную counter в классе Example И просто добавляем к желаемой точке движения результаты вычисления синуса и косинуса из переменной counter. И нужно не забыть увеличивать counter :)

public static float counter = 0;
   @Override
   public Input doSomething(WorldState state) {
   Input i = new Input();
   i.move.x = (float) ((Math.sin(counter) + client.mThisPlayer.mXy.x) - client.mThisPlayer.mXy.x);
   i.move.y = (float) ((Math.cos(counter) + client.mThisPlayer.mXy.y) - client.mThisPlayer.mXy.y);
   counter += 0.1;
   return i;
}

“Как найти расстояние до объекта?”

Чтобы эффективно справиться с управлением, часто вам придется узнавать расстояние до другого объекта - снаряда, или другого танка. Сделать это очень просто - в этом нам поможет всем известная теорема Пифагора. В данном случае - расстояние между объектами является гипотенузой.

public static int getDistantion(Shell shell, Player thisPlayer){
    return (int) Math.sqrt(Math.pow(shell.mXy.x - thisPlayer.mXy.x, 2) + Math.pow(shell.mXy.y - thisPlayer.mXy.y,2));

Эта функция может принимать на вход другой объект: в данном примере - снаряд, и ваш танк. Возвращает - текущее расстояние. Если вы хотите найти расстояние не до снаряда, а, например, до танка, то просто замените в аргументах функции объект Shell на обьект Player.

“Как найти ближайший танк?”

public static Player getNearestEnemy(WorldState state, Player thisPlayer){
        if (state.mPlayerList.size()<2 || thisPlayer == null || state == null)
            return null; // Если что-то не так - выходим

        Player nearestEnemy = null;
        int dist = state.mPlayerList.get(0).mUser.equals(thisPlayer.mUser) ? getDistantion(state.mPlayerList.get(1), thisPlayer) : getDistantion(state.mPlayerList.get(0), thisPlayer);
        for (Player player : state.mPlayerList){ // проходим по списку игроков
              int n = getDistantion(player, thisPlayer); // находим дистанцию по функции выше
              if (dist >= n && !thisPlayer.mUser.equals(player.mUser)){ // если дистанция меньше
                  dist = n;     // то сохраняем ссылку на
                  nearestEnemy = player;    // этого соперника
              }
        }
    return nearestEnemy; // Ура, мы нашли ближайшего соперника)
}