Beautifl - Flash Gallery

Thumbnail : [Box2D]ダンボー遊び!forked from :(略)ダンボーを作った
[Box2D]ダンボー遊び!forked from :(略)ダンボーを作った
paq 2009-08-28 All rights reserved

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

// forked from rsakane's Box2Dジョイントの練習でダンボーを作った(何故か左にスライド)
/*
 * 根本的に書き直した。(あまり意味はない)
 * ドラッグで動かせるようにした。
 * ダンボーを増やした。
 * 何となく手をブラブラ(体から取れそう)
 * 
 * 倒れても、自動で立ち上がるようになっています。(なんかカワイイ)
 * たまに倒れたままの事がある。
 * 
 * ダンボー同士がぶつかり合うとケンカになります。注意を。
 * ケンカをするとまれに足が骨折します。(足をつかむと完治します。)
 * 
 * ボール遊びが好きなようで、ボールを与えると投げて遊びます。
 * 
 *
 * 左にスライドする現象はとりあえずOKかな。
 * 
*/
package {

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;

	import Box2D.Dynamics.*;
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Dynamics.Joints.*;
	import Box2D.Dynamics.Contacts.*;
	import Box2D.Common.*;
	import Box2D.Common.Math.*;
	
	[SWF(backgroundColor="0x000000", frameRate=60)]
	public class Main extends Sprite {

		public var m_sprite:Sprite;
		public var m_world:b2World;
		public var m_physScale:Number = 30.0;
		public var m_iterations:int = 10;
		public var m_timeStep:Number = 1.0/60.0;

		public var m_mouseJoint:b2MouseJoint;

		static public var mouseXWorldPhys:Number;
		static public var mouseYWorldPhys:Number;
		static public var mouseXWorld:Number;
		static public var mouseYWorld:Number;

		private var mousePVec:b2Vec2 = new b2Vec2();
		private var mouseDown:Boolean = false;

		public function Main():void
		{
			//コンテナ
			m_sprite = new Sprite();
			addChild(m_sprite);
			
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			stage.addEventListener(MouseEvent.CLICK, onMouseUp);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeave);

			addEventListener(Event.ENTER_FRAME, update, false, 0, true);

			//WORLD

			var worldAABB:b2AABB = new b2AABB();
			worldAABB.lowerBound.Set(-1000.0, -1000.0);
			worldAABB.upperBound.Set(1000.0, 1000.0);
			var gravity:b2Vec2 = new b2Vec2(0.0, 10.0);
			var doSleep:Boolean = true;
			m_world = new b2World(worldAABB, gravity, doSleep);

			//デバック用

			var dbgDraw:b2DebugDraw= new b2DebugDraw();
			var dbgSprite:Sprite= new Sprite();
			m_sprite.addChild(dbgSprite);
			dbgDraw.m_sprite= dbgSprite;
			dbgDraw.m_drawScale= 30.0;
			dbgDraw.m_fillAlpha = 0.3;
			dbgDraw.m_lineThickness= 1.0;
			dbgDraw.m_alpha=1.0;
			dbgDraw.m_xformScale=1.0;
			dbgDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
			m_world.SetDebugDraw(dbgDraw);
			
			createDunbor(232/m_physScale, 1.1);
			createDunbor(232/m_physScale, 3.5);
			createDunbor(232/m_physScale, 5.1);
			createOtherObject();
			createWall();

		}
		private function createOtherObject():void
		{
			var circ:b2CircleDef = new b2CircleDef();
			var bd:b2BodyDef = new b2BodyDef();
			var body:b2Body;
			
			circ.radius = 10 / m_physScale;
			circ.density = 1.0;
			circ.friction = 0.0;
			circ.restitution = 0.0;
			bd = new b2BodyDef();
			bd.position.Set(50 / m_physScale, 100 / m_physScale);
			var circbd:b2Body = m_world.CreateBody(bd);
			circbd.CreateShape(circ);
			circbd.SetMassFromShapes();
		}
		private function createDunbor(x:Number,y:Number):void
		{
			// 頭
			var bodyDef1:b2BodyDef = new b2BodyDef();
			bodyDef1.position.Set(x, y);
			bodyDef1.userData = new Head();
			addChild(bodyDef1.userData);
			var polygonDef1:b2PolygonDef = new b2PolygonDef();
			polygonDef1.SetAsBox(0.8, 0.5);
			polygonDef1.density = 0.2;
			polygonDef1.friction = 0.4;
			polygonDef1.restitution = 2;
			var body1:b2Body = m_world.CreateBody(bodyDef1);
			body1.CreateShape(polygonDef1);
			body1.SetMassFromShapes();
			
			// 体
			var bodyDef2:b2BodyDef = new b2BodyDef();
			bodyDef2.position.Set(x, y+1.1);
			bodyDef2.userData = new Body();
			addChild(bodyDef2.userData);
			var polygonDef2:b2PolygonDef = new b2PolygonDef();
			polygonDef2.SetAsBox(0.5, 0.6);
			polygonDef2.density = 1;
			polygonDef2.friction = 0.4;
			polygonDef2.restitution = 5;
			var body2:b2Body = m_world.CreateBody(bodyDef2);
			body2.CreateShape(polygonDef2);
			body2.SetMassFromShapes();
			
			// 左足
			var bodyDef3:b2BodyDef = new b2BodyDef();
			bodyDef3.position.Set(x-0.3, y+2.1);
			var polygonDef3:b2PolygonDef = new b2PolygonDef();
			polygonDef3.SetAsBox(0.2, 0.4);
			polygonDef3.density = 10;
			polygonDef3.friction = 0.4;
			polygonDef3.restitution = 0.3;
			var body3:b2Body = m_world.CreateBody(bodyDef3);
			body3.CreateShape(polygonDef3);
			body3.SetMassFromShapes();
			
			// 右足
			var bodyDef4:b2BodyDef = new b2BodyDef();
			bodyDef4.position.Set(x+0.3, y+2.1);
			var polygonDef4:b2PolygonDef = new b2PolygonDef();
			polygonDef4.SetAsBox(0.2, 0.4);
			polygonDef4.density = 10;
			polygonDef4.friction = 0.4;
			polygonDef4.restitution = 0.3;
			var body4:b2Body = m_world.CreateBody(bodyDef4);
			body4.CreateShape(polygonDef4);
			body4.SetMassFromShapes();
			
			// 左手
			var bodyDef5:b2BodyDef = new b2BodyDef();
			bodyDef5.position.Set(x-0.8, y+0.9);
			bodyDef5.angle = 30 * Math.PI / 180;
			var polygonDef5:b2PolygonDef = new b2PolygonDef();
			polygonDef5.SetAsBox(0.2, 0.4);
			polygonDef5.density = 1;
			polygonDef5.friction = 0.4;
			polygonDef5.restitution = 0.3;
			var body5:b2Body = m_world.CreateBody(bodyDef5);
			body5.CreateShape(polygonDef5);
			body5.SetMassFromShapes();
			
			// 右手
			var bodyDef6:b2BodyDef = new b2BodyDef();
			bodyDef6.position.Set(x+0.8, y+0.9);
			bodyDef6.angle = 330 * Math.PI / 180;
			var polygonDef6:b2PolygonDef = new b2PolygonDef();
			polygonDef6.SetAsBox(0.2, 0.4);
			polygonDef6.density = 1;
			polygonDef6.friction = 0.4;
			polygonDef6.restitution = 0.3;
			var body6:b2Body = m_world.CreateBody(bodyDef6);
			body6.CreateShape(polygonDef5);
			body6.SetMassFromShapes();
			
			// 頭と体をジョイント
			var distance1:b2DistanceJointDef = new b2DistanceJointDef();
			distance1.Initialize(body1, body2, new b2Vec2(x-0.4, y+0.5), new b2Vec2(x-0.4, y+0.51));
			m_world.CreateJoint(distance1);
			var distance2:b2DistanceJointDef = new b2DistanceJointDef();
			distance2.Initialize(body1, body2, new b2Vec2(x+0.4, y+0.5), new b2Vec2(x+0.4, y+0.51));
			m_world.CreateJoint(distance2);
			
			// 体と左足をジョイント
			distance1.Initialize(body2, body3, new b2Vec2(x-0.5, y+1.7), new b2Vec2(x-0.5, y+1.71));
			m_world.CreateJoint(distance1);
			distance2.Initialize(body2, body3, new b2Vec2(x-0.1, y+1.7), new b2Vec2(x-0.1, y+1.71));
			m_world.CreateJoint(distance2);
			
			// 体と右足をジョイント
			distance1.Initialize(body2, body4, new b2Vec2(x+0.1, y+1.7), new b2Vec2(x+0.1, y+1.71));
			m_world.CreateJoint(distance1);
			distance2.Initialize(body2, body4, new b2Vec2(x+0.5, y+1.7), new b2Vec2(x+0.5, y+1.71));
			m_world.CreateJoint(distance2);
		
			// 体と左手をジョイント
			distance1.Initialize(body2, body5, new b2Vec2(x-0.51, y+0.5), new b2Vec2(x-0.51, y+0.51));
			m_world.CreateJoint(distance1);
			//distance2.Initialize(body2, body5, new b2Vec2(x-0.7, y+0.5), body5.GetWorldCenter());
			//m_world.CreateJoint(distance2);

			// 体と右手をジョイント
			distance1.Initialize(body2, body6, new b2Vec2(x+0.5, y+0.5), new b2Vec2(x+0.51, y+0.51));
			m_world.CreateJoint(distance1);
			//distance2.Initialize(body1, body6, new b2Vec2(x+0.8, y+0.5), body6.GetWorldCenter());
			//m_world.CreateJoint(distance2);
		}
		private function createWall():void
		{
			var wallObject:b2PolygonDef = new b2PolygonDef();
			wallObject.density = 0.0;
			var wallDef:b2BodyDef = new b2BodyDef();
			var wallBody:b2Body;

			//Left
			wallDef.position.Set(-6 / m_physScale, 465/2 / m_physScale);
			wallObject.SetAsBox(10/2 / m_physScale, 465/2 / m_physScale);
			wallBody = m_world.CreateBody(wallDef);
			wallBody.CreateShape(wallObject);
			wallBody.SetMassFromShapes();

			//Right
			wallDef.position.Set((465+14/2) / m_physScale, 465/2 / m_physScale);
			wallObject.SetAsBox(10/2 / m_physScale, 465/2 / m_physScale);
			wallBody = m_world.CreateBody(wallDef);
			wallBody.CreateShape(wallObject);
			wallBody.SetMassFromShapes();

			//Top
			wallDef.position.Set(465/2 / m_physScale, -7 / m_physScale);
			wallObject.SetAsBox(465/2 / m_physScale, 10/2 / m_physScale);
			wallBody = m_world.CreateBody(wallDef);
			wallBody.CreateShape(wallObject);
			wallBody.SetMassFromShapes();

			//Bottom
			wallDef.position.Set(465/2 / m_physScale, (465-10/2) / m_physScale);
			wallObject.SetAsBox(465/2 / m_physScale, 10/2 / m_physScale);
			wallBody = m_world.CreateBody(wallDef);
			wallBody.CreateShape(wallObject);
			wallBody.SetMassFromShapes();
		}
		
		private function update(event:Event):void
		{			
			m_world.Step(m_timeStep, m_iterations);
			m_sprite.graphics.clear();
			
			UpdateMouseWorld();
			MouseDrag();
			
			for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next)
			{
				if (bb.m_userData is Sprite)
				{
					bb.m_userData.x = bb.GetPosition().x * 30;
					bb.m_userData.y = bb.GetPosition().y * 30;
					bb.m_userData.rotation = bb.GetAngle() * 180 / Math.PI;
				}
			}
			
			// joints
			for (var jj:b2Joint = m_world.m_jointList; jj; jj = jj.m_next){
				DrawJoint(jj);
			}
		}
		
		private function onMouseDown(event:MouseEvent):void
		{
			mouseDown = true;
		}
		
		private function onMouseUp(event:MouseEvent):void
		{
			mouseDown = false;
		}
		
		private function onMouseMove(event:MouseEvent):void
		{
			if (mouseDown != event.buttonDown){
				mouseDown = event.buttonDown;
			}
		}
		
		public function onMouseLeave(e:Event):void
		{
			mouseDown = false;
			MouseDrag();
		}
		
		//======================
		// Update mouseWorld
		//======================
		public function UpdateMouseWorld():void
		{
			mouseXWorldPhys = (mouseX)/m_physScale; 
			mouseYWorldPhys = (mouseY)/m_physScale; 
			
			mouseXWorld = (mouseX); 
			mouseYWorld = (mouseY); 
		}
		
		//======================
		// Mouse Drag 
		//======================
		public function MouseDrag():void
		{
			// mouse press
			if (mouseDown && !m_mouseJoint){
				
				var body:b2Body = GetBodyAtMouse();
				
				if (body)
				{
					var md:b2MouseJointDef = new b2MouseJointDef();
					md.body1 = m_world.GetGroundBody();
					md.body2 = body;
					md.target.Set(mouseXWorldPhys, mouseYWorldPhys);
					md.maxForce = 300.0 * body.GetMass();
					md.timeStep = m_timeStep;
					m_mouseJoint = m_world.CreateJoint(md) as b2MouseJoint;
					body.WakeUp();
				}
			}
			
			// mouse release
			if (!mouseDown){
				if (m_mouseJoint)
				{
					m_world.DestroyJoint(m_mouseJoint);
					m_mouseJoint = null;
				}
			}
			
			// mouse move
			if (m_mouseJoint)
			{
				var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys);
				m_mouseJoint.SetTarget(p2);
			}
		}
		
		//======================
		// GetBodyAtMouse
		//======================
		public function GetBodyAtMouse(includeStatic:Boolean = false):b2Body
		{
			// Make a small box.
			mousePVec.Set(mouseXWorldPhys, mouseYWorldPhys);
			var aabb:b2AABB = new b2AABB();
			aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001);
			aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001);
			
			// Query the world for overlapping shapes.
			var k_maxCount:int = 10;
			var shapes:Array = new Array();
			var count:int = m_world.Query(aabb, shapes, k_maxCount);
			var body:b2Body = null;
			for (var i:int = 0; i < count; ++i)
			{
				if (shapes[i].GetBody().IsStatic() == false || includeStatic)
				{
					var tShape:b2Shape = shapes[i] as b2Shape;
					var inside:Boolean = tShape.TestPoint(tShape.GetBody().GetXForm(), mousePVec);
					if (inside)
					{
						body = tShape.GetBody();
						break;
					}
				}
			}
			return body;
		}

		//======================
		// Draw Joint 
		//======================
		public function DrawJoint(joint:b2Joint):void
		{
			var b1:b2Body = joint.m_body1;
			var b2:b2Body = joint.m_body2;
			
			var x1:b2Vec2 = b1.m_linearVelocity;
			var x2:b2Vec2 = b2.m_linearVelocity;
			var p1:b2Vec2 = joint.GetAnchor1();
			var p2:b2Vec2 = joint.GetAnchor2();
			
			m_sprite.graphics.lineStyle(1,0x44aaff,1/1);
			
			switch (joint.m_type)
			{
			case b2Joint.e_distanceJoint:
			case b2Joint.e_mouseJoint:
				m_sprite.graphics.moveTo(p1.x * m_physScale, p1.y * m_physScale);
				m_sprite.graphics.lineTo(p2.x * m_physScale, p2.y * m_physScale);
				break;
				
			case b2Joint.e_pulleyJoint:
				var pulley:b2PulleyJoint = joint as b2PulleyJoint;
				var s1:b2Vec2 = pulley.m_groundAnchor1;
				var s2:b2Vec2 = pulley.m_groundAnchor2;
				m_sprite.graphics.moveTo(s1.x * m_physScale, s1.y * m_physScale);
				m_sprite.graphics.lineTo(p1.x * m_physScale, p1.y * m_physScale);
				m_sprite.graphics.moveTo(s2.x * m_physScale, s2.y * m_physScale);
				m_sprite.graphics.lineTo(p2.x * m_physScale, p2.y * m_physScale);
				break;
				
			default:
				if (b1 == m_world.m_groundBody){
					m_sprite.graphics.moveTo(p1.x * m_physScale, p1.y * m_physScale);
					m_sprite.graphics.lineTo(x2.x * m_physScale, x2.y * m_physScale);
				}
				else if (b2 == m_world.m_groundBody){
					m_sprite.graphics.moveTo(p1.x * m_physScale, p1.y * m_physScale);
					m_sprite.graphics.lineTo(x1.x * m_physScale, x1.y * m_physScale);
				}
				else{
					m_sprite.graphics.moveTo(x1.x * m_physScale, x1.y * m_physScale);
					m_sprite.graphics.lineTo(p1.x * m_physScale, p1.y * m_physScale);
					m_sprite.graphics.lineTo(x2.x * m_physScale, x2.y * m_physScale);
					m_sprite.graphics.lineTo(p2.x * m_physScale, p2.y * m_physScale);
				}
			}
		}

	}
}

import flash.display.Sprite;

class Head extends Sprite
{
	public function Head()
	{
		graphics.beginFill(0x00000);
		graphics.drawCircle(-30, -15, 10);
		graphics.drawCircle(30, -15, 10);
		graphics.moveTo(0, 5);
		graphics.lineTo(-15, 23);
		graphics.lineTo(15, 23);
		graphics.lineTo(0, 5);
		graphics.endFill();
		
		scaleX = scaleY = 0.333;
	}
}

class Body extends Sprite
{
	public function Body()
	{
		graphics.beginFill(0x777777);
		graphics.drawCircle(30, -45, 8);
		graphics.endFill();
		graphics.beginFill(0x000000);
		graphics.drawRect(26, -45, 8, 2);
		graphics.endFill();
		
		scaleX = scaleY = 0.333;
	}
}