加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

[Box2D]五.和刚体交互

发布时间:2020-12-15 18:08:49 所属栏目:百科 来源:网络整理
导读:点这看效果 此demo包含以下内容: 1.通过鼠标选择刚体 2.销毁刚体 3.对刚体设置自定义属性(包括皮肤) 4.循环遍历世界中的所有刚体 5.获取刚体信息 详细的解释请看代码 皮肤下载 skin1.swc package {import Box2D.Collision.Shapes.b2PolygonShape;import Box



点这看效果



此demo包含以下内容:

1.通过鼠标选择刚体

2.销毁刚体

3.对刚体设置自定义属性(包括皮肤)

4.循环遍历世界中的所有刚体

5.获取刚体信息


详细的解释请看代码

皮肤下载skin1.swc

package 
{	
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2Fixture;
	import Box2D.Dynamics.b2FixtureDef;
	import Box2D.Dynamics.b2World;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	
	[SWF(width="410",height="480")]
	public class Interact extends Sprite {
		
		private var stageWidth:Number = 410;			//舞台宽度
		private var stageHeight:Number = 480;			//舞台高度
		private var backgroundColor:uint = 0x333333;	//背景色
		
		private var world:b2World;                //Box2D世界
		private var worldScale:Number = 30;        //一米等于30像素
		private var timeStep:Number = 1 / 30;    //时间步,世界将在每一个时间步被更新
		
		//只是定义了时间步还不够。在每一步,每一个物理实体(physic entity)根据作用
		//于自身的作用力来更新(不包括睡眠状态)。处理这项任务的算法叫约束解算器
		//(constraint solver)。它是基于循环每一个约束然后解算来进行的,一次一个。
		private var velIterations:int = 10;        //速率约束解算器
		private var posIterations:int = 10;        //位置约束解算器
		
		private var info:TextField;	//info实时显示头像的坐标,速度,角度
		
		public function Interact() {
			drawBackground();
			createTip();
			createInfo();
			createWorld();
			//创建地面
			var floorAsset:DisplayObject = new FloorAsset();
			createRectBody( {x:floorAsset.width/2,y:stageHeight - floorAsset.height/2,width:floorAsset.width,height:floorAsset.height,asset:floorAsset,id:"floor"} );
			
			//创建左边界
			createRectBody({x:1,y:stageHeight/2,width:2,height:stageHeight,id:"leftBound"});
			//创建右边界
			createRectBody({x:stageWidth - 1,id:"rightBound"});
			
			//创建砖块
			var brickAsset:Sprite = new BrickAsset1();
			createRectBody({x:175,y:435,width:brickAsset.width,height:brickAsset.height,asset:brickAsset,type:b2Body.b2_dynamicBody,canDestroy:true,id:"brick1"});

			brickAsset = new BrickAsset2();
			createRectBody({x:265,id:"brick2"});
			
			brickAsset = new BrickAsset3();
			createRectBody({x:220,y:405,id:"brick3"});
			
			brickAsset = new BrickAsset4();
			createRectBody({x:220,y:375,id:"brick4"});
			
			brickAsset = new BrickAsset5();
			createRectBody({x:205,y:345,id:"brick5"});
			
			brickAsset = new BrickAsset6();
			createRectBody({x:220,y:300,id:"brick6"});
			
			//创建头像
			var iconAsset:IconAsset = new IconAsset();
			createRectBody({x:220,y:80,width:iconAsset.width,height:iconAsset.height,asset:iconAsset,id:"userIcon"});
			
			addEventListener(Event.ENTER_FRAME,onUpdate);
			stage.addEventListener(MouseEvent.CLICK,onStageClick);
		}
		
		private function drawBackground():void {
			graphics.beginFill(backgroundColor);
			graphics.drawRect(0,stageWidth,stageHeight);
			graphics.endFill();
		}
		
		private function createTip():void {
			var tip:TextField = new TextField();
			var format:TextFormat = new TextFormat();
			format.size = 14;
			format.color = 0xFFFFFF;
			tip.autoSize = TextFieldAutoSize.LEFT;
			tip.defaultTextFormat = format;
			tip.text = "砖块可销毁(点击它)";
			addChild(tip);
			tip.x = (stageWidth - tip.width) / 2;
		}
		
		private function createInfo():void {
			info = new TextField();	
			var format:TextFormat = new TextFormat();
			format.size = 14;
			format.color = 0xFFFFFF;
			info.autoSize = TextFieldAutoSize.LEFT;
			info.defaultTextFormat = format;
			addChild(info);
		}
		
		private function createWorld():void {
			var gravity:b2Vec2 = new b2Vec2(0,9.81);    //重力
			//世界中的刚体静止时,可以允许他们进入睡眠状态,睡眠的刚体无需模拟
			var sleep:Boolean = true;
			world = new b2World(gravity,sleep);
		}
		
		private function onStageClick(event:MouseEvent):void {
			var x:Number = mouseX / worldScale;
			var y:Number = mouseY / worldScale;
			//世界的QueryPoint方法查询世界中所有的夹具,找出在点上的夹具,
			//然后如果有夹具在鼠标点击的点上,我们可以说我们点击了一个夹具。
			world.QueryPoint(queryCallback,new b2Vec2(x,y));
		}
		
		//在鼠标点击的点上的夹具。因为一个点上可以有不止一个的夹具(试
		//想一下重叠的staitc类型的刚体),如果你希望检查下一个夹具,那么你需要
		//让函数返回true,或者返回false将停止检查。
		private function queryCallback(fixture:b2Fixture):Boolean {
			var touchedBody:b2Body = fixture.GetBody();
			var userData:Object = touchedBody.GetUserData(); //获取自定义的刚体信息
			if(userData.canDestroy == true) {
				world.DestroyBody(touchedBody);	//销毁刚体
				removeChild(userData.asset);
			}
			//我们假设只可以有一个夹具在鼠标点击的点上
			//所以return false
			return false;
		}
		
		private function createRectBody(data:Object):void {
			var bodyDef:b2BodyDef = new b2BodyDef(); //刚体定义
			if(data.type != undefined) {
				bodyDef.type = data.type;  //刚体类型默认为静态	
			}
			bodyDef.position.Set(data.x/worldScale,data.y/worldScale);//设置刚体坐标,Box2D坐标用米表示	
			bodyDef.userData = new Object();
			if(data.id != undefined) {
				bodyDef.userData.id = data.id;	
			}
			if(data.asset != undefined) {
				bodyDef.userData.asset = data.asset;//为刚体设置皮肤
			}
			if(data.canDestroy != undefined) {
				bodyDef.userData.canDestroy = data.canDestroy;//点击时,是否能销毁
			}else {
				bodyDef.userData.canDestroy	= false;
			}
			var polygonShape:b2PolygonShape = new b2PolygonShape(); //创建多边形
			polygonShape.SetAsBox(data.width/2/worldScale,data.height/2/worldScale);//轴对称的矩形,半宽长和半高长          
			
			var fixtureDef:b2FixtureDef = new b2FixtureDef(); //夹具(fixture)用于将形状绑定到刚体上
			if(data.density != undefined) { //密度	
				fixtureDef.density = data.density;
			}else {
				fixtureDef.density = 1;
			}
			if(data.restitution != undefined) { //弹性系数
				fixtureDef.restitution = data.restitution;
			}else {
				fixtureDef.restitution = 0.1;
			}
			if(data.friction != undefined) { //摩擦系数
				fixtureDef.friction = data.friction;
			}else {
				fixtureDef.friction = 0.1;
			}
			fixtureDef.shape = polygonShape;
			
			var body:b2Body = world.CreateBody(bodyDef); //创建刚体
			body.CreateFixture(fixtureDef);
			
			if(data.asset != undefined) {
				addChild(data.asset);
				data.asset.x = body.GetPosition().x * worldScale;
				data.asset.y = body.GetPosition().y * worldScale;
			}
		}

		private function onUpdate(e:Event):void {
			world.Step(timeStep,velIterations,posIterations);
			world.ClearForces();
			//GetBodyList()方法获得世界刚体列表并返回列表的第一个刚体.
			//使用GetNext()方法获得列表的下一个刚体,但是如果你的刚
			//体已经到达了刚体列表的末端,这时GetNext()方法将返回null
			for (var body:b2Body = world.GetBodyList(); body; body = body.GetNext()) {
				if(body.GetUserData()) {
					var x:Number = body.GetPosition().x * worldScale;
					var y:Number = body.GetPosition().y * worldScale;
					var angle:Number = body.GetAngle() * 180 / Math.PI; //弧度转为度
					if(body.GetUserData().id == "userIcon") {
						info.text = "头像刚体的属性n坐标: ";
						info.appendText(x.toFixed(1));
						info.appendText(",");
						info.appendText(y.toFixed(1));
						info.appendText("n角度: ");
						info.appendText(angle.toFixed(1));
						info.appendText("n速度: ");
						//GetLinearVelocity()方法获得刚体中心的线速度,然后返回
						//一个b2Vec2对象,它代表水平和垂直速度,单位是米每秒
						var v:b2Vec2 = body.GetLinearVelocity();
						var vx:Number = v.x * worldScale;
						info.appendText(vx.toFixed(1));
						info.appendText(",");
						var vy:Number = v.y * worldScale;
						info.appendText(vy.toFixed(1));
						
					}
					if(body.GetUserData().asset) {
						body.GetUserData().asset.x = x;
						body.GetUserData().asset.y = y;
						body.GetUserData().asset.rotation = angle;	
					}
				}
			}
		}
	}
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读