实际效果(蛋疼这个gif制作软件,帧率太低....):
一 Egret和P2的坐标系
首先了解下P2和Egret的坐标系。
某人链接:http://blog.csdn.net/qilei2010/article/details/51925754
关于p2和Egret的单位换算,我看论坛拉登的demo没写这个factor,我也就没写了,不知后面会发生什么事情呢...= =!
二 创建物理世界
啥是物理世界? p2的刚体碰撞、重力、浮力等物理运算都在这个"世界"进行。
注意这里重力是10,如果是地球上,应该是朝地面,是-10才对。为啥这里是10,后面会讲。
this.world = new p2.World();
this.world.sleepMode = p2.World.BODY_SLEEPING; //刚体睡眠,貌似是不动的时候,不用参与物理运算??
this.world.gravity = [0,10];
三 创建一个地板
Plane相当于地面,默认面向Y轴方向。
因为这个Y轴是P2的Y轴,而不是Egret的Y轴。P2和Egret的Y轴是相反的。所以将地面翻转180度。planeBody.angle = Math.PI
我们来看看不旋转会怎么样?
红色方块位置 = [100,100]
棕色地面位置 = [stage.stageWidth/2, stage.stageHeight - 100]
不旋转180度时的情况:
在Egret中视觉上是正常的,但是地面朝下。
在P2中,方块在地面下了,会运行不正常,方块像吃了药,飞速往下掉。
如果想P2中正常,得将地面和方块位置替换,那么在Egret中会显示地面在上,方块在下,这显然不是我们想要的。
旋转180度后:
Egret中视觉上和地面方向都正常了。
P2中地面朝下了,这时物理世界的重力得从-10改为10。
翻转后的结果就是,P2和Egret是反的,那么将地面反转,反反得正... (其实我也很晕...)
var plane:p2.Plane = new p2.Plane();
this.planeBody = new p2.Body({position:[GameConst.stage.stageWidth/2, GameConst.stage.stageHeight - 100]});
this.planeBody.angle = Math.PI;
this.planeBody.addShape(plane);
this.world.addBody(this.planeBody);
this.plane = this.createPlane();
this.planeBody.displays = [this.plane];
四 创建一个自由落体方块
var box:p2.Box = new p2.Box({50, height:50}); //1. 创建一个Box
this.boxBody = new p2.Body({mass:10, angularVelocity:1, position:[100,100]}); //2. 创建一个刚体,赋予Box物理特性
this.boxBody.addShape(box);
this.world.addBody(this.boxBody);
this.ball = this.createBox();
this.boxBody.displays = [this.ball]; //3. 给Box绑一个在Egret中的显示对象
this.addChild(this.ball);
五 更新物理世界
物理世界step()不停的在进行物理运算, Egret对象就像是物理世界的影子,每帧将对象和物理世界对象同步。
private onEnterFrame(){
this.world.step(60/1000); //1. 60ms/1000 = 0.06秒更新一次
var len:number = this.world.bodies.length;
for(var i: number = 0;i < len;i++) { //2. 同步物理世界对象和Egret显示对象的位置和角度
var body: p2.Body = this.world.bodies[i];
var display: egret.DisplayObject = body.displays[0];
display.x = body.position[0];
display.y = body.position[1];
display.rotation = body.angle * 180 / Math.PI; //弧度和角度互换
}
}
六 所有代码
/**
* 创建一个方块,自由落体
*
* 1. 世界,矩形,地板的使用
*
* @author chenkai
* @since 2017/6/23
*/
class Box extends egret.Sprite{
private world:p2.World;
private boxBody:p2.Body;
private planeBody:p2.Body;
private ball:egret.Sprite;
private plane:egret.Sprite;
public constructor() {
super();
//创建world
this.world = new p2.World();
this.world.sleepMode = p2.World.BODY_SLEEPING;
this.world.gravity = [0,10];
//创建box
var box:p2.Box = new p2.Box({50, height:50});
this.boxBody = new p2.Body({mass:10, angularVelocity:1, position:[100,100]});
this.boxBody.addShape(box);
this.world.addBody(this.boxBody);
this.ball = this.createBox();
this.boxBody.displays = [this.ball];
this.addChild(this.ball);
//创建plane Plane shape class. The plane is facing in the Y direction.
var plane:p2.Plane = new p2.Plane();
this.planeBody = new p2.Body({position:[GameConst.stage.stageWidth/2, GameConst.stage.stageHeight - 100]}); //GameConst.stage保存全局静态变量stage
this.planeBody.angle = Math.PI;
this.planeBody.addShape(plane);
this.world.addBody(this.planeBody);
this.plane = this.createPlane();
this.planeBody.displays = [this.plane];
//每帧更新
this.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
}
private onEnterFrame(){
//更新物理世界
this.world.step(60/1000);
var len:number = this.world.bodies.length;
for(var i: number = 0;i < len;i++) {
var body: p2.Body = this.world.bodies[i];
var display: egret.DisplayObject = body.displays[0];
display.x = body.position[0]; //同步刚体和egret显示对象的位置和旋转角度
display.y = body.position[1];
display.rotation = body.angle * 180 / Math.PI;
}
}
private createBox(){
var sp:egret.Sprite = new egret.Sprite();
sp.graphics.beginFill(0xff0000);
sp.graphics.drawRect(0,0,50,50);
sp.graphics.endFill();
sp.anchorOffsetX = sp.width/2;
sp.anchorOffsetY = sp.height/2;
return sp;
}
private createPlane(){
var sp:egret.Sprite = new egret.Sprite();
sp.graphics.lineStyle(10, 0x00ff00);
sp.graphics.moveTo(0, 0);
sp.graphics.lineTo(GameConst.stage.stageWidth,0);
sp.anchorOffsetX = sp.width/2;
sp.anchorOffsetY = sp.height/2;
this.addChild(sp);
return sp;
}
}