前几个月,公司做了下"合成大西瓜" . 现在整理一下 P2的参数传递 , 碰撞检测 和 坐标转换
二, APIⅠ, 传递参数
在p2.Body实例对象上,加一个自定义的field,如: UserData. 如下
Ⅱ, 碰撞检测
Ⅲ, 坐标转换 p2.Body的实例对象 toWorldFrame( out Array
三, 核心代码
import {GameUtils} from "../cn/GameUtils"; /** * 小型的P2物理演示 * @author Aonaufly */ export class DemoP2 extends egret.DisplayObjectContainer{ private world: p2.World; private body: p2.Body; private planeBox: p2.Body;//地板刚体 private factor: number = 30; private debugDraw: p2DebugDraw; private display: egret.Bitmap;//用于刚体显示 private targetMap: egret.Bitmap; public constructor() { super(); } public start(): void{ //创建p2物理世界world this.world = new p2.World(); this.world.gravity = [0,10]; //添加一个地板 this.createPlane(); //创建矩形形状shape let shape: p2.Box = new p2.Box({ width: 275/this.factor, height: 100/this.factor }); //创建刚体 this.body = new p2.Body({ mass: 1} );//给出刚体的质量为1 this.body["userData"] = "hello p2";//需要传递的参数 this.body.position = [275/this.factor,100/this.factor]; //#region 添加贴图 this.body.displays = [ this.getDisplay(`b1`) ]; if( !this.display.parent ){ this.addChild( this.display ); } //#endregion this.body.addShape( shape );//加入形状 this.world.addBody( this.body );//加入刚体 //添加p2调试试图 let sprite: egret.Sprite = new egret.Sprite(); this.addChild( sprite ); this.debugDraw = new p2DebugDraw( this.world,sprite );//调试初始化 this.addEvent(); //体检游戏帧事件 this.addEventListener( egret.Event.ENTER_FRAME , this.loop, this ); } private getDisplay( key: string): egret.Bitmap{ let texture: egret.Texture = RES.getRes(`${key}_png`); if( !this.display ){ this.display = new egret.Bitmap( texture ); this.display.anchorOffsetX = texture.textureWidth >>1; this.display.anchorOffsetY = texture.textureHeight >>1; }else{ if( this.display.texture != texture ) this.display.texture = texture; } return this.display; } //生成挡板 private createPlane(): void{ //创建1个形状 let planeShape: p2.Box = new p2.Box( { width: GameUtils.instance.stage.stageWidth/this.factor, height: 100/this.factor } ); //创建刚体 this.planeBox = new p2.Body({ //刚体的类型 type: p2.Body.STATIC, //刚体的位置 position: [GameUtils.instance.stage.stageWidth/this.factor/2,(GameUtils.instance.stage.stageHeight - 100/2)/this.factor] }); // this.planeBox.angle = 0.1; this.planeBox.displays = []; this.planeBox.addShape( planeShape ); this.world.addBody( this.planeBox ); } //#region 碰撞事件处理 private addEvent(): void{ this.world.on( "postBroadPhaseEvent" , this.onPostBroadPhaseEvent , this);//当2个刚体的AABB发生重叠时,不断地派发postBroadPhase事件 this.world.on( "preSolveEvent" , this.onPreSolveEvent , this);//当2个刚体的形状发生重叠时 this.world.on( "beginContact" , this.onBeginContact , this);//当2个刚体形状发生重叠时会派发beinContact事件 this.world.on( "endContact" , this.onEndContact , this);//当2个刚体分离不再重叠时派发endContract } private removeEvent( ): void{ this.world.off( "postBroadPhaseEvent" , this.onPostBroadPhaseEvent );//当2个刚体的AABB发生重叠时,不断地派发postBroadPhase事件 this.world.off( "preSolveEvent" , this.onPreSolveEvent );//当2个刚体的形状发生重叠时 this.world.off( "beginContact" , this.onBeginContact );//当2个刚体形状发生重叠时会派发beinContact事件 this.world.off( "endContact" , this.onEndContact );//当2个刚体分离不再重叠时派发endContract } private onPostBroadPhaseEvent( e: any ): void{ console.log( e ); } private onPreSolveEvent( e:any ): void{ console.log( e ); } private onBeginContact( e:any ): void{ console.log( e ); let worldPo: Array = []; e.bodyB.toWorldFrame( worldPo, [ 0,0] ); this.showTarget( { x: worldPo[0] , y: worldPo[1] } ); } private onEndContact( e: any ): void{ console.log( e ); } //#endregion private showTarget : ( po: {x: number,y:number} ) => void = ( po ) => { if( !this.targetMap ){ let texture: egret.Texture = RES.getRes( `target` ); this.targetMap = new egret.Bitmap( texture); this.targetMap.anchorOffsetX = texture.textureWidth >>1; this.targetMap.anchorOffsetY = texture.textureHeight >>1; this.targetMap.scaleX = this.targetMap.scaleY = 0.2; this.addChild( this.targetMap ); } console.log( `type x: ${po.x} y: ${po.y}` ); this.targetMap.x = po.x * this.factor; this.targetMap.y = po.y * this.factor; } private loop( e: egret.Event ): void{ this.world.step( 1/60,0,10 ); // this.display.x = this.body.position[0] * this.factor; //同步刚体和egret显示对象的位置和旋转角度 // this.display.y = this.body.position[1] * this.factor; // this.display.rotation = this.body.angle * 180 / Math.PI; let texture: egret.DisplayObject; if( this.world.bodies !=null && this.world.bodies.length > 0 ){ this.world.bodies.forEach( ( itemBody ) => { if( itemBody.type != p2.Body.STATIC){ if( itemBody.displays && itemBody.displays.length > 0 ){ texture = itemBody.displays[0]; texture.x = itemBody.position[0] * this.factor; texture.y = itemBody.position[1] * this.factor; texture.rotation = itemBody.angle * 180 / Math.PI; } console.log( `参数 : ${ itemBody["userData"] }` ); }else{ console.log("static body"); } } ); } this.debugDraw.drawDebug();//绘制调试区域 } }四, 代码