1. 创建P2物理项目:
- 使用P2物理引擎创建物理应用的过程和Box2D类型,步骤是:创建world、创建shape、创建body刚体、实时调用step()函数更新物理模拟计算;基于形状、刚体使用Egret或其他HTML渲染以显示物理模拟效果。
-
1)世界world:
- world是P2物理引擎入口,对应World类,用于承载所有物理模拟对象。world类的构造函数为:
// 创建世界构造函数
function World([options]){options?:{gravity?:number[]=[0,-9.81];}}
# 其中,gravity是重力加速度,这是一个Vec2类型的向量对象,默认为垂直向上的向量[0,-9.81]。将gravity设置为[0,0]可以取消重力,模拟太空失重状态。
-
2)形状Shape:
- 形状是物理模拟计算的基础。任何物体都要有对应的形状,才可以基于P2进行物理碰撞检测和模拟。所有形状对象都需要通过addShape()添加到刚体中,才可以进行碰撞模拟计算:
// 创建一个刚体
var body:p2.Body=new p2.Body();
// 创建一个形状
var shape:p2.Shape=new p2.Shape();
// 形状添加到刚体中
body.addShape(shape);
# P2中的Shape类是一个抽象的父类,要使用Box、Circle等子类。
-
3)刚体Body:
- 刚体是P2物理引擎的核心概念和对象,拥有速度、角度、质量等物理属性,同时包含了形状对象,使刚体拥有具体的形状。将刚体添加到world中,World将以刚体为单位循环遍历,进行物理模拟计算,并将模拟的结果保存在刚体属性中,使刚体成为碰撞对象的原型。所有的刚体都必须通过addBody()添加到P2的world中,才会进行物理模拟:
// 创建一个刚体
var body:p2.Body=new p2.Body();
// 创建一个形状
var shape:p2.Shape=new p2.Shape();
// 形状添加到刚体中
body.addShape(shape);
// 刚体添加到世界中
world.addBody(body);
-
4)贴图Egret:
- P2只是一个算法库,以刚体为对象模型,模拟并输出物理碰撞、运动结果。这个过程通过持续调用world中的step()方法来实现:
// 通过持续调用world中的step()方法来实现以刚体为对象模型,模拟并输出物理碰撞、运动结果
function step(dt:number, timeSinceLastCalled?:number=0, maxSubSteps?:number=10)
// dt: step方法执行的时间间隔,单位秒,通常取值为游戏帧频的倒数;
// timeSinceLastCalled: 当游戏帧频降低时计算两帧之间的时间差作为参数值,此时P2会在一次step()中进行count= timeSinceLastCalled/dt次计算,以保证物理模拟的真实性,默认值为0;
// maxSubSteps: 单次step()进行物理模拟计算的最大次数,当timeSinceLastCalled不等于0时,单次step()中进行计算的次数count最大为maxSubSteps,默认值为10。
-
- 但P2本身不具备渲染功能,无法显示模拟结果,需要借助JavaScript渲染引擎,如Egret、Cocos2d-js、Pixi、phaser等,通过绘制或贴图来渲染物理模拟结果。在Egret中的简单示例:
class SampleP2APP extends egret.DisplayObjectContainer{
public constructor(){
super();
this.createP2App();
}
private world:p2.World;
private factor:number=30;
public createP2App():void{
// 创建了一个重力加速度gravity=[0,0]的失重环境world;
this.world=new p2.World();
var world=this.world;
world.gracity=[0,0];
// 使用Box形状创建尺寸100x50像素矩形;
var shape:p2.Box=new p2.Box({width:100/this.factor, height:50/this.factor});
var body:p2.Body=new p2.Body({mass:1});
// 通过addShape()方法将其添加到位于(275,100)位置的刚体body中;
body.position=[275/this.factor, 100/this.factor];
body.addShape(shape);
// 通过world的addBody()方法将刚体添加到世界中,完成一个基本的P2物理应用创建。
world.addBody(body);
this.addEventListener(egret.Event.ENTER_FRAME, this.loop, this);
}
// 在游戏的loop更新方法中,每帧持续调用step()方法,实现P2物理模拟计算的持续更新。
private loop(e.egret.Event):void{
this.world.step(1/60);
}
}
// 代码中创建了一个重力加速度gravity=[0,0]的失重环境world;
// 然后使用Box形状创建尺寸100x50像素矩形;
// 通过addShape()方法将其添加到位于(275,100)位置的刚体body中;
// 最后通过world的addBody()方法将刚体添加到世界中,完成一个基本的P2物理应用创建。在游戏的loop更新方法中,每帧持续调用step()方法,实现P2物理模拟计算的持续更新。
// P2物理引擎中的坐标单位是米,而大部分的游戏引擎在屏幕上渲染游戏时,都是基于像素的,所以在创建刚体对象、设置形状尺寸时,需要将像素转换成米后再进行赋值。游戏中,1米通常看作30px,所以代码中声明了一个值为30的factor变量,在设置形状尺寸或刚体时,都是使用像素坐标除以factor变量,转换成米之后再赋值的。
本文整理自: http://www.dwenzhao.cn/profession/netbuild/egretp2.html