'번역/Box2D AS3 매뉴얼'에 해당되는 글 4건

  1. Box2D - 7.Shapes 2009.11.25
  2. Box2D - 6.Bodies (1) 2009.10.24
  3. Box2D - 9.Contacts 2009.10.18
  4. Box2D - 8.Joint (2) 2009.06.28

미완성. 영어실력이 일천하므로 의역이 대부분입니다. 지적 감사히 받습니다.
개인적인 학습을 위해 작성된 게시물이며 원 저작권은 Box2D 포럼에 있습니다.

매뉴얼의 각 챕터의 번역은 역자의 판단에 따른 중요도 순서대로 진행될 예정입니다.
2012년 12월 현재 원문 매뉴얼은 위키에서 제거되고 PDF화된 매뉴얼이 배포중입니다. 근시일내 PDF에 대한 번역작업을 새로이 진행할 것이며 이하 번역내용은 2009년의 것으로 현재 버전과 다른 점이 있을 수 있음을 유의하시기 바랍니다.
일러두기>진행중인 문서입니다. 대부분 완료되었습니다.
원문보기>http://www.box2d.org/wiki/index.php?title=Manual/AS3#Shapes

About 개요

모양은 강체에 붙여지는 충돌 도형이다. 또한 모양은 강체의 질량을 정의하는데 쓰이기도 한다. 이는 당신이 밀도를 명시하게 하고 Box2D가 질량을 계산하는작업을 맡는 것이다.[todo:의역제거]

모양은 마찰과 탄성 속성을 갖는다. 그리고 특정한 게임 객체와의 충돌을 무시하는 필터링 정보를 갖고 있다.

모양은 항상 강체에 의해 소유된다. 당신은 하나의 강체에 며러 개의 모양을 붙일 수 있다. 모양은 추상 클래스이며 다양한 형태의 모양이 Box2D에서 구현될 수 있다. 당신이 용사-_-라면 당신은 고유의 모양을 구현할 수 있다. (또한 충돌 알고리즘도.)

The Shape Definition 모양의 정의

모양의 정의는 모양을 생성하기 위해 사용된다. 모양에서 공통되는 데이터는 b2ShapeDef가 가지고 있고 고유한 데이터는 파생 클래스가 갖고 있다.

Friction and Restitution 마찰과 탄성

마찰은 물체들이 서로 사실적으로 미끄러지도록 만드는 데 쓰인다. Box2D는 정적, 동적마찰을 지원하지만 양자는 같은 인수를 사용한다. 마찰은 Box2D에서 정확하게 시뮬레이트되며 마찰 강도는 법선 힘(이것은 쿨롱 마찰이라고 불린다.)에 비례한다. 마찰 인수는 일반적으로 0과 1사이에서 설저된다. 0의 값은 마찰을 끄고 1의 값은 마찰을 강하게 한다. 두 모양 사이에서 마찰이 계산될 때 Box2D는 두 모양의 마찰 인수를 병합해야 한다. 이것은 다음 수식에 의해 완료된다.

var friction :Number = Math.sqrt(shape1.friction * shape2.friction);
탄성은 물체를 튕겨내는데 사용된다. 탄성 값은 일반적으로 0과 1 사이의 값으로 설정된다. 테이블에 공을 떨어트리는 것을 생각해보자. 0의 값은 공이 튀기지 않음을 의미한다. 이는 비탄성 충돌이라 불린다. 1의 값은 공의 속도가 완전하게 반사됨을 의미한다. 이것은 완전 탄성 충돌이라 불린다. 탄성은 다음 수식을 통해 합성된다.







var restitution: Number = Math.Max(shape1.restitution, shape2.restitution);


모양이 복수의 충돌을 일으켰을 때 탄성은 간략하게 시뮬레이션된다. 이것은 Box2D가 반복적인 처리자를 사용하기 떄문이다. Box2D는 또한 충돌 속도가 작을 때에는 비탄성 충돌을 사용한다.


Density 밀도

Box2D는 강체에 붙여진 모양에 의해 암시된 질량의 분포를 사용해서 질량과 강체의 회전 관성을 선택적으로 계산한다. (todo:오역소지) 직접적으로 질량을 명시하는 것은 때때로 허접한 시뮬레이션을 만든다. 그러므로, 권장하는, 강체의 질량을 명시하는 방법은 모양의 밀도를 지정하고 강체에 붙여진 모든 모양에 대해 b2Body.setMessFromShape를 한번씩 호출하는 것이다.


Filtering

충돌 필터링은 모양들 사이의 충돌을 방지하는 시스템이다. 예를 들어, 당신이 자전거를 타는 캐릭터를 만든다고 해보자. 당신은 자전거가 지형과 충돌하고, 캐릭터도 지형과 충돌하길 원한다. 그러나 캐릭터가 자전거와 충돌하길 원하지는 않을 것이다 (그것들은 겹쳐져 있어야 하니까.) Box2D는 그런 충돌을 카테고리와 그룹을 통해 필터링하는 것을 지원한다.


Box2D는 16개의 충돌 카테고리를 지원한다. 각 모양을 위해 당신은 어느 카테고리에 그것이 속할 것인지 지정할 수 있다. 또한 어떤 카테고리가 이 모양과 충돌할 수 있을지도 지정할 수 있다. 예를 들면, 당신은 모든 플레이어가 서로 충돌하지 않고 몬스터들도 서로 충돌하지 않지만 플레이어와 몬스터는 충돌해야 하는 다중사용자 게임을 정의할 수 있다. 이것은 비트 마스크를 통해 이루어진다. 다음 예제를 보자.


playerShapeDef.filter.categoryBits = 0x0002;

monsterShapeDef.filter.categoryBits  = 0x0004;

playerShapeDef.filter.maskBits       = 0x0004;

monsterShapeDef.filter.maskBits      = 0x0002;

충돌 그룹은 필수적인 그룹 인덱스를 명시해야 한다. 당신은 같은 인덱스를 가진 모든 모양들이 항상 충돌(양수 인덱스)하거나, 또는 절대 충돌하지 않(음수 인덱스)도록 할 수 있다. 그룹 인덱스들은 일반적으로, 자전거의 각 부품들처럼 어떻게든 관계가 있는 것들을 위해 사용된다. 다음 예제에서는, shape1과 shape2가 항상 충돌한다. 그러나 shape3과 shape4는 절대 충돌하지 않는다.


shape1Def.filter.groupIndex = 2;
shape2Def.filter.groupIndex = 2;
shape3Def.filter.groupIndex = -8;
shape4Def.filter.groupIndex = -8;

다른 그룹 인덱스를 가진 모양들 사이의 충돌은 카테고리와 마스크 비트에 의해 걸러진다. 달리 말하면, 그룹 필터링은 그룹 필터링은 카테고리 필터링보다 선행한다는 것이다.

다음은 Box2D에서 일어나는 추가적인 필터링의 목록이다.

  • 정적 강체에 있는 모양은 다른 정적 강체의 모양과 절대 충돌하지 않는다.
  • 한 강체 안의 모양들은 절대 서로 충돌하지 않는다.
  • 당신은 조인트로 연결된 강체들의 모양이 서로 충돌할지 선택할 수 있다.

Sometimes you might need to change collision filtering after a shape has already been created. You can get and set the b2FilterData structure on an existing shape using b2Shape.GetFilterData and b2Shape.SetFilterData. Box2D caches filtering results, so you must manually re-filter a shape using b2World.Refilter.

때떄로 당신은 모양이 기존에 생성된 후에 충돌 필터링을 변경할 필요가 있을 것이다. 당신은 b2FilterData 구조체를 기존 모양의 b2Shape.GetFilterData와 b2Shape.SetFilterData를 통해 얻거나 지정할 수 있다. Box2D는 필터링 결과를 캐시해 두므로, 당신은 b2World.Refilter를 통해 수동으로 모양들을 다시 필터링할 필요가 있다.


Sensors

때떄로 게임 로직은 아직 충돌 반응이 없을 때라도 언제 두 모양이 겹쳐졌는지를 알 필요가 있다. 이것은 센서를 통해 이루어진다. 센서는 충돌을 감지하지만 반응을 일으키지는 않는 모양의 하나이다.


You can flag any shape as being a sensor. Sensors may be static or dynamic. Remember that you may have multiple shapes per body and you can have any mix of sensors and solid shapes.

당신은 어떤 모양이든 센서로서 기능하는 플래그를 지정할 수 있다. 센서는 정적이거나 동적일 수 있다. 강체 하나가 복수의 모양을 가질 수 있으며, 센서와 일반적인 모양을 아무렇게든 섞을 수 있음을 기억하라.


myShapeDef.isSensor = true;

Circle Definitions 원의 정의

b2CicleDef는 b2ShapeDef를 확장하며 지역적 위치와 반지름을 추가한다.


var def:b2CircleDef;
def.radius = 1.5;
def.localPosition.Set(1.0, 0.0);

Polygon Definitions 폴리곤의 정의

b2PolyDef is used to implement convex polygons. They are a bit tricky to use correctly, so please read closely. The maximum vertex count is defined by b2_maxPolyVertices which is currently 8. If you need to use more vertices, you must modify b2_maxPolyVertices in file b2Settings.
b2PolyDef는 볼록한 폴리곤을 구현한다. (todo:의불) 정점 수의 최대값은 b2_maxPolyVertices에 의해 정의되며 이 값은 현재 8이다. 만약 더 많은 정점을 필요로 한다면 b2Settings파일에 있는 b2_maxPolyVertices를 수정해야 한다.

When you build a polygon definition you must specify the number of vertices you will use. The vertices must be specified in counter-clockwise (CCW) order about the z-axis of a right-handed coordinate system. This might turn out to be clockwise on your screen, depending on your coordinate system conventions.

당신이 폴리곤의 정의를 구성할 때 사용할 정점의 갯수를 명시해야 한다. 정점들은 오른손 법칙 체계의 z축에 대해 시계반대방향 순서로 명시되어야 한다. 이것은 좌표체계의 방식에 의존하는 화면상에서는 결국 시계 반대 방향이 될 것이다. (todo:오역)


폴리곤은 반드시 볼록해야 한다. 달리 말하면, 각 정점은 일정 각도만큼 밖으로 향해야 한다. 마지막으로, 당신은 어떤 정점도 겹치지 않도록 해야 한다. Box2D는 자동적으로 루프를 끝낼 것이다.

convex_concave.gif

여기 삼각형을 이루는 폴리곤의 정의에 대한 예제가 있다.


var triangleDef:b2PolygonDef = b2PolygonDef()
triangleDef.vertexCount = 3
triangleDef.vertices[0].Set(-1.0, 0.0)
triangleDef.vertices[1].Set(1.0, 0.0)
triangleDef.vertices[2].Set(0.0, 2.0)

정점들은 부모 강체의 좌표체계 안에서 정의된다. 만약 당신이 상위 강체 안에서 폴리곤을 이동시키려면 단지 모든 정점을 이동시키면 된다.

편의를 위해서 폴리곤을 상자로서 초기화하는 함수가 있다. 당신은 강체 원점에 중심을 두는 축 정렬 상자나 강체 원점에서 이동된 상자를 얻을 수 있다.


// aligned

var alignedBoxDef:b2PolygonDef = new b2PolygonDef();
var hx:Number = 1.0; // half-width
var hy:Number = 2.0; // half-height
alignedBoxDef.SetAsBox(hx, hy);
// oriented var orientedBoxDef:b2PolygonDef = new b2PolygonDef(); var center:b2Vec2 = new b2Vec2(-1.5, 0.0); var angle:Number = 0.5 * b2Settings.b2_pi; orientedBoxDef.SetAsOrientedBox(hx, hy, center, angle);

Shape Factory

모양들은 강체 정의의 초기화에 의해 생성되며 상위 강체의 정의에 전달된다.


var circleDef:b2CircleDef = new b2CircleDef();
circleDef.radius = 3.0;
circleDef.density = 2.5;
var myShape:b2Shape = myBody.CreateShape(circleDef);
//[선택적으로 어딘가에 모양 객체를 저장한다]

이것은 모양을 생성하고 강체에 붙인다. 당신은 모양의 포인터를 저장할 필요가 없다. 모양은 상위 강체가 파괴될 때 자동적으로 파괴되므로. (묵시적 파괴를 보라)


당신이 모양을 강체에 붙이는 작업을 마친 후, 당신은 강체의 질량을 자식 모양에 기반해 재계산하기를 원할 것이다.


myBody.SetMassFromShapes()

이 함수는 실행 비용이 크다. 그러므로 당신은 이것을 필요할 때에만 호출해야 한다.

You can destroy a shape on the parent body easily. You may do this to model a breakable object. Otherwise you can just leave the shape alone and let the body destruction take care of destroying the attached shapes.

당신은 상위 강체 위에서 모양을 쉽게 파괴할 수 있다. 당신은 파괴 가능한 물체를 만들 때 이를 행할 것이다. (todo:의불)

myBody.DestroyShape(myShape)

강체로부터 모양이 삭제된 후, 당신은 SetMassFromShapes를 다시 호출하고 싶을 것이다.


Using a Shape 모양의 사용

여기서 할 말은 많지 않다. 당신은 모양의 종류와 그 상위의 강체를 얻을 수 있다. 또한 한 점이 모양 위에 포함되는지를 보기 위해 테스트를 할 수도 있다. 자세한 것은 b2Shape.h를 보라.


미완성. 영어실력이 일천하므로 의역이 대부분입니다. 지적 감사히 받습니다.
개인적인 학습을 위해 작성된 게시물이며 원 저작권은 Box2D 포럼에 있습니다.

매뉴얼의 각 챕터의 번역은 역자의 판단에 따른 중요도 순서대로 진행될 예정입니다.
2012년 12월 현재 원문 매뉴얼은 위키에서 제거되고 PDF화된 매뉴얼이 배포중입니다. 근시일내 PDF에 대한 번역작업을 새로이 진행할 것이며 이하 번역내용은 2009년의 것으로 현재 버전과 다른 점이 있을 수 있음을 유의하시기 바랍니다.

<일러두기>

1>번역기 돌린것보다 조금 나은 수준이지만 의미전달에는 크게 무리가 없다고 생각합니다. 오역 지적, 좀더 나은 의견은 감사히 받습니다.

2>이 글은 아직 작업 진행중입니다. 최종수정 11월 18일

<원문보기>


About 개요


강체는 위치와 속도를 가지며, 당신은 강체에 힘과 토크, 충격량을 가할 수 있다. 강체는 정적이거나 동적일 수 있다. 정적 강체는 절대 움직이지 않으며 다른 정적 강체와 충돌하지도 않는다.

강체는 모양들의 기반이 되며, 강체는 모양들을 세계 안에서 이끌고 다닌다. 강체는 Box2D에서 항상 강체이다.1) 이것은 같은 강체에 붙여진 두 모양이 절대로 서로 상대적인 이동을 할 수 없음을 의미한다.


당신은 일반적으로 당신이 만든 모든 강체의 포인터를 유지할 것이다. 이를 통해, 당신은 그래픽 엔티티의 위치를 갱신하기 위해, 강체의 위치를 확인할 수 있다. 또한 당신이 프로그램을 끝낼 때 모든 강체들을 제거하기 위해서도 그들 모두에 대한 포인터를 유지해야 한다. 2)

Body Definition 강체의 정의


강체가 생성되기 전에 먼저 당신은 강체의 정의를 먼저 생성해야 한다 (b2BodyDef). 당신은 강체의 정의를 스택에 생성하거나 당신의 게임의 자료구조 안에 정리해 둘 수 있다. 선택은 당신의 몫이다.Box2D는 강체의 정의 결과를 복사하며, 그에 대한 포인터를 유지하지 않는다. 이것은 당신이 강체의 정의를 여러 개의 강체를 생성하는
데 재사용할 수 있음을 의미한다.


강체 정의의 몇몇 중요한 멤버를 보러 가자.


Mass Properties 중량 속성


강체의 중량 속성을 확정하는 데는 몇 가지 방법이 있다.

  1. 강체의 정의에 중량 속성을 명시적으로 지정한다.
  2. 강체가 생성된 후 강체의 중량 속성을 명시적으로 지정한다.
  3. 강체에 붙여진 모양들의 밀도에 기반해 중량을 정한다.


많은 게임 시나리오에서는 모양의 밀도에 기반해 중량을 계산한다. 이것은 강체가 일관성있게 적당한 중량을 갖는 것을 보증한다.


그러나 그렇지 않은 게임 시나리오는 특정한 중량 값을 필요로 할 것이다. 예를 들면, 당신은 저울처럼 정확한 중량을 갖도록 조절할 필요가 있는 메커니즘을 사용하는 경우처럼.


You can explicitly set the mass properties in the body definition as follows:

당신은 다음과 같이 강체 정의의 중량을 명시적으로 설정할 수 있다.

bodyDef.massData.mass = 2.0; // 킬로그램 단위 강체 중량
bodyDef.massData.center.SetZero(); // 지역적 질량중심
bodyDef.massData.I = 3.0; // 회전 관성 in kg*m^2.
중량을 설정하는 다른 방법들은 본문의 다른 곳에서 소개할 것이다.


Position and Angle 위치와 각도

강체 정의는 당신에게 강체 생성시의 위치를 초기화할 기회를 준다. 이것은 세계의 원점에 강체를 생성한 후 이동하는 것보다 나은 퍼포먼스를 보인다.

강체는 두 개의 흥미로운 정점을 갖는다. 첫째는 강체의 원점이다. 모양들과 조인트는 강체의 원점에 상대적으로 붙여져 있다. 두 번째 흥미로운 정점은 질량중심이다. 질량중심은 강체에 붙여진 모양들의 질량 분포에서 결정되거나, b2MassData를 통해 명시적으로 지정할 수 있다. Box2D의 내부적 연산 대부분은 질량 중심을 사용한다. 예를들면 b2Body는 질량중심을 위해 선형 속도를 저장한다.(For example b2Body stores the linear velocity for the center of mass.)


당신이 강체 정의를 구성할 때는 질량중심이 어디에 위치할 것인지 알지 못할 것이다. 그러므로 당신은 강체의 원점을 질량중심으로서 간주한다(오역소지). 또한 강체의 각도를 라디안으로 지정할 것이다. 이는 질량중심의 위치에 영향을 받지 않는다.

당신이 나중에 강체의 중량을 변경한다면 질량중심이 강체 위에서 이동할 것이다. 그러나 원점은 움직이지 않으며 붙여진 모양과 조인트들도 움직이지 않는다.


bodyDef.position.Set(0.0, 2.0); // 강체의 원래 위치.
bodyDef.angle = 0.25 * b2Settings.b2_pi; // 호도법상 강체의 각도.


Damping 제동

제동은 강체의 속도를 줄이는 데 사용된다. 제동은 마찰과는 별개인데, 왜냐하면 마찰은 오직 충돌시에만 일어나고 제동은 마찰보다 시뮬레이션 비용이 적게 든다. 그러나 제동은 마찰을 대체할 수 없으며 두 가지 효과는 함께 사용되어야 한다.

제동 인자는 0과 무한대 사이에 있어야 한다. 0은 제동을 하지 않음을 의미하고 무한대는 최대한 제동을 거는 것을 의미한다. 일반적으로 당신은 0~1.0사이의 제동 값을 사용할 것이다. 나는 일반적으로 선형 제동을 사용하지 않는데 이것은 강체가 떠다니는 것처럼 보이기 떄문이다.


bodyDef.linearDamping = 0.0;
bodyDef.angularDamping = 0.1;

제동은 안정성과 퍼포먼스를 위해 근사된다. 작은 제동 값에서 제동 효과는 대개 타임스텝에서 독립적이다. 보다 큰 제동 값에서 제동 효과는 타임스텝에 따라 달라질 것이다. 이것은 당신이 고정된 타임스텝을 사용할 경우에는 별 문제가 되지 않는다. (이를 권장한다.)


Sleep Parameters 수면 인자

What does sleep mean? Well it is expensive to simulate bodies, sothe less we have to simulate the better. When a body comes to rest wewould like to stop simulating it.

수면이란 무엇을 의미하는가? 글쎄, 이것은 강체를 시뮬레이션하는 것의 확장이며, ....강체가 휴지상태가 될 때 우리는 그것을 시뮬레이션하지 않을 것이다.


Box2D가 강체(또는 강체의 묶음)을 휴지 상태로 만들 때 강체는 매우 작은 CPU오버헤드를 갖는 수면 상태로 들어간다. 만약 살아 움직이는 강체가 잠든 강체와 충돌한다면 잠든 강체가 깨어난다. 또한 강체들은 그들에게 붙여진 조인트나 컨택트가 파괴될 때도 깨어난다. 또한 당신은 수동으로 강체를 깨어나게 할 수 있다.


강체의 정의는 당신을 강체가 잠들 수 있는지, 그리고 강체가 수면 상태에서 생성될지 명시하도록 한다.

bodyDef.allowSleep = true;
bodyDef.isSleeping = false;


Bullets 탄환

게임 시뮬레이션은 보통 약간의 프레임 레이트 안에 재생되는 이미지들의 시퀀스를 생성한다. 이런 설정에서 강체는 한 타임스텝 안에서 먼 거리를 이동할 수 도 있다. 만약 물리 엔진이 큰 동작을 지원하지 않는다면 당신은 몇몇 물체들이 부정확하게 서로를 통과해버리는 것을 보게 될 것이다. 이런 효과를 터널링이라고 부른다.

기본적으로, Box2D는 동적인 강체들이 정적인 강체를 통과하는 터널링을 예방하기 위해 지속적 충톨탐색(continuous collision detection; CCD)를 사용한다. 이것은 모양들이 그들의 이전 위치에서 다음 위치까지 휩쓸고 지나감으로서 실행된다. 엔진은 휩쓰는 동안에 새로운 충돌을 찾는다. 그리고 그 충돌들을 위해 충돌지점(time of impact;TOI)를 계산한다. 강체들은 그들의 첫번째 TOI로 이동하고 최초 타임스텝의 끝까지 시뮬레이트한다. 이 처리 과정은 필요에 따라 반복된다.


일반적으로 CCD는 동적 강체들 간에는 사용되지 않는다. 이것은 퍼포먼스를 유지하기 위해서이다. 몇몇 게임 시나리오에서 당신은 동적 강체에서도 CCD를 필요로 할 것이다. 예를 들면, 당신은 고속의 탄환을 얇은 벽을 향해 발사하는 것을 원할 수도 있다. CCD가 없으면 탄환은 탄환은 벽에 구멍에 난 듯 통과해 버릴 것이다. (역주 : 의역 - the bullet my tunnel through thewall)

고속으로 이동하는 물체를 Box2D에서는 탄환이라 불린다. 당신은 당신의 게임 디자인을 기반으로 어떤 강체가 탄환이 될 것인지 결정해야 한다. 만약 당신이 어떤 강체를 탄환으로 취급하기로 결정했다면 다음과 같은 설정을 사용하라.


bodyDef.isBullet = true;

탄환 플래그는 동적 강체에만 적용된다.


CCD를 사용하는 대가는 비싸고 따라서 당신은 아마 모든 움직이는 강체를 탄환으로 취급하기를 원하지 않을 것이다. 그래서 기본적으로 Box2D는 CCD를 움직이는 강체와 정적 강체 사이에서만 사용한다. 이것은 강체가 당신의 게임 세계에서 벗어나지 않도록 예방하는 효과적인 접근방법 중 하나이다. 그러나 당신은 항상 CCD를 필요로 하는 몇몇 고속이동 강체를 갖고 있을 수도 있다.



Body Factory 강체 팩토리



강체는 세계 클래스에서 제공되는 강체 팩토리에 의해 생성되고 파괴된다. 이것은 세계가 효과적인 할당자를 사용해 강체를 생성하고 세계 자료구조에 추가하도록 한다.

강체는 질량 속성에 의해 동적이거나 정적일 수 있다. 둘 다 같은 생성/파괴 메소드를 사용한다.

var dynamicBody:b2Body = myWorld.CreateBody(bodyDef);
//... do stuff ...
myWorld.DestroyBody(dynamicBody);
dynamicBody = null;


정적 강체는 다른 강체의 영향에 의해서는 움직이지 않는다. 당신은 수동으로 정적 강체를 이동할 수 있지만, 동적 강체가 두 정적 강체 사이에서 찌그러지지 않도록 주의해야 한다. 마찰은 당신이 정적 강체를 이동하는 때는 정확하게 동작하지 않을 것이다. 정적 강체는 스스로 시뮬레이트되지 않으 결코 다른 정적 강체와 충돌을 발생시키지도 않는다. 하나의 정적강체에 몇 개의 모양을 붙이는 것이 하나의 모양을 가진 여러개의 정적 강체를 생성하는 것보다 빠르다. 내부적으로, Box2D는 정적 강체의 질량/질량 역수를 0으로 설정한다. 이것은 수학연산을 종료시키고 대부분의 알고리즘이 정적 강체를특수한 케이스로서 취급할 필요가 없게 한다.


Box2D는 강체 정의에 대한 참조나 그것을 유지하기 위한 어떤 데이터도 갖지 않는다.(유저데이터에 대한 포인터는 예외). 그러므로 당신은 임시적인 강체 정의를 생성하거나 같은 강체의 정의를 재사용할 수 있다.


Box2D는 당신이 b2World객체를 삭제함으로서 강체를 일일이 삭제할 필요를 없게 해주며, 이것은 당신을 위해 완벽한 정리작업을 해준다. 그러나 당신은 당신의 게임엔진 안에서 모든 강체에 대한 참조를 무효화해둬야 함을 유의해야 한다.

당신이 강체를 파괴했을 때, 붙여진 모양들과 조인트들은 자동적으로 파괴된다. 이것은 당신이 모양과 조인트 포인터를 어떻게 관리해야 하는지에 대한 중요한 의미를 내포하고 있다. 상세한 것은 9.2절 묵시적 파괴를 참고하라.


당신은 그라운드와 동적 강체를 조인트로 연결하려 할지도 모른다. 당신은 정적 강체와 연결하는 조인트가 필요할 것이다. 만약 정적 강체를 갖고 있지 않다면 당신은 공유되는 그라운드 강체를 세계 객체로부터 얻을 수 있다. 당신은 정적인 모양을 그라운드 강체에 붙일 수도 있다.


var ground:b2Body = myWorld.GetGroundBody();
//... 그라운드 강체를 사용한 조인트 생성 ...

Using a Body 강체의 사용

강체를 생성한 후에는, 당신이 강체를 동작하게 하는데 쓸 수 있는 여러 연산들이 있다. 그것은 질량 속성을 지정하는 것, 위치와 속도에 접근, 힘의 적용, 점과 벡터를 변환하는 것들을 포함한다.


Mass Data 질량

당신은 실행 시간에 강체의 질량값을 조절할 수 있다. 이것은 일반적으로 당신이 강체에서 모양을 생성하거나 파괴할 때 완료된다. 당신은 현재의 모양들에 기반해 강체의 질량을 설정하길 원할 것이다.

b2Body.SetMassFromShapes():void;


또한 당신은 직접 질량을 설정하길 원할수도 있다. 예를 들면, 당신이 직접 모양을 변경하지만 당신 고유의 질량 수식을 사용하려는 것처럼.


b2Body.SetMass(massData:b2MassData):void;

강체의 질량은 다음 함수를 통해 사용할 수 있다.
b2Body.GetMass():Number;
b2Body.GetInertia():Number;
b2Body.GetLocalCenter():b2Vec;

State Information 상태 정보

강체의 상태에는 여러가지 국면이 있다. 당신은 이 상태 데이터에 다음 함수들을 사용해 효과적으로 접근할 수 있다.


b2Body.IsBullet():Boolean;
b2Body.SetBullet(flag:Boolean):void;
b2Body.IsStatic():Boolean
b2Body.IsDynamic():Boolean;
b2Body.IsFrozen():Boolean;
b2Body.IsSleeping():Boolean;
b2Body.AllowSleeping(flag:Boolean):void;
b2Body.WakeUp():void;


The bullet state is described in Bullets. The frozen state is described in World Boundary.

탄환 상태는 탄환일 경우에만 기술된다. 냉각 상태는 세계 경계 밖에 있을 때 기술된다.


Position and Velocity 위치와 속도

당신은 강체의 위치와 회전값에 접근할 수 있다. 이것은 일반적으로 당신의 게임 액터가 렌더링 될 때 이다. 또, 당신이 평범하게 이동을 시뮬레이션 하는 데 Box2D를 사용하는 이상 흔하지 않은 경우이지만. 위치를 지정할 수 도 있다.


SetXForm(position:b2Vec2, angle:Number):Boolean;
GetXForm():b2XForm;
GetPosition():b2Vec2;
GetAngle():Number;

당신은 세계 좌표 위에서의 질량중심에 접근할 수 있다. Box2D의 내부적인 시뮬레이션 대부분은 질량중심을 사용한다. 그러나 당신은 일반적으로는 이에 접근할 필요가 없다. 대신 당신은 보통 강체의 변환값을 가지고 작업하게 될 것이다.

GetWorldCenter():b2Vec2;

당신은 선형속도와 각속도에 접근할 수 있다. 선형 속도는 질량중심을 위한 것이다.

function SetLinearVelocity(v:b2Vec2):void;
function GetLinearVelocity():b2Vec2;
function SetAngularVelocity(omega:Number):void;
function GetAngularVelocity():Number;

Forces and Impulses 힘과 충격량

You can apply forces, torques, and impulses to a body. When youapply a force or an impulse, you provide a world point where the loadis applied. This often results in a torque about the center of mass.

당신은 힘과 토크, 충격량을 강체에 적용할 수 있다. 상신이 힘이나 충격량을 적용할 때 당신은 이 부하가 적용될 세계 좌표를 지정해야 한다. 이것은 토크의 경우 대개 질량 중심에 해당한다.This often results in a torque about the center of mass. [todo:의역제거]


ApplyForce(force:b2Vec2, point:b2Vec2):void;
ApplyTorque(float32 torque):void;
ApplyImpulse(impulse:b2Vec2, point:b2Vec2):void;

Applying a force, torque, or impulse wakes the body. Sometimes thisis undesirable. For example, you may be applying a steady force and want to allow the body to sleep to improve performance. In this caseyou can use the following code.

힘과 토크 또는 충격의 적용은 강체를 깨운다. 때떄로 이것은 바람직하지 않다. 예를 들면, 당신은 지속적인 힘을 적용하고 ....[todo:빠진것]

이 경우에 당신은 다음과 같은 코드를 사용할 수 있다.


if (myBody.IsSleeping() == false)
{
myBody.ApplyForce(myForce, myPoint);
}

Coordinate Transformations 좌표변환

강체 클래스는 지역공간과 세계공간 사이에서 점과 벡터를 변환하는데 도움을 주는 유틸리티 함수를 몇 개 갖고 있다. 만약 당신이 이 개념을 이해하지 못한다면, Jim Val Verth와 Lars Bishop이 쓴 "게임과 상호작용적 애플리케이션을 위한 수학의 정수;Essential Mathematics for Games and Interactive Applications"를 읽기 바란다. 이들 함수는 효율적이므로 이들의 사용에는 비용이 들지 않는다.


GetWorldPoint(localPoint:b2Vec2):b2Vec2;
GetWorldVector(localVector:b2Vec2):b2Vec2;
GetLocalPoint(worldPoint:b2Vec2):b2Vec2;
GetLocalVector(worldVector:b2Vec2):b2Vec2;

Lists 열거

당신은 강체의 모양들을 열거할 수 있다. 이것은 주로 모양의 사용자 데이터에 접근할 필요가 있을 때 유용하다.

for (var s:b2Shape = body.GetShapeList(); s; s = s.GetNext())
{
var data:MyShapeData = s.GetUserData() as MyShapeData;
... do something with data ...
}

강체의 조인트 목록도 비슷한 방식으로 열거할 수 있다.




역주-

  1. Body는 엄밀히 말해서 굳고 무른 정도에 관계없이 물체를 지칭하지만 적당한 대안 단어가 없고, Box2D안에서 모든 물체는 모든 힘에 대해 형태가 변하지 않는 강체이기 떄문에 처음부터 Body를 강체로 번역했다.
  2. ActionScript 버전은 해당되지 않는 내용이다.


2012년 12월 현재 원문 매뉴얼은 위키에서 제거되고 PDF화된 매뉴얼이 배포중입니다. 근시일내 PDF에 대한 번역작업을 새로이 진행할 것이며 이하 번역내용은 2009년의 것으로 현재 버전과 다른 점이 있을 수 있음을 유의하시기 바랍니다.

<일러두기>

번역기 돌린것보다 조금 나은 수준이지만 의미전달에는 크게 무리가 없다고 생각합니다. 오역 지적, 좀더 나은 의견은 감사히 받습니다.

<원문보기>

About



<Contact>는 모양들 간의 충돌을 관리하기 위한 Box2D객체이다. 서로 다른 종류의 모양들 사이의 접촉을 관리하기 위해 b2Contact에서 파생된 서로 다른 종류의 몇 가지 컨택트가 존재한다. 예를들면 다각형-다각형 충돌을 관리하는 클래스와 원-원의 충돌을 관리하는 클래스가 있다. 이것들은 보통 당신에게는 중요하지 않지만, 적어도 당신이 알고 있을 필요는 있다.


다음에 몇가지 컨택트와 관련된 몇가지 용어가 있다. 이들은 Box2D 특유의 것이지만, 당신은 다른 물리엔진에서도 비슷한 용어들을 찾을 수 있을 것이다.


접점
접점은 두 모양이 접한 위치의 정점이다. 사실 객체들은 표면이 접했을 때 겹치게 되어 있다. Box2D는 적은 수의 접점으로 컨택트를 근사한다.
컨택트 법선
컨택트 법선은 접점을 기준으로 shape1에서 shape2로 향하는 단위 벡터이다.
컨택트 분리
분리는 관통의 반대이다, 분리는 모양들이 겹칠 때 음수가 된다. Box2D의 향후 버전에서는 양의 분리를 갖는 접점이 생성되도록 바뀔 수 있다. 따라서, 당신은 접점이 보고되었을 때 부호를 체크해야 할 지도 모른다.
법선 힘
Box2D는 상호작용적인 충돌처리기를 사용하고 충돌점을 결과와 함께 저장한다. 당신은 충돌 강도를 측정하는 데 안전하게 법선 힘을 사용할 수 있다. 예를 들면, 당신은 법선 힘을 부서지는 물체들에 대해 이벤트를 트리거하거나 충돌 사운드를 재생하는 데 사용할 수 있다.
탄젠트 힘
탄젠트 힘은 충돌 처리기의 마찰력에 대한 근사값이다.
충돌 ID
Box2D는 최초 타임스텝으로부터 추정된 충돌 결과를 다음 타임스텝에서도 재사용하려고 한다. Box2D는 타임스텝에 관계없이 충돌점을 확인하기 위해 충돌 ID를 사용한다. ID들은 한 충돌점을 다른 것들과 구별하게 해 주는, 기하학적 요소의 색인을 갖고 있다.

충돌들은 두 AABB(축정렬 경계상자)가 겹칠 때 생성된다. 때때로 충돌 필터는 컨택트의 생성을 막을 것이다. Box2D는 가끔, 충돌이 필터링되더라도 컨택트를 생성할 필요가 있다. 이 경우 컨택트의 발생을 막는 b2NullContact가 사용된다. 컨택트는 AABB들이 겹치지 않을 때 파괴된다.


그러므로 당신은 닿지 않는(단지 AABB만 닿는) 많은 Contect들을 얻게 된다. 글쎄, 이건 확실하다. 이건 닭과 달걀의 문제이다. 충돌 사실을 분석하기 위한 Contact객체가 만들어질 때까지는, 우리는 Contact객체가 필요할지 필요할지 그렇지 않을지 알 수 없다. 우리는 Shape들이 더 이상 닿지 않으면 즉시 Contact를 지우거나, 또는AABB가 더 이상 겹치지 않을 때까지 두고 볼 수 있었다. Box2D는 후자의 접근방식을 취했다.



Contact Listener

당신은 b2ContactListener를 구현함으로서 충돌 데이터를 얻을 수 있다. 이 리스너는 충돌점이 생성될 때, 그리고 1타임스텝 이상 지속될 때, 그리고 파괴될 때 보고한다.  두 모양이 복수의 충돌점을 가진다는것을 주지하라.

public class MyContactListener extends b2ContactListener
{
public override function Add(point:b2ContactPoint) : void
{
// handle add point
}
 
public override function Persist(point:b2ContactPoint) : void
{
// handle persist point
}
 
public override function Remove(point:b2ContactPoint) : void
{
// handle remove point
}
 
public override function Result(point:b2ContactResult) : void
{
// handle results
}
};

Caution

b2ContactListener에 들어오는 접점에 대한 참조를 만들지 말라. 대신 당신의 버퍼에 접점의 데이터를 깊은 복사로 넘겨라. 아래의 예제가 이를 위한 한가지 방법을 보여준다.
지속적인 물리는 단계적 진행을 사용한다. 그러므로 하나의 접점은 같은 타임스텝에서 추가되고 제거된다. 이는 일반적으로는 문제가 되지 않지만, 당신의 코드는 이를 우아하게 처리해야 한다.


접점은 추가되거나 지속하거나, 제거되는 즉시 보고된다. 이것은 처리자가 호출되기 전에 일어난다. 그러므로 b2ContactPoint 객체는 계산된 충격량을 갖지 않는다. 그러나 당신이 접촉시의 충격량을 어림할 수 있도록 접점에서의 상대속도가 제공된다. 만약 당신이 Result 함수를 구현했다면, 처리자가 호출된 이후의 실질적인 접점에 대한 b2ContactResult객체를 받을 것이다. 이들 결과 구조체는 하위 스텝의 충격량을 포함한다. 다시 말하면, 연속적인 물리를 위해 당신은 b2World.Step당 생성되는 복수의 점점 당, 복수의 결과를 받게 될 것이다.


이것은 컨택트 콜백 안에서 물리공간을 변화시키도록 게임 로직을 구현하도록 유혹한다. 예를 들면, 당신은 데미지를 를 적용하는 충돌을 보고받고 관련된 행동자와 그것의 강체를 파괴하려고 시도할 것이다. 그러나 Box2D는 당신이 콜백 안에서 물리공간을 변화시키도록 허용하지 않는다. 왜나하면 당신이 현재 Box2D가 처리하고 있는 물체를 파괴할 수 도 있고, 이것은 포인터를 고아로 만들기 때문이다.


접점 처리에 대한 추천할만한 관례는, 당신이 처리할 모든 접점을 버퍼에 넣고 해당 타임스텝이 끝난 다음에 처리하는 것이다. 당신은 항상 접점들을 타임스텝이 끝난 후에 곧바로 처리해야 한다. 그렇지 않으면 다른 클라이언트 코드가 물리공간을 변화시켜 놓을 것이고, 접점 버퍼가 쓸모없어지기 때문이다. 당신이 접점 버퍼를 처리할 때는 물리 공간을 변화시킬 수 있지만, 접점 버퍼에 고아가 된 포인터를 넣지 않도록 당신은 여전히 주의해야 한다.

아래의 코드는 충돌 처리 테스트(test_CollisionProcessing.py)를 포팅한 것 중에서 발췌한 것이며, 어떻게 접점 버퍼를 처리하는 중에 고아가 된 강체를 어떻게 처리하는지 보여준다.


// 우리는 접점에 관련된 몇 강체를 파괴할 것이다.
// 우리는 파괴되어야 하는 강체들을 버퍼에 넣어야 한다.
// 왜냐하면 그것들은 복수의 접점에 속해있을 것이므로.
var k_maxNuke:int = 6
var nuke:Array = new Array();
var nukeCount:int = 0

 
// 충돌 결과를 통과시킨다.
// 보다 더 무거운 강체에 닿은 강체를 파괴한다.
for each(var point:ContactPoint in contactPoints)
{

var body1:b2Body = point.body1.GetBody();
var body2:b2Body = point.body2.GetBody();
var mass1:Number = body1.GetMass();
var mass2:Number = body2.GetMass();
 
if(mass1 > 0.0 and mass2 > 0.0){
if(mass2 > mass1){
nuke_body = body1;
} else {
nuke_body = body2;
}
if (nuke.indexOf(nuke_body) == -1){
nuke.push(nuke_body);
if(nuke.length == k_maxNuke)
break;
}
}
}


// 강체를 파괴한다. 중복된 것은 넘어간다.
for each(var b:b2Body in nuke){
trace("Nuking:", b);
self.world.DestroyBody(b);
}


Contact Filtering

당신은 종종 게임 안의 모든 물체가 충돌을 일으키는 것을 바라지 않을 것이다. 예를 들면 당신은 정해진 캐릭터만 통과할 수 있는 문을 만들고 싶을 수도 있다. 이것을 컨택트 필터링이라 부른다. 일부 상호작용이 걸러지기 때문이다.


Box2D는 당신이 b2ContactFilter 클래스를 구현함으로서 커스텀 필터를 얻는 것을 허용한다. 이 클래스는 당신이 두 개의 b2Shape포인터를 받는 ShouldCollide 함수를 구현할 것을 요구한다. 당신이 구현할 함수는 두 모양이 충돌한다면 참을 반환하는 것이다.


ShouldCollide의 기본적인 구현은, 모양 챕터의 필터링 섹션에 구현된 b2FilterData를 사용한다.


public class b2ContactFilter
{
 
/// Return true if contact calculations should be performed between these two shapes.
/// @warning for performance reasons this is only called when the AABBs begin to overlap.
public virtual function ShouldCollide(shape1:b2Shape, shape2:b2Shape) : Boolean{
var filter1:b2FilterData = shape1.GetFilterData();
var filter2:b2FilterData = shape2.GetFilterData();
 
if (filter1.groupIndex == filter2.groupIndex && filter1.groupIndex != 0)
{
return filter1.groupIndex > 0;
}
 
var collide:Boolean = (filter1.maskBits & filter2.categoryBits) != 0 && (filter1.categoryBits & filter2.maskBits) != 0;
return collide;
}
 
static public var b2_defaultFilter:b2ContactFilter = new b2ContactFilter();
 
};


미완성. 영어실력이 일천하므로 의역이 대부분입니다. 지적 감사히 받습니다.
개인적인 학습을 위해 작성된 게시물이며 원 저작권은 Box2D 포럼에 있습니다.

매뉴얼의 각 챕터의 번역은 역자의 판단에 따른 중요도 순서대로 진행될 예정입니다.
원문보기
2012년 12월 현재 원문 매뉴얼은 위키에서 제거되고 PDF화된 매뉴얼이 배포중입니다. 근시일내 PDF에 대한 번역작업을 새로이 진행할 것이며 이하 번역내용은 2009년의 것으로 현재 버전과 다른 점이 있을 수 있음을 유의하시기 바랍니다.




개요


조인트는 강체들을 세계에, 또는 서로에게 속박시키는데 사용된다. 래그돌, 시소, 풀리 등이 게임에서 사용되는 전형적인 예이다. 조인트는 흥미로운 동작들을 만들기 위한 여러가지 방법을 내포하고 있을 수 있다. 어떤 조인트는 동작의 범위를 조절하기 위한 한계를 제공한다. 어떤 조인트는 지정된 토크, 속도로 동작하는 모터를 제공한다. 모터는 여러가지 방법으로 사용될 수 있다. 당신은 조인트의 속도를 지정함으로서 강체의 현재 위치로부터 원하는 위치 사이의 비율을 조절하는 데 모터를 사용할 수 있다 또한 당신은 모터의 속도를 0에 가깝게 낮도록, 그러나 출력은 최대로 지정함으로서 조인트의 마찰을 흉내내는 데에도 모터를 사용할 수 있다. 그럴 경우 충분한 하중이 가해지지 않으면 움직이지 않고 제자리를 지키려고 할 것이다.


조인트의 정의
각 조인트의 정의는 b2JointDef로부터 유도된다. 모든 조인트는 두개의 서로 다른 강체 사이에 연결된다. 한 개의 강체는 정적일 것이다(?). 당신이 메모리를 낭비하고 싶다면 두 개의 정적 강체 사이에 조인트를 만들면 된다 :)

당신은 모든 형태의 조인트에 연동 데이터(user data:사용자 지정)를 지정할 수 있으며, 연결된 강체가 서로 충돌하지 않도록 클래그를 제공할 수 있다. 이것은 사실 기본적인 행동이며 당신은 두 강체 사이의 충돌을 허용할 것인지, collidDConnected 부울 값을 지정해야만 한다.

대부분의 조인트의 정의는 당신이 약간의 기하 데이터를 제공할 것을 요구한다. 대개 조인트는 anchor point로서 정의된다. 연결된 강체를 고정해두는 점들이 있다. Box2D는 그런 점들이 로컬 좌표에 지정될 것을 요구한다. 그러함으로서, 게임이 저장되었다가 다시 불러졌을 때 일반적으로 발생하는 현재 강체의 변환이 조인트의 구속과 충돌할 경우에도 조인트가 지정될 수 있다. 또한, 일부 조인트의 정의는 두 강체 사이의 기본적인 상대적 각도를 알아야 한다고 요구한다.


거리 조인트
가장 단순한 조인트 중의 하나는 두 개의 강체를 잇는 점들의 거리가 일정함을 의미하는 거리 조인트이다. 당신이 거리 조인트를 지정할 때 두 개의 강체는 이미 존재하고 있어야 한다. 그럴 경우 당신은 월드좌표 안에 두 개의 앵커(anchor)를 정의하게 된다. 한 앵커 포인트는 body1에 연결되며, 두번째 앵커 포인트는 body2에 연결된다. 이 포인트들은 구속된 거리의 길이를 의미한다.
distanceJoint.gif
여기 거리 조인트 정의의 한 예가 있다. 이 케이스에서 우리는 강체의 충돌을 허용할 것을 결정하였다.

var jointDef:b2DistanceJointDef = new b2DistanceJointDef();
jointDef.Initialize(myBody1, myBody2, worldAnchorOnBody1, worldAnchorOnBody2);
jointDef.collideConnected = true;


경첩(revolute) 조인트
경첩 조인트는 두 강체가 일반적인 흔히 경첩(hinge point)이라 불리는 앵커 포인트 하나를 공유하도록 강제한다. 경첩은 두 강체의 상대적 회전에 대해 자유로운 각도를 가지고 있다. 이것은 사잇각(joint angle)이라고 불린다.
revoluteJoint.gif
꺾임을 정의하기 위해 당신은 세계 공간 안에 두 개의 강체와 하나의 앵커 포인트 제공해야 한다. 초기화 함수는 이미 두 강체가 정확한 위치에 있다고 가정한다.
이 예제에서, 두 강체는 첫번째 강체의 질량중심에 경첩 조인트로 연결된다.
var jointDef:b2RevoluteJointDef = new b2RevoluteJointDef();
jointDef.Initialize(myBody1, myBody2, myBody1->GetWorldCenter());


경첩 조인트의 각도는 body2가 이음매에 대해서 시계반대 회전을 할 때 양의 값이다. Box2D의 모든 각도와 같이 경첩의 각도 역시 라디안으로서 측정된다. 관례적으로 경첩 각도는 Initialize()에 의해 생성되었을 때, 현재 두 강체의 회전값에 관계없이 0 이다.

몇 가지 경우에 당신은 사잇각을 조절하고 싶을 것이다. 이를 위해, 경첩 조인트는 조인트 한계와 모터를 선택적으로 시뮬레이션할 수 있다.(?)

조인트 한계는 사잇각이 최저값과 최대값 사이를 유지하도록 강제한다. 한계는 충분히 토크가 강할 때 적용된다. 한계범위는 0을 포함해야 한다. 그렇지 않으면 시뮬레이션이 시작되었을 때 조인트가 비틀거릴 수 있다.

조인트 모터는 당신이 조인트의 속도(시간에 대한 각도 변화)를 지정할 수 있도록 허용한다. 속도는 양수이거나 음수일 수 있다. 모터는 무한한 힘을 가질 수 있다. 그러나 이것은 당신이 들어본 표현식 중엔 일반적으로 바람직하지 않다. (???)

경고

"움직일 수 없는 물체에 불가항력이 가해졌을 때 무슨 일이 일어나는가?"

나는 당신에게 적절하지 않다고 말해줄 수 있다.(?) 그러므로 당신은 조인트 모터에 최대 토크를 제공할 수 있다. 조인트 모터는 요구되는 토크가 한계치를 넘지 않는 한 지정된 속도를 유지할 것이다. 최대 토크가 초과되었을 때, 조인트는 느려지거나 그 반대가 될 수 있다.

당신은 조인트 모터를 조인트의 저항력을 흉내내는데 사용할 수 있다. 단지 조인트의 속도를 0으로 지정하고, 최대 토크를 조금 작지만 의미있는 값으로 지정하는 것 만으로. 모터는 조인트가 회전하는것을 방해하려고 시도할 것이다. 그러나 적절한 부하에는 굴복할 것이다.

여기에 이전의 경첩 조인트 정의의 수정본이 있다. 이번에는 조인트가 한계점을 가지며 모터가 동작한다. 모터는 저항력을 흉내내기 위해 설정되었다.
var jointDef:b2RevoluteJointDef = new b2RevoluteJointDef();
jointDef.Initialize(body1, body2, myBody1.GetWorldCenter());
jointDef.lowerAngle = -0.5 * b2Settings.b2_pi; // -90 degrees
jointDef.upperAngle = 0.25 * b2Settings.b2_pi; // 45 degrees
jointDef.enableLimit = true;
jointDef.maxMotorTorque = 10.0;
jointDef.motorSpeed = 0.0;
jointDef.enableMotor = true;





기둥(Prismatic) 조인트

기둥 조인트는 특정 축에 대한 두 강체 사이의 상대적인 변환을 허용한다. 기둥 조인트는 상대적인 회전을 방해한다. 그러므로, 기둥 조인트는 특정 각도에 대해서만 자유롭다.(?)

prismaticJoint.gif
기둥 조인트의 정의는 경첩 조인트의 정의와 유사하다. 단지 substitute translation for angle and force for torque(불명). 이 유사성을 통해  조인트 한계와 저항력을 갖는 기둥 조인트의 정의의 예제가 제공된다.
var worldAxis:b2Vec2 = new b2Vec2(1.0, 0.0);
var jointDef:b2PrismaticJointDef = new b2PrismaticJointDef();
jointDef.Initialize(myBody1, myBody2, myBody1.GetWorldCenter(), worldAxis);
jointDef.lowerTranslation= -5.0;
jointDef.upperTranslation= 2.5;
jointDef.enableLimit = true;
jointDef.maxMotorForce = 1.0;
jointDef.motorSpeed = 0.0;
jointDef.enableMotor = true;



경첩 조인트는 스크린 밖으로 나오는 가상의 축을 가지고 있다. 기둥 조인트는 스크린에 평행한, 명백한 축을 필요로 한다. 이 축은 두 강체와 그들의 움직임을 고정한다.
경첩 조인트와 같이, Initialize()를 사용하여 초기화 되었을 때 기둥 조인트의 변환은 0이다. 그러므로 당신이 정한 최저,최대 변환값 한계 사이에 0이 있음은 명백하다.


활차 조인트

활차는 가상의 도르래를 만들기 위해 사용된다. 활차는 두 강체를 ground를 통해 서로 연결한다. 한 강체가 올라가면 다른 강체는 내려간다. 활차 끈의 총 길이는 초기 구성대로 유지된다.
length1 + length2 == constant

pulleyJoint.gif
당신은 "벽돌과 도르래"를 흉내내기 위한 비율을 제공할 수 있다.(?) 이것은 한 쪽의 활차가 다른 쪽보자 빨리 늘어날 수 있는 원인이 된다. 동시에 한쪽에 작용하는 구속력이 다른 쪽보다 작을 수 있다. 당신은 이것을 기계적인 지레 작용에 사용할 수 있다.
length1 + ratio * length2 == constant

예를 들면, 비율이 2라고 할 때 length1은 length2의 두배로 변화한다. 마찬가지로 body1에 달린 로프에 가해지는 힘은 body2에 달린 로프에 가해지는 힘의 절반이 된다.
활차 조인트는 한쪽이 최대로 늘어났을때 골치아파질 수 있다. 반대쪽의 끈이 0의 길이를 갖게 될 것이다. 이 점에서 구속력의 방정식이 단일 해를 갖게 된다. 그런 까닭에 풀리 조인트는 어느 쪽이든 가능한 다다를 수 있는 최대 길이를 구속한다. 또한, 당신은 게임 플레이상의 이유로 최대 길이를 조절하길 원할지도 모른다. 그래서 최대 길이는 안정적이고 당신에게 제어권을 제공하도록 개선되었다.

여기 도르래의 정의에 대한 한 가지 예가 있다.
var anchor1:b2Vec2 = myBody1.GetWorldCenter();
var anchor2:b2Vec2 = myBody2.GetWorldCenter();
var groundAnchor1:b2Vec2 = new b2Vec2(p1.x, p1.y + 10.0);
var groundAnchor2:b2Vec2 = new b2Vec2(p2.x, p2.y + 12.0);
var ratio:Number = 1.0;
var jointDef:b2PulleyJointDef = new b2PulleyJointDef();
jointDef.Initialize(myBody1, myBody2, groundAnchor1, groundAnchor2, anchor1, anchor2, ratio);
jointDef.maxLength1 = 18.0;
jointDef.maxLength2 = 20.0;



기어 조인트
만약 당신이 정교한 기계장치를 만들고 싶다면, 당신은 기어를 사용하려고 할 것이다. 기본적으로, 당신은 Box2D에서 톱니바퀴 이빨을 가진 복합 형체를 사용함으로서 기어를 생성할 수 있다. 이것은 매우 효율적이지 못하며 제작자를 짜증나게 한다. 또한 당신은 톱니 메시가 부드럽게 정렬되도록 주의해야 한다. Box2D는 기어 조인트라는, 기어를 만들기 위한 간단한 방법을 가지고 있다.
gearJoint.gif
당신은 역시 두 강체를 경첩 또는 기둥 조인트로서 ground에 연결해야 한다. 당신은 어떤 조인트들의 조합이라도 사용할 수 있다. 또한, Box2D는 ground에 이어진 경첩,기둥 조인트가 body1에 생성될 것을 요구한다.

활차의 비율과 마찬가지로, 당신은 기어의 비율을 지정할 수 있다. 그러나, 이번 케이스에는 기어의 비율이 음수일 수 있다. 역시 한 조인트가 경첩(각도)이고 다른 조인트가 기둥(변환)일 때를 주의하라. 그러므로 기어의 비율은 길이 이상의 일정한 단위를 가진다(?)
(therefore the gear ratio will have units of length or one over length. 부정)
coordinate1 + ratio * coordinate2 == constant

여기 기어 조인트의 한가지 예가 있다.
var jointDef:b2GearJointDef = new b2GearJointDef();
jointDef.body1 = myBody1;
jointDef.body2 = myBody2;
jointDef.joint1 = myRevoluteJoint;
jointDef.joint2 = myPrismaticJoint;
jointDef.ratio = 2.0 * b2Settings.b2_pi / myLength;

주목할 점은 기어 조인트가 두개의 다른 조인트에 의존하고 있다는 것이다. 이것은 나쁜 상황을 만든다. 만약 그 조인트들 중 하나가 지워지면 어떻게 될까?

경고
항상 기어 조인트를 경첩,기둥 조인트보다 먼저 제거해야 한다. 그렇지 않으면 기어 조인트의 고아가 된 포인터들로 인해 당신의 코드는 잘못된 방향으로 치달을 것이다.(역주:이것은 C++코드에 해당하는 표현으로 as의 릴리스 빌드에서는 단지 아무일도 일어나지 않게 될 것이다.) 또한 당신은 강체에 연관된 무언가(그것이 무엇이든)를 지우기 전에 먼저 기어 조인트를 제거해야 한다.

----------------------------------------

Joint Factory

조인트는 월드의 팩토리 메소드에 의해 생성/파괴되어야 한다. 이것은 오래된 이슈를 상기시킨다.

경고
강체나 조인트를 스택 또는 힙에 new 또는 malloc을 사용해 생성하려고 하지 말라. 당신은 반드시 b2World클래스의 생성/파괴 메소드를 사용해 강체와 조인트를 다루어야 한다.

다음에 경첩조인트의 일생이 담긴 예제가 있다.

var jointDef:b2RevoluteJointDef = new b2RevoluteJointDef();
jointDef.body1 = myBody1;
jointDef.body2 = myBody2;
jointDef.anchorPoint = myBody1.GetCenterPosition();
var joint:b2RevoluteJoint = myWorld.CreateJoint(jointDef);
... do stuff ...
myWorld.DestroyJoint(joint);
joint = null;

포인터가 파괴된 후에는 항상 초기화시켜 두는 것이 좋다. 당신이 포인터를 재사용하려고 했을 때 프로그램의 크래시를 통제된 방법으로 처리할 수 있게 해준다.

조인트의 일생은 단순하지 않다. 이 경고에 주의하라.

경고
조인트는 연결된 강체가 파괴될 때 같이 파괴된다.
이 예방책은 항상 필요하진 않다. 당신은 당신의 게임 엔진에 대해, 조인트들이 항상 연결된 강체들에 앞서 파괴되도록 구성할 수 있다. 이 경우, 당신은 리스너를 구현할 필요가 없다. 자세한 것은 묵시적 파괴를 참조하라.
Using Joints

많은 시뮬레이션들은 조인트를 만들고 그것들이 파괴될 때까지 다시 거들떠보지도 않는다. 그러나 더 풍부한 시뮬레이션을 만들기 위해서, 당신은 조인트 안에 든 유용한 데이터들을 사용할 수 있다.

먼저, 당신은 조인트로부터 강체를 얻거나, 연결점을 얻거나, 사용자 데이터를 얻을 수 있다.

GetBody1():b2Body;
GetBody2():b2Body;
GetAnchor1():b2Vec2;
GetAnchor2():b2Vec2;
GetUserData():*;

모 든 조인트는 반응 힘과 반응 토크 양쪽을 가지고 있다. 그것들은 body2의 연결점에 적용된다. 당신은 반응 힘을 조인트의 파괴나 기타 게임 이벤트를 트리거하는데 사용할 수 있다. 이런 메소드들은 약간의 계산을 필요로 하므로 당신에게 필요없을 때는 호출하지 말라.

function GetReactionForce():b2Vec2;
function GetReactionTorque():Number;