Box2D 实现不倒翁效果 绘制扇形

效果图

/*
* name;
*/
class SetMassData extends ui.ApplyForeeTestUI{
    constructor(){
        super();
        this.createRect();
        this.createBody();
        this.on(Laya.Event.CLICK,this,this.onClick);
        Laya.timer.frameLoop(1,this,this.update);
    }

    private body:b2Body;
    private centerSprite:Laya.Sprite;

    private createRect():void
    {
        Physics.Instance.createb2Body_rectangle(this.width-10,640,20,Laya.stage.height,0,b2Body.b2_kinematicBody);
        Physics.Instance.createb2Body_rectangle(10,640,20,Laya.stage.height,0,b2Body.b2_kinematicBody);
        Physics.Instance.createb2Body_rectangle(360,10,Laya.stage.width,20,0,b2Body.b2_kinematicBody);
        Physics.Instance.createb2Body_rectangle(360,this.height - 10,Laya.stage.width,20,0,b2Body.b2_kinematicBody);

    }

    private createBody():void
    {
        let bodyDef:b2BodyDef = new b2BodyDef();
        bodyDef.type = b2Body.b2_dynamicBody;
        bodyDef.position.Set(360/30,800/30);

        this.body = Physics.Instance._world.CreateBody(bodyDef);

        // 创建 半圆
        let semiCircle:b2PolygonShape = new b2PolygonShape();
        let r = 100/30;
        let angle = 0;
        let vertices = [];
        for(let i = 0;i < 21;i++)
        {
            angle = i * 9;
            // console.log(angle);
            let x = r * Math.cos(angle * Math.PI/180); 
            let y = r * Math.sin(angle * Math.PI/180);
            // console.log(x,y);
            vertices.push(b2Vec2.Make(x,y));
        }
        semiCircle.SetAsArray(vertices);

        // 创建三角形
        let triangle:b2PolygonShape = new b2PolygonShape();
        let t_verts = [];
        t_verts.push(b2Vec2.Make(r,0));
        t_verts.push(b2Vec2.Make(-r,0));
        t_verts.push(b2Vec2.Make(0,-r*3));
        triangle.SetAsVector(t_verts);

        this.body.CreateFixture2(semiCircle,1);
        this.body.CreateFixture2(triangle,1);

        // 设置重心
        let md:b2MassData = new b2MassData(); // 获取质量 和 旋转惯性属性对象
        this.body.GetMassData(md);
        md.center.Set(0,30/30);
        md.I = md.mass * md.center.LengthSquared() + 200;    // 设置惯性为200
        this.body.SetMassData(md);

        // 画出中心点
        this.centerSprite = new Laya.Sprite();
        let center = this.body.GetWorldPoint(b2Vec2.Make(md.center.x,md.center.y));
        this.centerSprite.graphics.drawCircle(center.x * 30,center.y * 30,10,"#ffffff");
        this.addChild(this.centerSprite);
    }

    private onClick():void
    {
        let impulse:b2Vec2 = new b2Vec2(this.body.GetMass(),0);  // this.body.GetMass()  返回刚体的质量
        if(Math.random()>0.5) impulse.x *= -1;
        this.body.ApplyImpulse(impulse,this.body.GetWorldPoint(b2Vec2.Make(0,-20/30)));  // this.body.GetWorldPoint(b2Vec2.Make(0,-20/30)  获取这个点的全局坐标
    }

    private update():void
    {
        // 更新重新点位置
        if(null != this.centerSprite)
            this.centerSprite.graphics.destroy();
            
        this.centerSprite = new Laya.Sprite();
        let center = this.body.GetWorldPoint(b2Vec2.Make(0,30/30));
        this.centerSprite.graphics.drawCircle(center.x * 30,center.y * 30,10,"#ffffff");
        this.addChild(this.centerSprite);
    }

}
/*
* name;
*/
import b2World = Box2D.Dynamics.b2World;
import b2BodyDef = Box2D.Dynamics.b2BodyDef;
import b2Body = Box2D.Dynamics.b2Body;
import b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape;
import b2CircleShape = Box2D.Collision.Shapes.b2CircleShape;
import b2MassData = Box2D.Collision.Shapes.b2MassData;
import b2FixtureDef = Box2D.Dynamics.b2FixtureDef;
import b2Vec2 = Box2D.Common.Math.b2Vec2;
import b2Math = Box2D.Common.Math.b2Math;

class Physics{
    
    private static instance:Physics = null;
    public static get Instance():Physics
    {
        if(null == this.instance)
        {
            this.instance = new Physics();
            this.Instance.init();
        }
        return this.instance;
    }

    public _world:b2World;

    private init():void
    {
        this.create2bWorld();
        this.b2DebugDraw();
        Laya.timer.frameLoop(1,this,this.update);
    }

    private update():void
    {
        this._world.Step(1/30,10,10);
        this._world.DrawDebugData();
    }

    // 创建物理世界
    public create2bWorld():void
    {
        let gravity:Box2D.Common.Math.b2Vec2 = new Box2D.Common.Math.b2Vec2(0,10);    // 重力 
        let doSleep:boolean = true;                                                   // 为 true 时 将静止的刚体标记为随眠状态,在遍历的时候直接跳过去,不进行运动模拟计算,提高了Box2D的计算效率,节省CPU 
        this._world = new b2World(gravity,doSleep);
    }

    // 2bDebugDraw 调试视图绘制
    private b2DebugDraw():void
    {
        // ----- Laya 绘制 --------
        var canvas = Laya.Browser.createElement('canvas');
        canvas.width = Laya.stage.width;
        canvas.height = Laya.stage.height;
        var ctx = canvas.getContext('2d');
        
        Laya.stage.graphics.clear(false);
        var textture = new Laya.Texture(canvas);
        textture.bitmap.alwaysChange = true;                //小游戏使用,非常费,每帧刷新
        Laya.stage.graphics.drawTexture(textture);

        // box2d 
        let debugDraw:Box2D.Dynamics.b2DebugDraw = new  Box2D.Dynamics.b2DebugDraw();
        debugDraw.SetSprite(ctx);
        debugDraw.SetDrawScale(30);
        debugDraw.SetFlags(Box2D.Dynamics.b2DebugDraw.e_shapeBit|Box2D.Dynamics.b2DebugDraw.e_jointBit);
        debugDraw.SetFillAlpha(0);                 // 设置内容线条的透明度
        debugDraw.SetLineThickness(1);             // 设置绘制内容线条的粗细
        this._world.SetDebugDraw(debugDraw);
    }

    // 创建一个 矩形刚体
    public createb2Body_rectangle(x:number,y:number,width:number,height:number,angle:number,type:number):b2Body
    {
        let bd:b2BodyDef = new b2BodyDef();              // b2BodyDef 是b2Body所有属性的一个集合,作用:在刚体创建前,收集所有运动合状态相关属性,然后传入b2Body。
        // bd.type = b2Body.b2_dynamicBody;              // 设置为 动态刚体,受重力影响;动态物体可以进行全模拟
        // bd.type = b2Body.b2_staticBody;               // 设置为 静态
        // bd.type = b2Body.b2_kinematicBody;            // 设置为 为可动刚体,不受重力影响,可以通过施加速度或者力的方式使其运动
        bd.type = type;
        bd.position = new Box2D.Common.Math.b2Vec2(x/30,y/30);       //设置位置
        bd.angle = angle * Math.PI/180;

        let b2_rect:b2PolygonShape = new b2PolygonShape();       // 多边形对象
        b2_rect.SetAsBox(width/2/30,height/2/30);

        let fd:b2FixtureDef = new b2FixtureDef();         // b2FixtureDef 主要保存了刚体物质特性方面的属性,如形状shape,密度density,表面摩擦力friction,弹性系数restitution等等
        fd.shape = b2_rect;
        fd.filter.groupIndex = 1;

        let body:b2Body = this._world.CreateBody(bd);            // 刚体对象
        body.CreateFixture(fd);

        return body;
    }

    // 创建一个 圆形刚体
    public createb2Body_circle(x:number,y:number,radius:number,type:number):b2Body
    {
        let bd:b2BodyDef = new b2BodyDef();           // b2BodyDef 是b2Body所有属性的一个集合,作用:在刚体创建前,收集所有运动合状态相关属性,然后传入b2Body。
        // bd.type = b2Body.b2_dynamicBody;           // 设置为 动态
        // bd.type = b2Body.b2_staticBody;            // 设置为 静态
        bd.type = type;
        bd.position = new Box2D.Common.Math.b2Vec2(x/30,y/30);       //设置位置


        let circle:b2CircleShape = new b2CircleShape(radius/30);       // 多边形对象
        let fd:b2FixtureDef = new b2FixtureDef();         // b2FixtureDef 主要保存了刚体物质特性方面的属性,如形状shape,密度density,表面摩擦力friction,弹性系数restitution等等
        fd.shape = circle;
        fd.filter.groupIndex = 1;

        let body:b2Body = this._world.CreateBody(bd);            // 刚体对象
        body.CreateFixture(fd);

        return body;
    }

    private shapeMapList:Array<Array<number>>;
    private boxSize:number = 50;
    private counter:number = 0;

    // 
    private createAsOrientedBox():void
    {
        if(++this.counter > 50)
        {
            this.counter = 0;
            let index = Math.floor(Math.random()*this.shapeMapList.length);
            this.createBody(Math.random()*50+150,-50,this.shapeMapList[index]);
        }
    }

    private createShapeMap():void
    {
        let Z:Array<number> = [ 1,1,0,
                                0,1,1,
                                0,0,0];
        let S:Array<number> = [ 0,1,1,
                                1,1,0,
                                0,0,0];
        let L:Array<number> = [ 1,0,0,
                                1,0,0,
                                1,1,0];
        let L2:Array<number> = [ 0,1,0,
                                0,1,0,
                                1,1,0];
        let T:Array<number> = [ 1,1,1,
                                0,1,0,
                                0,0,0];
        let M:Array<number> = [ 1,1,1,
                                1,0,1,
                                0,0,0];
        let X:Array<number> = [ 0,1,0,
                                1,1,1,
                                0,1,0];
        let O:Array<number> = [ 1,1,0,
                                1,1,0,
                                0,0,0];
        this.shapeMapList = new Array<Array<number>>();
        this.shapeMapList.push(Z,T,L,M,X,O,S,L2);
    }

    private createBody(x:number,y:number,map:Array<number>):b2Body
    {
        let bodyDef:b2BodyDef = new b2BodyDef();
        bodyDef.type = b2Body.b2_dynamicBody;
        bodyDef.position = new b2Vec2(x/30,y/30);

        let fixtureDef:b2FixtureDef = new b2FixtureDef();
        fixtureDef.density = 1;           // 密度
        fixtureDef.restitution = 0;       // 弹性系数
        let body:b2Body = this._world.CreateBody(bodyDef);
        
        let bx:number;
        let by:number;
        let center:b2Vec2;
        let shape:b2PolygonShape;

        for (var i = 0; i < 3; i++)
        {
             for (var j = 0; j < 3; j++)
            {
                if(map[i*3+j] == 1)
                {
                    bx = j*this.boxSize;
                    by = i*this.boxSize;
                    center = new b2Vec2(bx/30,by/30);
                    shape = b2PolygonShape.AsOrientedBox(this.boxSize/30/2,this.boxSize/30/2,center);
                    fixtureDef.shape = shape;
                    body.CreateFixture(fixtureDef);
                }
            }
        }

        return body;
    } 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值