본문 바로가기

AS3/Box2D

box2D를 활용한 그래픽 붙이기






box2D와 관련된 자료가 한국 사이트에는 많이 없어서 이것저것 배울 수 있는 자료에 제약이 많다.
이럴때마다 느끼는게 영어가 절대적으로 배움이 필요하다는걸 느낀다.

box2D는 다양한 언어로 개발이 되어있고 공식 포럼란에 가면 flash포럼란이 따로있다.
그곳에는 많은 사람들이 정보를 공유하고 있지만 정작 내가 얻을 수 있는게 많지 않다는게 아쉬울뿐이다.

위에 작업은 아주 기본적인 예제 자료에서 Loader클래스로 이미지를 불러온다음 무비클립에 이미지를
담은 후 객체를 생성에 물리공간안에 뿌려주게된다.

공부를 하면서 참고를 많이 할 수 있었던 곳은 네이버에 ooaso님이 운영중이신 http://cafe.naver.com/uiaa 카페에
가면 box2d와 관련된 좋은 강좌들을 만나볼 수 있다.

box2D 공식 홈페이지 http://www.box2d.org/
Flash Box2DFlashAS3.0 다운로드 http://box2dflash.sourceforge.net/
ooaso님이 운영중이신 uiaa카페 box2d 강좌란 http://cafe.naver.com/uiaa.cafe
이곳에 가면 관련자료들이 많다.

그리고 아래 사용된 소스들은 http://cafe.naver.com/uiaa.cafe에 운영자이신
ooaso님이 작성하신 소스를 가지고 편집했음을 알려드립니다.


출처 :
http://cafe.naver.com/uiaa.cafe



package {
	/**
	* ...
	* sanoi(ooaso@naver.com/sanoi@iamg.kr)@ IAMG
	* http://cafe.naver.com/uiaa.cafe
	*/
	import adobe.utils.CustomActions;
	import flash.display.*;
	import flash.events.*;
	import Box2D.Collision.*; // 경계박스를 사용하기 위해 필요합니다.
	import Box2D.Common.Math.*; // 벡터를 사용하기 위해 필요합니다. 
	import flash.net.URLRequest;
								// 벡터는 중력을 정의할 때 사용합니다.
	import Box2D.Dynamics.*; // 물체와 world 를 정의할 때 필요합니다. 
	import Box2D.Collision.Shapes.*; // shape 을 정의할 때 필요합니다.
	
	public class Box2DRectTest extends Sprite {
		
		private var myWorld:b2World; // world
		private var m_timeStep:Number; // time step
		private var m_iterations:int; // iterations
		private var mouseHandel:Box2DMouseHandle;
		private var mouseDown:Boolean;
		
		private var McImg:MovieClip;
		
		function Box2DRectTest(){
			m_timeStep = 1.0 / 36.0;
			m_iterations = 10;
					
			//world 경계박스
			var worldBox:b2AABB = new b2AABB();			

			worldBox.lowerBound.Set(-100,-100) // 1 미터 = 30 픽셀
			worldBox.upperBound.Set(100,100);
			
			// 중력
			var gravity:b2Vec2 = new b2Vec2(0, 50 );
			
			var bSleep:Boolean = true;
			
			// world 만들기
			myWorld = new b2World(worldBox, gravity, bSleep);
			
			mouseHandel = new Box2DMouseHandle(myWorld, 30, m_timeStep, m_iterations);
			mouseDown = false;
						
			// 디버그 모드
			/*
			var dbgDraw:b2DebugDraw = new b2DebugDraw();
			dbgDraw.m_sprite = new Sprite();
			addChild(dbgDraw.m_sprite);
			dbgDraw.m_drawScale = 30.0;
			dbgDraw.m_fillAlpha = 0.3;
			dbgDraw.m_lineThickness = 1.0;
			dbgDraw.m_drawFlags = b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit;
			
			myWorld.SetDebugDraw(dbgDraw);
			*/
			setGround();
			startCalc();
			
			
			// McImg = new Sprite();
			
			for (var i:int = 1; i < 17;i++){
				makeDynamicBody(i);
			}
			
			
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mousePress);
			stage.addEventListener(MouseEvent.CLICK, mouseRelease);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
			stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
			
		}
		
		private function mouseLeave(e:Event):void {
			mouseDown = false;
		}
		
		private function mouseMove(e:MouseEvent):void {
			mouseDown = e.buttonDown;
		}
		
		private function mouseRelease(e:MouseEvent):void {
			mouseDown = false;
		}
		
		private function mousePress(e:MouseEvent):void {
			mouseDown = true;
		}
		
		private function setGround():void	{
			// 정적 물체 만들기
			// shape 정의
			var boxDef:b2PolygonDef = new b2PolygonDef();
			boxDef.SetAsBox(11,.1); // 1 meter = 30 pixels, width 90, height 30
			boxDef.friction = 0.8 // between 0 and 1
			
			var posX:Array = [ 400, 0, 800];
			var posY:Array = [ 605, 200, 200];
			var angle:Array = [ 0, 90*Math.PI/180, 90*Math.PI/180];
			
			for(var i:int = 0;i<3;i++){
				// 바디정의 만들기
				var bodyDef:b2BodyDef = new b2BodyDef();
				bodyDef.userData = new Sprite();
				bodyDef.userData.width = 510;
				bodyDef.userData.height = 3;
				bodyDef.angle = angle[i];
				bodyDef.position.Set(posX[i]/30, posY[i]/30);
	
				addChild(bodyDef.userData);
				
				// 실제 바디를 만든다
				var body:b2Body = myWorld.CreateBody(bodyDef);
				body.CreateShape(boxDef);
			}			
		}
		
		private function makeDynamicBody(i:int):void {
		   // 크기는 랜덤하게
		   
			var loader:Loader = new Loader();
			loader.load(new URLRequest('http://nicekon.cafe24.com/test/box2d_gallery/images/'+i+'_s.jpg'));
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadExternalImg); 
		
		}
		

		// 동적 물체 만들기
		// 호출 될 때 마다 하나의 물체를 만든다.
		private function onLoadExternalImg(e:Event):void {
			// 크기는 랜덤하게
			buttonMode = true;
			var w:int = int((Math.random()*50) + 90);
			var h:int = w;
			var boxDef:b2PolygonDef = new b2PolygonDef();
			boxDef.SetAsBox(w/60,h/60); // 1 meter = 30 pixels, width 90, height 30
			boxDef.friction = 0.6 // between 0 and 1
			boxDef.density = 20; // 질량이 있는 물체이므로 밀도를 지정해 준다
			
			var bodyDef:b2BodyDef = new b2BodyDef();
			//bodyDef.userData = new Sprite();
			
			var bitmapContainer:MovieClip = new MovieClip();
		    var bmp:Bitmap = e.target.content;
		    bmp.x -= bmp.width / 2;
		    bmp.y -= bmp.height / 2;
		    bitmapContainer.addChild(e.target.content);

			bodyDef.userData = bitmapContainer;
			bodyDef.userData.width = w;
			bodyDef.userData.height = h;
			bodyDef.angle = (Math.random() * 90) * Math.PI / 180;
			bodyDef.position.Set(int(Math.random() * 800)/30, int(Math.random() * -1000/30));
				
			addChild(bodyDef.userData);
			
			// 실제 바디를 만든다
			var body:b2Body = myWorld.CreateBody(bodyDef);
			body.CreateShape(boxDef);
			body.SetMassFromShapes(); // Shape 정보로 부터 질량을 자동으로 계산한다
			
			addEventListener( MouseEvent.MOUSE_DOWN, onDownBody );
		
		}
		
		
		private function makeWater():void {
			// 크기는 랜덤하게
			buttonMode = true;
			var w:int = 8;
			var h:int = 8;
			var circleBodyDef:b2CircleDef = new b2CircleDef();
			circleBodyDef.radius = 0.13;
			circleBodyDef.friction = 0.2;
			circleBodyDef.restitution = 0.5;
			circleBodyDef.density = 10;
			
			
			var bodyDef:b2BodyDef = new b2BodyDef();
			//bodyDef.userData = new Sprite();
			
			//var bitmapContainer:MovieClip = new MovieClip();
		    //var bmp:Bitmap = e.target.content;
		    //bmp.x -= bmp.width / 2;
		    //bmp.y -= bmp.height / 2;
		    //bitmapContainer.addChild(e.target.content);

			bodyDef.userData = new McWater();
			bodyDef.userData.width = w;
			bodyDef.userData.height = h;
			bodyDef.angle = (Math.random() * 90) * Math.PI / 180;
			bodyDef.position.Set(int(Math.random() * 800)/30, int(Math.random() * -300/30));
				
			addChild(bodyDef.userData);
			
			// 실제 바디를 만든다
			var body:b2Body = myWorld.CreateBody(bodyDef);
			body.CreateShape(circleBodyDef);
			body.SetMassFromShapes(); // Shape 정보로 부터 질량을 자동으로 계산한다
			
			addEventListener( MouseEvent.MOUSE_DOWN, onDownBody );
		
		}
	
		
		private function onDownBody(e:MouseEvent):void 		{
		
		}
		
		
		// 물리 세계 시뮬레이션 시작
		private function startCalc():void {
			addEventListener(Event.ENTER_FRAME, Update);
		}
		
		private function Update(e:Event):void {
			// 마우스 조인트 연동
			mouseHandel.MouseDrag(stage.mouseX, stage.mouseY, mouseDown);
			// 물리 세계 시뮬레이션
			myWorld.Step(m_timeStep, m_iterations);	
			
			
			if(int(Math.random() * 10)==0){
				makeWater();
			}
			
			
			// Go through body list and update sprite positions/rotations
			for (var bb:b2Body = myWorld.m_bodyList; bb; bb = bb.m_next){
				if (bb.m_userData is MovieClip){
					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);
				}
			}
		}
	}
}

 

'AS3 > Box2D' 카테고리의 다른 글

box2d  (0) 2009.06.26