вторник, 22 августа 2017 г.

Добавление сложных объектов

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

Физический редактор

  Программа, поддерживающая феймворком Phaser и написанная для создания и экспорта данных фигур называется PhysicsEditor. Эта программа, сделанная компанией CodeAndWeb, может очерчивать спрайты для создания довольно точных контуров многоугольника, которые также можно отредактировать вручную. Ссылку на скачку можно найти на https://www. codeandweb.com/physicseditor.
  Для быстрого и легкого способа добавления фигуры к спрайту, перетащите спрайт в левую область "фигур". В этой программе возможно обрисовать спрайт и создать контуры множества различных фигур, до того как экспортировать все тела, так что когда ваш проект имеет много собственных фигур, вы можете делать всю работу перемещаясь между разными элементами панели фигур.
  После того как у вас есть фигура в рабочей области, найдите инструмент magic wand над картинкой и кликните на него. Вам будет представлен экран, которые автоматически очертит объект спрайта, основываясь на прозрачности объекта, используя для фигуры границы между видимой частью и прозрачной (поэтому убедитесь что ваши изображения сохранены в формате png). Регулировка погрешности вверх сделает вычисления более простыми, обычно уменьшая число точек конечной фигуры. Уменьшенное число точек создаст быстро рассчитываемую для физической системы фигуру. Установка значения погрешности, равное 0 добавит больше точек, создавая более точную фигуру с большим числом точек, которая будет требовать более долгой обработки.
  После того, как вы стали довольными своей фигурой, нажмите OK и вы сможете более тонко настроить фигуру, хватая и двигая точки вручную. Также возможно удалить точки с помощью нажатия на них правой кнопки мыши, или добавить новые точки, нажимая правой кнопкой мыши на пустую часть линии многоугольника.

суббота, 19 августа 2017 г.

Построение составных объектов

  Не все тела в реальном мире являются идеальными кругами или прямоугольниками. Большинство из них очень сложные, хотя игры часто упрощают их в набор примитивных фигур. Например 2D кресло имеет хотя бы четыре прямоугольника (сиденье, спинка, две ножки). Прямоугольники, круги, капсулы (форма пилюли) - все это фигуры, которые можно использовать для созданиях составных объектов. Менее используемые варианты включают в себя линии и плоскости, которые занимают всю площадь игрового мира (полезно для границ или земли).
  При создании составных тел сначала нужно удалить старые фигуры тела спрайта через body.clearShapes()
  В следующем случае загружается спрайт жезла с круговым весом на каждой из сторон палки. Прямоугольник не будет представлять этот жезл в полной мере. Также он будет слишком большим или слишком маленьким в центре, если использовать круги. Капсула будет иметь закругленные концы, но так же не подходит, как и прямоугольник. Лучшим решением будет создание прямоугольника для средней секции и два круга для круговых весов.


game.physics.startSystem(Phaser.Physics.P2JS);
baton = game.add.sprite(300, 400, phaser);
game.physics.p2.enable(baton, true);
baton.body.clearShapes();
baton.body.addRectangle(35, 10);
baton.body.addCircle(10, 20, 0);
baton.body.addCircle(10, 20, 0);


  При добавлении фигур аргументы, идущие за их размером (ширина, высота и радиус), задают сдвиг. По умолчанию все фигуры располагаются над центральной точкой спрайта, к которому они добавляются. Если задан сдвиг, они сдвигаются от цента спрайта на это расстояние. Заметьте, что в этом коде сдвиг по x для двух кругов задан как 20 и -20. Это поместит круги на края жезла, туда где они должны быть.

Добавление основных объектов

  По умолчанию тело спрайта - это прямоугольник, совпадающий со спрайтом по ширине и высоте. Чтобы добавить другую фигуру, нужно удалить тело по умолчанию и заменить его новой фигурой тела. В Phaser есть функция автоматического создания и замены простых тел. Основные метод замены - это setCircle и setRectangle. В следующем коде оригинальный прямоугольник спрайта таблетки заменен на круг. Затем это тело круга будет снова заменено на другой прямоугольник размером, отличающимся от оригинального.


game.physics.startSystem(Phaser.Physics.P2JS);
pill = game.add.sprite(300, 400, pill);
game.physics.p2.enable(pill);
pill.body.setCircle(40);
pill.body.setRectangle(50, 100);


пятница, 18 августа 2017 г.

Настройка мира в P2

  Так же, как для всех физическим системам Phaser, P2 нужно запустить до добавления тел в игровой мир.


game.physics.startSystem(Phaser.Physics.P2JS);

  После этого запуска у спрайтов появляются тела. Так же, как и для аркадных тел, прямоугольник для столкновений по умолчанию будет являться фигурой размером с высоту и ширину спрайта.


brick = game.add.sprite(300, 400, brick);
game.physics.p2.enable(brick);


Отладка тел

  Во время работы с системой P2, довольно часто может быть необходимо видеть как выглядят тела спрайтов. Добавление true в качестве второго аргумента при включении физики спрайта позволит затенить тело спрайта, чтобы оно визуально отличалось.


game.physics.p2.enable(brick, true);

пятница, 11 августа 2017 г.

Физическая система P2

  Вторая главная физическая система в Phaser - это P2. Разработанная Стэфаном Хэдманом, это полнофункциональная физическая система, которая включает в себя коллайдеры (еще один термин для частей тела, которое может сталкиваться с другими частями), которые работают для большего количества фигур, а не только для квадрата. Некоторые из главных коллайдеров могут включать в себя круги, плоскости, прямоугольники, капсулы и выпуклые многоугольники. Все эти коллайдеры не обязательно должны быть выровнены по осям, так что поворот объекта повлияет на столкновения естественным образом.
  Эти коллайдеры часто используются для создания веселых и интересных игр с симуляцией физики. Общие типы игр, которые могут использовать P2, включают в себя строительно-разрушительные виды игр, типа Angry Birds, игры с приземлением или гоночные игры с грубым 2D ландшафтом, или продвинутые 2D платформеры с шаткими мостами, которые колеблются, когда игрок их перебегает их. В отличие от аркадного физического движка, эта система обрабатывает столкновения по умолчанию. После того как тело было добавлено в мир, оно всегда будет сталкиваться с другими телами.

Угловая скорость и упругость

  Есть еще один способ двигать аркадные тела на экране - через их угловую скорость и угловое ускорение. Оба эти свойства изменяют "скорость поворота" объекта игры, к которому привязано тело. Это менее используемые свойства, но их можно использовать в гонках с видом сверху или похожих играх с этим же видом.
  Последний пример даст игроку контроль над кораблем, которым может двигаться по экрану. Дополнительно, из-за того что большинство кораблей поглотит большую часть отдачи от удара и хотя-бы немного сместится, упругость корабля и астероидов отрегулирована таким образом, чтобы игра хорошо чувствовалась.


function create() {
  game.physics.startSystem(Phaser.Physics.ARCADE);
  player = game.add.sprite(200, 100, "player");
  player.anchor.setTo(.5,.5);
  game.physics.enable(player, Phaser.Physics.ARCADE);
  player.body.collideWorldBounds = true;
  player.body.drag = { x: 1000, y: 1000 };
  player.body.angularDrag = 750;asteroids = game.add.group();
  asteroids.enableBody = true;
  asteroids.physicsBodyType = Phaser.Physics.ARCADE;
  for (var i = 0; i < 10; i++) {
    var asteroid = asteroids.create(game.rnd.integerInRange(20, 780), 
     game.rnd.integerInRange(20, 580), 'roid');
    asteroid.body.bounce = .9;
  }
  //управление
  cursors = game.input.keyboard.reateCursorKeys();
}
function update() {
  //запуск кода игрового цикла
  if(cursors.left.isDown) {
    player.body.angularVelocity = -200;
  }
  if(cursors.right.isDown) {
    player.body.angularVelocity = 200;
  }
  if(cursors.up.isDown) {
    game.physics.arcade.velocityFromAngle(player.angle, 200, player.body.velocity);
  }
  game.physics.arcade.collide(player, asteroids);
}

четверг, 10 августа 2017 г.

Сопротивление и границы мира

  Вы можете заметить одну вещь, связанную с прошлым примером: персонаж будет скользить вечно в одном из направлений и в конечном итоге упадет за экран. Это произойдет, потому что персонаж существует в мире без трения. Хотя мир без трения на какое-то время может быть крутым, в какой-то момент будет полезно ввести сопротивление в игру, чтобы  игроку не нужно было постоянно контролировать свое движение. Затем, просто на всякий случай, если персонаж спрыгнет с края платформы, мы могли бы оставить его на экране, используя встроенную команду collideWorldBounds. Эта команда автоматически столкнет игрока с четырьмя границами экрана.
  Если вы хотите добавить трение к предыдущему примеру игры, прямо после включения игрока в физическую систему в функции создания, добавьте эти две строчки кода:


player.body.collideWorldBounds = true;
player.body.drag.x = 1000;

Гравитация и неподвижные объекты

  Гравитация - это ускорение вниз, применяемое к спрайтам игрового мира. Довольно легко поместить кучу объектов на уровень и добавить гравитацию, но если мы хотим чтобы они оставались видимы, а не просто падали вниз за экран, нужно что-то, что останавливало  бы объекты при их столкновении. Из-за того что метод collide - это стандартной вызов физики, который передает силы при столкновении двух объектов, если мы поместим землю на уровень, земля начнет двигаться от силы удара. Если у вас есть такие объекты как земля, которые не должны двигаться после столкновений, они должны быть заданы как неподвижные.
  Этот пример - быстрый способ того, как получить игрока, контроллируемого кнопками налево и направо и острова. Остров не подвержен гравитации, а так же столкновение с ним не передает его телу импульса.


var player, ground, cursors;
function create() {
  //настройка игры
  game.physics.startSystem(Phaser.Physics.ARCADE);
  game.physics.arcade.gravity.y = 300;
  player = game.add.sprite(200, 100, player);
  player.anchor.setTo(.5,1);
  game.physics.enable(player, Phaser.Physics.ARCADE);
  ground = game.add.sprite( 100, 500, ground);
  game.physics.enable(ground, Phaser.Physics.ARCADE);
  ground.body.immovable = true;
  ground.body.allowGravity = false;
  //управление
  cursors = game.input.keyboard.createCursorKeys();
}
function update() {
  //запуск кода игрового цикла
  if(cursors.left.isDown) {
    player.body.velocity.x = 200;
    player.scale.x = 1;
  }
  if(cursors.right.isDown) {
    player.body.velocity.x = 200;
    player.scale.x = 1;
  }
  game.physics.arcade.collide(player, ground);
}


  Важная строка в этом куске кода - включение гравитации через game.physics.arcade.gravity.y, что даст всем телам физики arcade ускорение вниз, равное 300. Для земли гравитация явно отключена (ground.body.allowGravity = false), а также она неподвижна, так что когда игрок падает на платформу, она стоит на месте. Затем, когда физика включена, для движения предпочтительнее использовать скорость тела, вместо того, чтобы напрямую изменять координаты x. Это позволит спрайту хорошо работать с физической системой. 
  Наконец, не обязательно писать обработчик столкновений между игроком и землей. Вместо этого нам нужно просто чтобы эти столкновения происходили, чтобы они корректно разделялись при столкновении.

понедельник, 7 августа 2017 г.

Группа с группой

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


var ships;
var mines;
function create() {
  game.physics.startSystem(Phaser.Physics.ARCADE);
  ships = game.add.group();
  ships.enableBody = true;
  ships.physicsBodyType = Phaser.Physics.ARCADE;
  mines = game.add.group();
  mines.enableBody = true;
  mines.physicsBodyType = Phaser.Physics.ARCADE;
  for (var i = 0; i < 50; i++)
  {
    var mine = mines.create(game.rnd.integerInRange(20, 780), 
     game.rnd.integerInRange(20, 580), mine);
    var ship = ships.create(game.rnd.integerInRange(20, 780), 
     game.rnd.integerInRange(20, 580), ship);
    ship.body.velocity.x = 20;
    ship.body.velocity.y = 20;
  }
}
function update() {
  game.physics.arcade.collide(ships, mines, collisionHandler, null, this);
}
function collisionHandler (ship, mine) {
  ship.kill();
  mine.kill();
}

Спрайт с группой

  Столкновение спрайта с группой спрайтов не сильно отличается от столкновения двух спрайтов, единственное отличие в том, что процесс включает в себя создание группы и подключение всех тел этой группы, чтобы они стали частью физической системы. Вот пример кода, который создает минное поле и посылает бедный космический корабль практически на верную смерть.

var ship;
var group;
function create() {
  game.physics.startSystem(Phaser.Physics.ARCADE);
  ship = game.add.sprite(10, 10, ship);
  game.physics.enable(ship, Phaser.Physics.ARCADE);
  group = game.add.group();
  group.enableBody = true;
  group.physicsBodyType = Phaser.Physics.ARCADE;
  for (var i = 0; i < 50; i++)
  {
    var mine = group.create(
    game.rnd.integerInRange(20, 780),
    game.rnd.integerInRange(20, 580), 'mine');
  }
  ship.body.velocity.x = 20;
  ship.body.velocity.y = 20;
}
function update() {
  game.physics.arcade.collide(ship, group, collisionHandler, null, this);
}
function collisionHandler (player, mine) {
  player.kill();
}

  Главное изменение здесь - это создание группы и подключение всех физических тел через group.enableBody и group.physicsBodyType. Так мы создадим тела для всех спрайтов группы без необходимости прохождения через каждый спрайт и вызовем game.physics.enable для создания тела. В противном случае функция обновления должна выглядеть очень похоже, однако теперь второй аргумент функции collide будет группой вместо одиночного спрайта. Эта функция проверит столкновения между игроком и любой из мин, запуская обработчик столкновений для каждого найденного столкновения (хотя в данном случае после первого столкновения игрок будет мертв, так что следующие столкновения происходить не будут).


Экспорт из PhysicEditor   Когда все фигуры удовлетворяют вашему вкусу и вы готовы перенести работу в Phaser, необходимо экспортировать д...