В этой статье мы познакомимся с физическими движками доступными в 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;
}
Легко, просто и удобно. Я приобрёл редактор как раз перед проектом, в котором надо было делать физику не стандартной формы, теперь я не знаю лучшей альтернативы и доволен как слон)
В следующих статьях сделаем какую-нибудь простую игру с физикой)
В комментариях можете писать какую бы вам хотелось.
