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;
}