Nape中的DistanceJoint——距离关节
前面我们学习了PivotJoint关节和WeldJoint关节,今天要学习的是DistanceJoint关节,即”距离关节”。但是Nape中的距离关机与Box2D稍有不同,我们可以通过jointMin和jointMax参数,设置关节的最短距离和最长距离。
实际上,这个关节效果在游戏中应用的并不是很多,至少我是没怎么见到过。但这并不代表它没用,充分发挥我们的想象力,说不定下一个游戏中就会用得到。
首先我来看一下DistanceJoint关节的构造函数:
public function DistanceJoint( body1:Body, body2:Body, anchor1:Vec2, anchor2:Vec2, jointMin:Number, jointMax:Number):void
与PivotJoint关节类似,DistanceJoint同样连接了两个刚体,有两个节点anchor1和anchor2。不过连接刚体的控制节点同样也有两个,这一点与PivotJoint关节不同。正如Nape Mannual里所示:
同样anchor1和anchor2也是相对于刚体本地坐标的。我们可以先定义好全局的控制节点坐标(即我们看到的在舞台上的坐标位置),然后再通过body.worldPointToLocal转换成刚体本地坐标。
另外就是参数jointMin和jointMax,DistanceJoint关节中限制刚体移动的范围。下图红红色线条表示jointMin,蓝色线条表示jointMax,这样两个刚体只能在图中红色区域内移动。而Box2D中的距离关节只是jointMin=jointMax时的情况。
另外在初始化jointMin和jointMax的时候要注意,jointMin要小于jointMax, jointMax要大于两个刚体初始的距离。好了,接下来我们来看一下示例把。
在下面的SWF中,有两个圆形刚体,小圆是动态刚体,大圆是sensor刚体。在大圆内点击鼠标创建矩形刚体,如果刚体处在上面的sensor刚体中,则会自动创建一个jointMin=0, jointMax=150的距离关节。如果是在下面的sensor刚体中,则会创建一个jointMin=50, jointMax=150的距离关节。试试看吧!
[swfobject]845[/swfobject]
完整的代码和注释如下:
package learnNape { import ldEasyNape.LDEasyUserData; import nape.callbacks.InteractionCallback; import nape.callbacks.CbType; import nape.callbacks.InteractionType; import nape.callbacks.CbEvent; import nape.callbacks.InteractionListener; import nape.shape.Circle; import flash.events.MouseEvent; import flash.events.Event; import nape.geom.Vec2; import nape.constraint.DistanceJoint; import ldEasyNape.LDEasyNape; import nape.phys.Body; import learnNape.AbstractNapeTest; /** * @author yangfei */ [SWF( width="400", height="500", frameRate="60")] public class T16_DistanceJoint extends AbstractNapeTest { //定义关节所需的变量 private var anchorBody1 : Body; private var anchorBody2 : Body; private var joint1 : DistanceJoint; private var joint2 : DistanceJoint; //定义sensor刚体所需的内容 private var sensorListener : InteractionListener; private var sensorShape : Circle; private var sensorType : CbType; private var bodyType : CbType; //定义贴图 private var graphic : LDEasyUserData; public function T16_DistanceJoint() { super(600); } override protected function onNapeWorldReady() : void { graphic = new LDEasyUserData(); graphic.setGraphicAuotmatically(0); //定义sensor图形,侦听鼠标点击产生的刚体,是否在感应区域内 sensorShape = new Circle(110); sensorShape.sensorEnabled = true; //senor刚体的类型,在碰撞处理函数中使用 sensorType = new CbType(); //鼠标点击时创建的刚体类型 bodyType = new CbType(); //创建上下两个圆形刚体,并添加一个大的sensor图形 anchorBody1 = LDEasyNape.createCircle(200, 100, 10, false, true, graphic); anchorBody1.shapes.add(sensorShape); anchorBody1.cbTypes.add(sensorType); anchorBody2 = LDEasyNape.createCircle(200, 350, 10, false, true, graphic); anchorBody2.shapes.add(sensorShape.copy()); anchorBody2.cbTypes.add(sensorType); //先创建好两个关节,这和PivotJoint差不多,设置active为FALSE,不进行物理模拟 joint1 = new DistanceJoint(anchorBody1, null, Vec2.weak(),Vec2.weak(),0, 110); joint1.active=false; joint1.space = napeWorld; joint2 = new DistanceJoint(anchorBody2, null, Vec2.weak(),Vec2.weak(),50, 110); joint2.active=false; joint2.space = napeWorld; //添加碰撞事件侦听,具体碰撞教程请参考我的文章 //http://www.ladeng6666.com/blog/2013/02/20/handling-nape-collision/ sensorListener = new InteractionListener(CbEvent.BEGIN, InteractionType.SENSOR, sensorType, bodyType, sensorHanlder); napeWorld.listeners.add(sensorListener); } private function sensorHanlder(cb:InteractionCallback):void{ var body1 : Body = cb.int1.castBody; var body2 : Body = cb.int2.castBody; //如果刚体已与anchor刚体连接,则返回 if(body2.constraints.length>0) return; //上面的anchor刚体 if(body1.position.y < 200){ //更新第2个刚体引用,变更后,原刚体会自动解除与anchor刚体的关节,自由下落 joint1.body2 = body2; //激活关节 joint1.active = true; //下面的anchor刚体 }else{ joint2.body2 = body2; joint2.active = true; } } override protected function loop(event : Event) : void { super.loop(event); napeWorld.liveBodies.foreach(function (b:Body):void{ //刚体超出舞台时,删除该刚体 if(b.position.y> stage.stageHeight+50){ napeWorld.liveBodies.remove(b); } }); } override protected function mouseEventHanlder(event : MouseEvent) : void { super.mouseEventHanlder(event); //在鼠标点击位置创建矩形刚体 if(event.type == MouseEvent.MOUSE_DOWN){ if(LDEasyNape.getBodyAtMouse()==null || !LDEasyNape.getBodyAtMouse().cbTypes.has(bodyType)){ graphic.setGraphicAuotmatically(0xff0000); var body : Body = LDEasyNape.createBox(mouseX,mouseY, 30, 30, false, false, graphic); body.cbTypes.add(bodyType); } } } } }
点击下载源文件
联系作者
猛一看还以为cad制图呢
是物理运动模拟啦!可以进行鼠标交互的,点点试试~