пятница, 26 мая 2017 г.

Создание состояния Phaser

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


var sampleState = {
init: function() {
//выполнить любую настройку до того как состояние начнет работать
},
preload: function() {
//загрузить ассеты для игры
},
create: function() {
//заполнить состояние игровыми объектами
},
update: function() {
//особый код игры
},
shutdown: function() {
//код, выполняемый перед завершением состояния
}
}


вторник, 23 мая 2017 г.

Конечный автомат

  Цель конечного автомата - создать группу разных уникальных режимов, в которых может работать программа. Эти состояния "конечны" в том смысле, что всегда только одно из этих состояний может быть активно или запущено в игре в определенный момент времени. Автомат состояний - это конструкция, созданная для обеспечения того, что всегда работает только одно состояние и для плавного перехода между состояниями. Переходы между состояниями происходят с помощью остановки текущего состояния (позволяя ему уничтожить данные или сделать сохранение в последний момент перед его остановкой) и последующего его отключения. После того, как старое состояние остановлено, запускается новое состояние , позволяя ему пройти этап настройки. Затем это новое состояние запустит его метод обновления в тандеме с обновлением игры, пока оно не остановится для перехода.
  Рабочий день - это хороший пример различных состояний и переходов между ними. Много людей начинают их рабочий день дома, где они просыпаются и занимаются работой по дому. Это можно считать состоянием "приготовление". Дальше будет поездка, чаще всего на автомобиле, что является состоянием "вождение". Потом будет сама работа и она ассоциируется с состоянием "работа". Каждое из этих состояний не пересекается, по крайней мере не в нашем идеализированном мире. Когда сотрудник едет, он просто едет. Очевидно есть промежуток времени между каждым состоянием, например время, которое работник тратит чтобы выйти из дома и сесть в машину. Двери должны открываться, из домов нужно выходить, ключи должны находиться. Эти переходы состоят из двух частей: окончание старого состояния и начало нового. В случае перехода в связывающее состояние, дом должен быть покинут и заперт, закрывая состояние "подготовки". Далее нужно открыть машину, сесть в нее и завести для запуска состояния "вождения". Комбинация методов отключения и настройки становится тем переходом между более сложными циклами обновления состояния.
  Состояния Phaser работают точно так же. После того, как запущено конкретное состояние, его цикл обновления будет управлять всей игрой. Игра имеет несколько методов для смены между состояниями, которые будут автоматически вызывать функцию на текущем состоянии, чтобы правильно завершить работу состояния и затем создать и настроить новое состояние для его запуска.
  Другое замечательное место, где можно увидеть конечный автомат в действии - это анимации внутри игр, где анимация должна быть завершена до того, как другая сможет начаться. Файтинги - отличный пример применения конечного автомата. Когда управляешь персонажем файтинга, только одна анимация атаки может быть активна в данный момент. После того, как вызвана и начата анимация атаки персонажа, она будет полностью воспроизведена до конца и затем, как только состояние атаки закончится, будет переход. Переход может быть в состояние бездействия, или в случае комбо, может быть другая анимация, которая будет длиться столько, сколько верна цепочка нажатия кнопок для комбо. Запрет на потенциальные передвижения, основанные на текущем состоянии объекта это еще одна крутая вещь для использования конечного автомата и это может быть применено для замечательного эффекта в ваших играх с помощью небольшой работы и вниманием над этим.

среда, 17 мая 2017 г.

Состояния

  Вся игровая логика, которая делает вашу игру уникальной, располагается внутри состояния. Состояния связывают ряд методов, которые помогают программе входить и потенциально выходить из некоторой части геймплея. Простая игра, имеющая только одну часть геймплея или взаимодействия  будет иметь только одно состояние, но реальная сила состояний осознается во время создания нескольких различных состояний и переходов между ними, для того, чтобы перемещать пользователя между частями игры. Обычное использование нескольких состояний включает в себя создание начального экрана, который переходит в геймплей или разные уровни внутри игры. Они особенно полезны для игр, которые имеют разные типы геймплея на разных уровнях, как например летающий уровень, идущий за уровнем под водой. Состояния дают фреймворку Phaser способность превратить эти очень сложные части геймплея в разделенные куски кода, которыми легче и логичнее управлять.
  Вообще, состояния в Phaser это реализация программной структуры, называемой “finite-state machine" (конечный автомат). В силу своей природы конечного автомат, Phaser будет запускать методы внутри состояний в определенном порядке, начиная с предварительной загрузки, останавливаясь на методе обновления, и вызывая финальную функцию очистки, если вам необходимо перейти в другое состояние. Phaser вызовет все эти методы автоматически, так же как он автоматически вызывает обновление текущего состояния для работы уникального геймплея игры. До того, как вникнуть глубже в особенности состояний Phaser, мы обсудим то, как работают автоматы состояний и их конкретные виды использования помогут нам попытаться соединить эти разные состояния в одной игре.

вторник, 16 мая 2017 г.

Этап обновления логики

  На этапе обновления логики выполняется код, который осуществляет весь геймплей. На самом деле этот метод является двумя для каждого из обновлений: пред-обновление и само обновление. Во время фазы пред-обновления, все очищается и приготавливается для обновления, но никого кода геймплея не выполняется. Как только все готово для обновления, Phaser запустит метод обновления текущего состояния, изменит позиции элементов на уровне, выполнит физические вычисления, обновит текущую используемую систему частиц, а так же выполнит некоторые другие разные задачи для работы игры.
  Разработчик работает в методе обновления состояния. Это место,   где   он 
указывает, что делать с вводом, как двигать объекты, когда вызывать анимацию, и все что угодно остальное, что делает его игру уникальной. Каждый игровой объект также имеет потенциальный шанс запустить его собственную функцию обновления, если разработчик определит ее. Собственные функции обновления полезны для объектов, которым нужно сделать что-то большее, например, расчет искусственного интеллекта или собственное управление состоянием (например, дверь может закрыться сама собой в игре-страшилке). Если вы хотите создать объект, который осуществит его собственную функцию обновления, они должны быть расширены от классов, реализованных в Phaser, тогда Phaser сможет найти этот метод обновления и работать с классами. Примеры этого подхода обсуждаются этом разделе под названием "Принципы Phaser". Комбинирование обновления состояния и их отдельных объектов делает каждую игру уникальной. Код, который написан для обновления сайд-скроллер платформера будет сильно отличаться от кода для игры три в ряд.
  Если игра не на паузе, Phaser запустит все эти методы для каждого обновления этапа логики. Следующий список - это все методы, которые Phaser выполняет для того чтобы обработать обновление. Обратите внимание на три фазы (пред-обновление, обновление, пост-обновление). Сначала запускается код геймплея, написанный разработчиком (в state.update()) и затем система Phaser делает остальную часть работы игрового движка автоматически. Все это происходит за сценой и часто не нужно ничего менять, но будет хорошо знать порядок вещей, происходящих в игре.

this.debug.preUpdate();
this.world.camera.preUpdate();
this.physics.preUpdate();
this.state.preUpdate(timeStep);
this.plugins.preUpdate(timeStep);
this.stage.preUpdate();
this.state.update();
this.stage.update();
this.tweens.update(timeStep);
this.sound.update();
this.input.update();
this.physics.update();
this.particles.update();
this.plugins.update();
this.stage.postUpdate();
this.plugins.postUpdate();

понедельник, 15 мая 2017 г.

Игровой цикл

  Первая вещь, которую надо понять об игровых движках (и это будет правдой почти о любом игровом движке) это игровой цикл, который работает всю игру. Для того, чтобы игрок воспринимал движение в игре плавным и непрерывным, игра в идеале должна запускать некий код 30 раз в секунду, хотя это может быть снижено до 20 раз и все еще будет удовлетворительно. Мало того что код, который управляет всей игрой, должен выполняться десятки раз в секунд, но еще он должен делать это надежно каждый раз, когда происходит обновление. Если что-то происходит в тот момент, когда он выполняется, и это занимает долгое время, тогда будет меньше времени для следующего кадра, и число кадров, отрисовывающихся в ту секунду будет уменьшено (часто называется падением фпс). Создание функции, которая работает надежно так много раз в секунду - это небольшое приключение.
  Раньше игровой цикл был прекрасно прост. Он создавал блок кода, который работал вечно ( while(true) делал штуку, которая никогда не останавливалась). Внутри того блока кода, игра работала через три главных задачи игрового движка: получала ввод от пользователя, обновляла игровое состояние и отрисовывала результат двух предыдущих шагов на экран. Метод ввода получал все, что пользователь делал в тот момент с устройствами, особенно клавиатурой и мышью, но сюда так же относились контроллеры и пульты. Обновление игрового состояния происходит там, где полностью реализован сам геймплей. Изображения двигались повсюду, срабатывал звук, проверялись столкновения, и все это в в методе обновления. Наконец, метод отрисовки очищал весь экран и перерисовывал каждый видимый элемент в игры. С каждым следующим подходом, все это происходило настолько быстро, насколько это возможно с целью достичь или превысить отметку 30 кадров в секунду.

while(true) {
getInput();
updateLogic();
render();
}

  Будучи быстрым и простым в создании, простой цикл имел два недостатка. Во-первых, код замедлялся, если в нем было слишком много вычислений. Больше кода, сложные алгоритмы, или просто плохое программирование означало замедленный цикл и меньше кадров в секунду. Вторая проблема этого подхода была в том, что в прошлом скорость игры зависела от скорости процессора. Игры, написанные для старых компьютеров, которые отражали уровень развития в то время, быстро начали ускорятся на поздних компьютерах, которые стали значительно быстрее исходя из закона Мура, и процессоры удваивались в скорости каждые два года. Игры быстро стали неиграбельными, поскольку обрабатывались со сверхсветовой скоростью (говоря относительно).
  Решением проблемы очень частых обновлений было заставить игру ждать пока она готова для следующего обновления, с помощью приостановления времени обработки до тех пор, пока не прошла определенная доля секунды. Это не направит нас к решению противоположной проблемы медленной игры, которая использует слишком много времени для игрового цикла. Исправление этой проблемы - хранение прошедшего времени с последнего обновления и запуск обновлений логики настолько часто, насколько нужно, чтобы наверстать все к текущему времени. Этот процесс "наверстывания" происходит между полным циклом. Так что игра получит ввод единожды, несколько раз обновит только логику, и затем отрисует один раз. Медленным компьютерам может потребоваться обновлять логику несколько раз чтобы наверстать, в то время как быстрым потребуется сделать это меньше число раз, приближаясь к идеалу только одного обновления логики за полный игровой цикл.
  Важно помнить, что отрисовка и обновление логики не происходит в одно и то же время, или даже синхронно. Полностью возможно обрабатывать обновления для игры без отрисовки этих обновлений, и это иногда может быть очень полезно для игры, чтобы получить все "настроенное и решенное", например как в игре, основанной на физике. Движения и другие обновления также могут разными для обновления и отрисовки. Когда обновление двигает объект на 5 пикселей вправо, это не то же самое, если бы отрисовка двигала его на 5 пикселей каждый кадр. Фактически он может двигаться дальше, в зависимости от числа обновлений логики, которые происходят до отрисовки.

Принципы Phaser

  Все игровые движки предлагают набор возможностей для разработки тем, кто решил их использовать. Как правило, часто эти возможности влияют на выбор тех, кто выбрал один движок вместо другого. Одна из крутых вещей в Phaser - это то, что он полнофункциональный, с кучей функций, доступных прямо из коробки, а другое доступны через плагины. Функции, составляющие Phaser выливаются в довольно большую систему, которая хорошо задокументирована на phaser.io/examples и phaser.io/docs . Размер и сложность фреймворка - это всегда благо и проклятье. Это круто, когда фреймворк способен на многое, но в то же время это значит, что разработчикам нужно понимать что предоставляет фреймворк, как он работает и пределы технологий, прежде чем они смогут вникнуть и начать работать.
  Цель этой главы - объяснить различные части Phaser, чтобы дать обзор того, как движок работает, и это это, в целом, возможно. Эта глава содержит исходный код, где необходимо помочь объяснить идеи или написать примеры, которые могут быть использованы когда вы сядете писать свою собственную игру. Это не исчерпывающий список того, на что Phaser способен, и я сильно рекомендую, чтобы вы потратили время на то, что бы просмотреть на некоторые примеры на сайте Phaser и найти больше возможностей и примеров кода, которые вы сможете использовать в ваших собственных играх.

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