Layabox 实现画 刚体线

Layabox 的刚体里面只有一个b2PolygonShape,而为了实现画刚体线,我们需要用到复合Shape,也就是多个Shape组成一个刚体。

此时如果用Layabox自带的Collider就实现不了,所以我们需要继承ColliderBase来实现复合体,下面是代码

package
{
    import laya.physics.ColliderBase;
    import laya.physics.Physics;
    import laya.maths.MathUtil;

    public class RectLineCollider extends ColliderBase
    {
        private var _lineWidth:Number = 5;
        public function set lineWidth(val:Number):void{
            _lineWidth = val;
        }

        private var _fixtures:Array = [];

        public function setPoints(points:Array,re:Boolean = true ):void
        {
            if(points==null || points.length<4) return;

            _shape = [];
            var _x:Number = 0;
            var _y:Number = 0;
            var len:int = points.length;
            
            for (var i:int = 2; i < len-1; i+=2) {
                var x1:Number = points[i-2];
                var y1:Number = points[i-1];
                var x2:Number = points[i];
                var y2:Number = points[i+1];
                var cx:Number = (x1+x2)*0.5;
                var cy:Number = (y1+y2)*0.5;
                
                var dx:Number = x1-x2;
                var dy:Number = y1-y2;
                var linelen:Number = Math.sqrt(dx*dx+dy*dy);

                var angle:Number = Math.atan2(y2 - y1, x2 - x1)- Math.PI*0.5;

                var s:* = new window.box2d.b2PolygonShape();
                s.SetAsBox(_lineWidth/2/Physics.PIXEL_RATIO,linelen/2/Physics.PIXEL_RATIO, new window.box2d.b2Vec2(cx / Physics.PIXEL_RATIO, cy / Physics.PIXEL_RATIO), angle);
                _shape.push(s);
            }

			if (re) refresh();
        }

        public override function refresh():void {
			if (enabled && rigidBody) {
				var body:* = rigidBody.body;
				
                if (_fixtures.length>0) {
                    for(var j:int = 0 ;j<_fixtures.length;++j){
                        if (_fixtures[j].GetBody() == rigidBody.body) {
                            rigidBody.body.DestroyFixture(_fixtures[j]);
                        }
                        _fixtures[j].Destroy();
                    }
					_fixtures.length = 0;
				}

                for(var i:int = 0 ;i<_shape.length;++i){
                    var def:* = new window.box2d.b2FixtureDef();
                    def.density = density;
                    def.friction = friction;
                    def.isSensor = isSensor;
                    def.restitution = restitution;
                    def.shape = _shape[i];
                    def.filter.groupIndex = rigidBody.group;
                    def.filter.categoryBits = rigidBody.category;
                    def.filter.maskBits = rigidBody.mask;
                    fixture = body.CreateFixture(def);
                    fixture.collider = this;
                }
			}
		}


        override protected function _onDestroy():void {
			if (rigidBody) {
				if (_fixtures.length>0) {
                    for(var i:int = 0 ;i<_fixtures.length;++i){
                        if (_fixtures[i].GetBody() == rigidBody.body) {
                            rigidBody.body.DestroyFixture(_fixtures[i]);
                        }
                    }
					_fixtures.length = 0;
				}
				rigidBody = null;
				_shape = null;
			}
		}
    }   
}

场景的需要启用物理引擎

Physics.enable({gravity:50000});

PhysicsDebugDraw.enable();

并且在画线的时候,还不能和其他对象穿插,也就是线不能画到其他刚体里面,所以需要射线判断。

private function addLine():void{
	var isDown:Boolean = false;
	var prevX:Number = 0;
	var prevY:Number = 0;
	var line:Sprite = null;
	var points:Array = null;
	var color:String = "#ff0000";
	var lineSize:Number = 5;
	Laya.stage.on(Event.MOUSE_DOWN,this,function(e:Event):void{
		if(isDown) return;
		isDown = true;
		prevX = Laya.stage.mouseX;
		prevY = Laya.stage.mouseY;
		if(points==null) points = [];
		points.push(prevX,prevY);

		line = new Sprite();
		line.mouseEnabled = false;
		Laya.stage.addChild(line);
	});

	Laya.stage.on(Event.MOUSE_MOVE,this,function(e:Event):void{
		if(isDown && line && distance(Laya.stage.mouseX,Laya.stage.mouseY,prevX,prevY)>10)
		{
			//ray check
			var rayHit:Object = new Object();
			if(!rayCast(prevX,prevY,Laya.stage.mouseX,Laya.stage.mouseY,rayHit))
			{
				line.graphics.drawLine(prevX,prevY,Laya.stage.mouseX,Laya.stage.mouseY,color,lineSize);
				prevX = Laya.stage.mouseX;
				prevY = Laya.stage.mouseY;
				points.push(prevX,prevY);
			}
		}
	});

	Laya.stage.on(Event.MOUSE_UP,this,function(e:Event):void{
		if(isDown && points!=null && points.length>3){
			isDown = false;
			var col:RectLineCollider = line.addComponent(RectLineCollider);
			col.setPoints(points)
			var rb:RigidBody = line.addComponent(RigidBody);
			rb.allowRotation = true;

		}else if(line!=null){
			line.destroy();
			line = null;
		}
		points = null;
	});
}

private function rayCast(startX:Number,startY:Number,endX:Number,endY:Number,outHitInfo:Object):Boolean{
	var world:*= Physics.I.world;
	var result:int = 0;
	world.RayCast(function(fixture,point,normal,fraction):int{
		outHitInfo.fixture = fixture;
		outHitInfo.point = point;
		outHitInfo.normal = normal;
		outHitInfo.fraction = fraction;
		result = 1;
		return 0;//只检测一个
	},{
		x:startX/Physics.PIXEL_RATIO,
		y:startY/Physics.PIXEL_RATIO
	},{
		x:endX/Physics.PIXEL_RATIO,
		y:endY/Physics.PIXEL_RATIO
	});
	return result;
}

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值