Egret之P2物理引擎(测试)

一 : 前景

    前几个月,公司做了下"合成大西瓜" . 现在整理一下 P2的参数传递 , 碰撞检测 和 坐标转换

二, API

        Ⅰ, 传递参数

             在p2.Body实例对象上,加一个自定义的field,如: UserData. 如下

Egret之P2物理引擎(测试)

        Ⅱ, 碰撞检测

            Egret之P2物理引擎(测试)

        Ⅲ, 坐标转换  p2.Body的实例对象 toWorldFrame( out Array

            Egret之P2物理引擎(测试)

三, 核心代码
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();//绘制调试区域
    }
}
四, 代码

Egret之P2物理引擎(测试)

上一篇:R语言基于Bootstrap的线性回归预测置信区间估计方法


下一篇:java.net.SocketException: Software caused connection abort: socket write error