zoukankan      html  css  js  c++  java
  • 自定义刚体与拖动

    调用b2PolygonDef的setAsBox函数传入一个半宽和半高,即可以创建一个矩形刚体,设置b2CircleDef的radius属性,即可以创建一个圆形的刚体,如果现在要创建一个五边形,六边形的刚体呢,box2d并没有提供这样的方法来创建。

    利用b2PolygonDef的两个属性vertexCount和vertices,可以创建自定义刚体。

    vertexCount:刚体的顶点数。
    vertices:一个数组,用来保存刚体的所有定点。

    package  
    {
    	import Box2D.Collision.Shapes.b2PolygonDef;
    	import Box2D.Common.Math.b2Vec2;
    	import Box2D.Dynamics.b2Body;
    	import Box2D.Dynamics.b2BodyDef;
    	import Box2D.Dynamics.b2DebugDraw;
    	import Box2D.Dynamics.b2World;
    	import Box2D.Dynamics.Joints.b2MouseJoint;
    	import Box2D.Dynamics.Joints.b2MouseJointDef;
    	import flash.display.Sprite;
    	import flash.events.Event;
    	import flash.events.MouseEvent;
    	import flash.geom.Point;
    	import myClass.box2d.PhyOption;
    	import myClass.box2d.Floor;
    	import myClass.box2d.Wall;
    	
    	/**
    	 * ...
    	 * @author ywxgod
    	 */
    	[SWF(backgroundColor="0x333333",frameRate="30")]
    	public class CustomBody extends Sprite
    	{
    		private var _world:b2World;
    		private var _mouseJoint:b2MouseJoint;
    		
    		public function CustomBody() 
    		{
    			if (stage) init();
    			else addEventListener(Event.ADDED_TO_STAGE, init);
    		}
    		
    		private function init(e:Event=null):void 
    		{
    			removeEventListener(Event.ADDED_TO_STAGE, init);
    			
    			_world = PhyOption.getInstance().world;
    			new Floor(new MyFloor(), this);
    			new Wall(new MyFloor(), this, Wall.LEFT);
    			new Wall(new MyFloor(), this,Wall.RIGHT);
    			
    			createBodies();
    			showDebug();
    			
    			addEventListener(Event.ENTER_FRAME, onFrame);
    			stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
    			stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
    		}
    		
    		private function setConvexVertex(shapeDef:b2PolygonDef,n:int,radius:Number):void 
    		{
    			shapeDef.vertexCount = n;
    			var angle:Number = Math.PI * 2 / n;
    			var radius:Number = radius / PhyOption.PHYSCALE;
    			for (var i:int = 0; i < n;i++ )
    			{
    				var dx:Number = radius * Math.cos(angle * i);
    				var dy:Number = radius * Math.sin(angle * i);
    				shapeDef.vertices[i].Set(dx,dy);
    			}
    			shapeDef.friction = 0.3;
    			shapeDef.restitution = 0.3;
    			shapeDef.density = 2;
    		}
    		
    		private function setRandomInt(a:int,b:int):int
    		{
    			return a + Math.floor(Math.random() * (b - a + 1));
    		}
    		
    		private function createBodies():void 
    		{
    			for (var i:int = 3; i <= 7;i++ )
    			{
    				var xpos:Number = 275 + setRandomInt( -20, 20);
    				var ypos:Number = 0;
    				var radius:Number = 30 + setRandomInt( -20, 20);
    				createBody(xpos,ypos,i,radius);
    			}
    			
    		}
    		
    		private function createBody(xpos:Number,ypos:Number,vertexCount:int,radius:Number):void
    		{
    			var boxShapeDef:b2PolygonDef = new b2PolygonDef();
    			setConvexVertex(boxShapeDef,vertexCount,radius);
    			var bodyDef:b2BodyDef = new b2BodyDef();
    			bodyDef.angle = Math.random() * 360;
    			bodyDef.position.Set(xpos/ PhyOption.PHYSCALE, ypos/PhyOption.PHYSCALE);
    			var body:b2Body = _world.CreateBody(bodyDef);
    			body.CreateShape(boxShapeDef);
    			body.SetMassFromShapes();
    		}
    		
    		private function showDebug():void 
    		{
    			var sp:Sprite = new Sprite();
    			this.addChild(sp);
    			var dbg:b2DebugDraw = new b2DebugDraw();
    			dbg.m_sprite = sp;
    			dbg.m_alpha = 0.5;
    			dbg.m_drawScale = PhyOption.PHYSCALE;
    			dbg.m_fillAlpha = 0.5;
    			dbg.m_drawFlags = b2DebugDraw.e_shapeBit;
    			dbg.m_lineThickness = 1;
    			_world.SetDebugDraw(dbg);
    		}
    		
    		private function onFrame(e:Event):void 
    		{
    			PhyOption.getInstance().update();
    			if (_mouseJoint)
    			{
    				_mouseJoint.SetTarget(new b2Vec2(stage.mouseX/PhyOption.PHYSCALE,stage.mouseY/PhyOption.PHYSCALE));
    			}
    		}
    		
    		private function onDown(e:MouseEvent):void 
    		{
    			var body:b2Body = PhyOption.getInstance().GetBodyAtMouse(this.stage);
    			if (body)
    			{
    				var mouseJointDef:b2MouseJointDef = new b2MouseJointDef();
    				mouseJointDef.body1 = _world.GetGroundBody();
    				mouseJointDef.body2 = body;
    				mouseJointDef.maxForce = 40000;
    				mouseJointDef.timeStep = PhyOption.STEP;
    				mouseJointDef.target.Set(stage.mouseX / PhyOption.PHYSCALE, stage.mouseY / PhyOption.PHYSCALE);
    				_mouseJoint = _world.CreateJoint(mouseJointDef) as b2MouseJoint;
    			}
    		}
    		
    		private function onUp(e:MouseEvent):void 
    		{
    			if (_mouseJoint)
    			{
    				_world.DestroyJoint(_mouseJoint);
    				_mouseJoint = null;
    			}
    		}
    		
    	}
    
    }

    39-42行:PhyOption,Floor,Wall都是自定义类,分别用来初始化b2world,创建地面,墙壁等。

    52-66行:函数setConvexVertex创建圆内切多边形,box2d中只对凸多边形起作用,凹多边形是box2d无法处理的。

    73-83行:创建3,4,5。。。7边形。奇怪的是,如果创建九边形,就会报错,即:循环i从3到8没问题,一旦循环到9就会报错:

          TypeError: Error #1010: 术语尚未定义,并且无任何属性。
           at CustomBody/setConvexVertex()
           at CustomBody/createBody()
           at CustomBody/createBodies()
           at CustomBody/init()
           at CustomBody()
    此处我用的flashDevelop创建的一个Flash IDE Project,用的是FlashCS4编译运行,不知道这个是不是一个bug呢?有遇到过此类问题的朋友还请不吝赐教。

    97-109行:显示box2d的debug模式。

    122行:寻找鼠标点击处的刚体。

    125-131行:创建一个mouseJoint,用来拖动刚体。创建mouseJoint跟刚体一样,先要创建mouseJointDef的各个参数。

          body1:值为_world.GetGroundBody(),_world.GetGroundBody()具体表示的是哪一个刚体,本人还未明白,看源代码注释不是很清楚,如果您明白还请不吝赐教啊!

          body2:鼠标点击处的刚体。

          maxForce:拖动刚体时铰链给刚体的最大力,box2d会根据这个力来计算刚体被拖动的最大速度及位移,使得刚体始终处于鼠标的控制之下,实际这里的拖动,并不像flash中拖动一个显示对象用startDrag()或者设置对象的坐标为鼠标的坐标,box2d中考虑了更多复杂的运动参数,有加速度,质量,动量,冲量等。

          timeStep:box2d模拟屋里世界的时间片,一般取swf文件帧频的倒数。

          target:目标位置,设置为鼠标位置。在EnterFrame事件中更新目标。

  • 相关阅读:
    软件开发沉思录读书笔记
    卓有成效的程序员读书笔记
    结对编程收获
    《提高c++性能的编程技术》读书笔记
    第六次读书笔记
    第五周读书笔记
    美团与它的超级大脑
    第四次读书笔记
    团队-团队编程项目爬取豆瓣电影top250-模块测试过程
    团队-爬取豆瓣电影TOP250-模块开发过程
  • 原文地址:https://www.cnblogs.com/ywxgod/p/1710676.html
Copyright © 2011-2022 走看看