Nape中的LineJoint-线段关节

今天要学习的内容时LineJoint线段关节,通过线段关节,我们可以限制刚体在某个指定的方向上来回移动。就像算珠只能在算盘的轴上移动一样。

老规矩,我们先来看一下LineJoint的构造函数:

public function LineJoint(
	body1:Body,
	body2:Body,
	anchor1:Vec2,
	anchor2:Vec2,
	direction:Vec2,
	jointMin:Number,
	jointMax:Number):void

每个参数的作用说明如下:

  • body1:和其他的关节一下,关节连接的第1个刚体
  • body2:和其他的关节一下,关节连接的第2个刚体
  • anchor1:连接刚体body1的节点,其坐标是相对于body1的本地坐标的
  • anchor2:连接刚体body2的节点,其坐标是相对于body2的本地坐标的
  • direction:线段关节中线条的方法,用一个Vec2向量表示
  • jointMin:线段上沿direction方法,距离anchor1的距离
  • jointMax:线段沿上direction方向,距离anchor2的距离

看完构造函数和参数说明,依然有些不知其解,看看下面的图示会更简单些:

lineJoint_desc

如图所示,anchor1和anchor2是线段关节中的两个点,两点形成的线段即线段关节。线段关节的方向可以用anchor1.sub(anchor2)表示。线段起点与anchor1的距离是JointMin,终点与anchor1的距离是jonitMax;jointMin/jointMax小于0,在anchor1左侧,大于0在anchor1右侧。值得注意的是,body1可不能绕着anchor1旋转,而body2可以绕着anchor2旋转。

还记得distanceJoint示例吗?如果把示例中的刚体限制在水平方向移动,会是什么样子呢?下面的示例中,点击圆形刚体,可以在水平方向拖动,它通过一个distanceJoint关节与下面的矩形刚体连接。按下空格键”剪断”这个distanceJoint关节,让矩形落到下面的圆形范围内。有没有《割绳子》游戏里的样子呢?赶快动手试试吧!

[swfobject]852[/swfobject]

完整的代码和注释如下:

package learnNape {
	import ldEasyNape.LDEasyUserData;
	import com.bit101.components.PushButton;
	import nape.callbacks.InteractionCallback;
	import nape.callbacks.InteractionType;
	import nape.callbacks.CbEvent;
	import nape.callbacks.InteractionListener;
	import nape.callbacks.CbType;
	import flash.ui.Keyboard;
	import flash.events.KeyboardEvent;
	import nape.constraint.DistanceJoint;
	import nape.shape.Circle;
	import flash.events.MouseEvent;
	import nape.constraint.LineJoint;
	import ldEasyNape.LDEasyNape;
	import nape.phys.Body;
	import nape.geom.Vec2;
	import learnNape.AbstractNapeTest;

	/**
	 * @author yangfei
	 */
	[SWF( width="400", height="500", frameRate="60")]
	public class T19_LineJoint extends AbstractNapeTest {

		private var anchorX1 : Number = 100;
		private var anchorX2 : Number = 300;
		private var anchorY1 : Number = 100;
		private var anchorY2 : Number = 300;

		private var anchorBody1 : Body;
		private var anchorBody2 : Body;

		private var joint1 : LineJoint;
		private var joint2 : LineJoint;
		private var distanceJoint : DistanceJoint;

		private var box : Body;
		private var sensorType : CbType;
		private var boxType : CbType;
		private var graphic : LDEasyUserData;

		public function T19_LineJoint() {
			super();
		}

		override protected function onNapeWorldReady() : void {
			createStuff();
			var sensorListener : InteractionListener = new InteractionListener(CbEvent.BEGIN, InteractionType.SENSOR, sensorType, boxType, onCollision);
			napeWorld.listeners.add(sensorListener);

			new PushButton(this, 280, 15, "reStart",function (e:MouseEvent):void{
				box.position.setxy(anchorBody1.position.x+10, anchorY1-50);
				distanceJoint.body1= anchorBody1;
				distanceJoint.body2 = box;
				distanceJoint.active = true;
			});

		}
		private function createStuff():void{
			var sensorShape : Circle = new Circle(50);
			sensorShape.sensorEnabled = true;
			sensorType = new CbType();

			graphic = new LDEasyUserData();
			graphic.setGraphicAuotmatically(0);

			//创建上面的圆形刚体
			anchorBody1 = LDEasyNape.createCircle(anchorX1, anchorY1, 10, false, false, graphic);
			anchorBody1.shapes.add(sensorShape);
			anchorBody1.cbTypes.add(sensorType);
			//用线段关节限制anchorBody1只能在水平方向移动
			var anchorStart1 : Vec2 = new Vec2(anchorX1, anchorY1);
			var anchorEnd1 : Vec2 = new Vec2(anchorX2, anchorY1);
			var direction1 : Vec2 = anchorEnd1.sub(anchorStart1);
			joint1 = new LineJoint(napeWorld.world, anchorBody1, anchorStart1, Vec2.weak(), direction1, 0, direction1.length);
			joint1.space = napeWorld;

			//创建下面的刚体
			anchorBody2 = LDEasyNape.createCircle(anchorX2, anchorY2, 10, false, false, graphic.clone());
			anchorBody2.shapes.add(sensorShape.copy());
			anchorBody2.cbTypes.add(sensorType);
			//用线段关节限制anchorBody1只能在水平方向移动
			var anchorStart2 : Vec2 = new Vec2(anchorX1, anchorY2);
			var anchorEnd2 : Vec2 = new Vec2(anchorX2, anchorY2);
			var direction2 : Vec2 = anchorEnd2.sub(anchorStart2);
			joint2 = new LineJoint(napeWorld.world, anchorBody2, anchorStart2, Vec2.weak(), direction2, 0, direction2.length);
			joint2.space = napeWorld;

			graphic.setGraphicAuotmatically(0xFF0000,1);
			box = LDEasyNape.createBox(anchorX1+10, anchorY1-50, 30, 30, false, false, graphic.clone());
			boxType = new CbType();
			box.cbTypes.add(boxType);
			//创建距离关节,连接矩形和圆形
			distanceJoint  = new DistanceJoint(anchorBody1, box, Vec2.weak(), Vec2.weak(), 0, 100);
			distanceJoint.space = napeWorld;
		}
		private function onCollision(cb: InteractionCallback):void{
			var anchorBody : Body = cb.int1.castBody;
			if(!anchorBody.constraints.has(distanceJoint)){
				distanceJoint.body1 = anchorBody;
				distanceJoint.body2 = box;
				distanceJoint.active = true;
			}
		}
		override protected function mouseEventHanlder(event : MouseEvent) : void {
			if(event.type == MouseEvent.MOUSE_DOWN){
				if(LDEasyNape.getBodyAtMouse()!=null ){
					if(LDEasyNape.getBodyAtMouse().shapes.length<=1) return;
				}
			}
			super.mouseEventHanlder(event);

		}

		override protected function keyBoardEventHanlder(event : KeyboardEvent) : void {

			if(event.type != KeyboardEvent.KEY_DOWN) return;
			if(event.keyCode == Keyboard.SPACE){
				if(box.constraints.length>0){
					box.constraints.at(0).active = false;
				}
			}
		}

	}
}

点击下载源文件

 

联系作者

公众号:拉小登 | 微博:拉登Dony | B站:拉小登Excel

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注