В этой статье мы познакомимся с физическими движками доступными в Phaser-е по умолчанию. Это Arcade, P2JS и Ninja.
Так же в Phaser-е доступен и Box2d, но он доступен только как платное дополнение.
Arcade
Физика Arcade весьма элементарна, в ней возможны только простейшие геометрические фигуры: прямоугольник и окружность. При этом тела не могу вращаться. Поэтому эта физика подходит только для каких-нибудь элементарных физических игр. Достаточно посмотреть пример на оф. сайте.
Ninja
Физика Ninja, была создана во Flash компанией Metanet Software и портирована на js Ричардом (создателем Фейзера).
Как говорит сам Ричи (написано в документации), «библиотека работает хорошо, но она нуждается в серьёзной доработке и оптимизации». Таким образом эту физику не используют, т.к., можно сказать, она технически устарела. Да и скудное кол-во примеров на сайте тоже об этом говорит.
P2JS
А вот физика P2 — то что надо. Можно создавать сложные объекты, настраивать и вращать их и т.д. как в полноценном физическом движке.
Для начала сделаем простейший пример использование этой физики — создание и удаление геометрических примитивов.
Для всех своих проектов я буду брать свой шаблон для HTML5 проекта на Phaser+TypeScript который описан в этой статье. Создаём новый проект на TS, подключаем фейзер или просто берём мой шаблон.
И делам создание объектов по тапу на пустом месте и уничтожение объекта если тапнули на сам объект:
Можно открыть чистую страницу примера для мобильных устройств: страница примера.
Полный код примера вы найдёте на гитхабе.
Основной код находится в классе состояния Game:
module P2JSExample.Client { export class Game extends Phaser.State { tfFPS: Phaser.Text; create() { // for fps displaing this.game.time.advancedTiming = true; // physics init this.physics.startSystem(Phaser.Physics.P2JS); // setting gravity this.game.physics.p2.gravity.y = 300; // adding event listener for mousedown/touch event this.game.input.onDown.add(this.onDown, this); this.tfFPS = new Phaser.Text(this.game, 5, 5, 'FPS: ', { fill: '#EEEEEE', align: 'left' }); this.add.existing(this.tfFPS); var info = this.add.text(Config.GW - 5, 5, 'Phaser P2 physics test\nclick on the screen and objects', { fill: '#EEEEEE', align: 'right' }); info.anchor.set(1, 0); this.addRandomObject(new Phaser.Point(this.world.centerX, this.world.centerY)); } onDown(pointer: Phaser.Pointer) { // checking for bodies under the mouse var bodyClicked = this.game.physics.p2.hitTest(pointer.position); if (bodyClicked.length == 0) { this.addRandomObject(pointer.position); } else { try { // destruction of physics body and its graphic asset for (var i = 0; i < bodyClicked.length; i++) { var spr: Phaser.Sprite = bodyClicked[i]['parent']['sprite'] as Phaser.Sprite; if (spr != null) spr.kill(); } } catch (e) { LogMng.log(e, LogMng.ERROR); } } } // creation of physics body and its graphic asset addRandomObject(aPos: Phaser.Point) { // select random texture var isCerc: boolean = MyMath.randomIntInRange(1, 10) <= 5; var key = isCerc ? Const.cercObjs[MyMath.randomIntInRange(0, Const.cercObjs.length - 1)] : Const.rectObjs[MyMath.randomIntInRange(0, Const.rectObjs.length - 1)]; var newObj = this.add.sprite(aPos.x, aPos.y, key); // enable physics to graphic this.game.physics.p2.enable(newObj); // make circle if (isCerc) newObj.body.setCircle(35); } update() { } render() { // update FPS this.tfFPS.text = 'FPS: ' + (String(this.game.time.fps) || '--'); } } }
Из интересных моментов стоит обратить как надо отображать FPS counter в Phaser-е, для начала надо поставить свойство game.time.advancedTiming в true а затем отображать переменную this.game.time.fps в процедуре render(), т.к. в отличии от update() она вызывается через фиксированные промежутки времени.
Использование Physics Editor для P2
Physics Editor — это очень простая и удобная программа разработанная командой CodeAndWeb (создатели TexturePacker) для создания физики для 2D объектов.
Программа не бесплатная, но стоит не дорого и она того стоит.
Существует готовый экспорт данных для Phaser-а и для многих других движков и фреймворков. Вот официальная документация для Phaser-а: ссылка.
Принцип использования такой — загружаешь текстуры, которые будут использоваться в игре в программу и прям по ним создаёшь физический объект. Далее экспорт и использование в программе.
Вот как загружаются данные:
preload() { // phys this.load.physics('physData', './assets/phys/objects.json'); }
А вот как применяются на объект:
constructor(game: Phaser.Game, x: number, y: number, id: number) { super(game, x, y, 'game', ConstObjs.ObjsData[id].texture); this.game.physics.p2.enable(this, false); this.body.clearShapes(); this.body.loadPolygon('physData', ConstObjs.ObjsData[id].texture); this.body.fixedRotation = true; this.body.kinematic = true; }
Легко, просто и удобно. Я приобрёл редактор как раз перед проектом, в котором надо было делать физику не стандартной формы, теперь я не знаю лучшей альтернативы и доволен как слон)
В следующих статьях сделаем какую-нибудь простую игру с физикой)
В комментариях можете писать какую бы вам хотелось.