Search…

Box2D - Phần 5: Joint (Tiếp Theo)

30/09/20203 min read
Giới thiệu các loại joint có sẵn trong Box2D, các khái niệm, vai trò, và ví dụ cụ thể.

Trong bài viết này sẽ giới thiệu về các loại joint sau:

  • Prismatic joint.
  • Distance joint.
  • Rope joint.
  • Gear joint.
  • Line joint.
  • Weld joint.

Điểm lại những gì cần trong bài viết này:

  • Tạo một physics world.
  • Thêm tính năng debug draw để vẽ hình dạng body của các đối tượng.
  • Thêm touchs event.

Prismatic joint

Là loại joint mà các bodies tham gia vào cố định đến nhau, và chúng chỉ có thể di chuyển dọc theo một trục đã định. Prismatic joint có thể đưa ra các giới hạn để các bodies chỉ có thể di chuyển dọc theo các trục trong một phạm vi cụ thể. Cũng có thể đưa các motor giống như revolute joint để cho các bodies di chuyển ở một tốc độ nhất định với một lực nhất định. Sử dụng prismatic joint trong các trường hợp muốn tạo:

  • Thang máy.
  • Di chuyển cố định.
  • Cửa trượt.
  • Pistons

Ví dụ

Trong class HelloWorld thêm phương thức prismaticJoint() để ví dụ cho joint này.

void HelloWorld::prismaticJoint() {	
	b2PrismaticJointDef prismaticJointDef;
	prismaticJointDef.bodyA = m_bodyA;
	prismaticJointDef.bodyB = m_bodyB;
	prismaticJointDef.collideConnected = true;

	prismaticJointDef.localAnchorA.Set(0, 0);
	prismaticJointDef.localAnchorB.Set(0, 0);

	//prismaticJointDef.enableLimit = true;
	//prismaticJointDef.lowerTranslation = 10;
	//prismaticJointDef.upperTranslation = 100;

	//prismaticJointDef.enableMotor = true;
	//prismaticJointDef.maxMotorForce = 50;
	//prismaticJointDef.motorSpeed = -5;

	m_prismaticJoint = (b2PrismaticJoint*)world->CreateJoint(&prismaticJointDef);
}

Distance joint

Đây là một loại joint dùng để duy trị một khoảng cách giữa hai đối tượng. Đối với mỗi body tham gia vào distance joint sẽ chọn ra một local anchors giống như revolute joint. Khoảng cách giữa hai đối tượng tham gia distance joint chính là khoảng cách giữa hai local anchors này.

Ví dụ

Trong class HelloWorld thêm phương thức distanceJoint() để ví dụ cho joint này.

void HelloWorld::distanceJoint() {	
	b2DistanceJointDef distanceJointDef;
	distanceJointDef.Initialize(m_bodyA, m_bodyB, m_bodyA->GetWorldCenter(), m_bodyB->GetWorldCenter());
	m_distanceJoint = (b2DistanceJoint*)world->CreateJoint(&distanceJointDef);
}

Rope joint

Hãy tưởng tượng rằng có một sợi dây chun, có thể kéo dãn nó. Rope joint có tác dụng giống như cái dây chun này.

Ví dụ

Trong class HelloWold thêm phương thức ropeJoint() để ví dụ cho joint này.

void HelloWorld::ropeJoint() {
	b2RopeJointDef ropeJointDef;
	ropeJointDef.bodyA = m_bodyA;
	ropeJointDef.bodyB = m_bodyB;
	ropeJointDef.localAnchorA.Set(0, 0);
	ropeJointDef.localAnchorB.Set(1, 1);
	ropeJointDef.maxLength = 10;
	ropeJointDef.collideConnected = true;
	m_ropeJoint = (b2RopeJoint*)world->CreateJoint(&ropeJointDef);
}

Phân tích

Về cơ bản, rope joint nhìn rất giống với distance joint ở cách khởi tạo cũng như chức năng. Rope joint khác distance joint ở chỗ:

  • Khoảng cách của distance được tính bởi khoảng cách hai điểm local anchor, còn khoảng cách của Rope joint chính là tính chất maxLength của định nghĩa define.
  • Khoảng cách giữa hai đối tượng tham gia distance joint là không thay đổi. Còn với rope joint thì khoảng cách đối đa là maxLenght, và khoảng cách tối tiếu khi hai điểm local anchor trùng nhau.

Gear joint

Một gear joint được tạo ra bằng việc kết hợp giữa một revolure joint với prismatic joint.

Ví dụ

Trong class HelloWorld thêm phương thức gearJoint() để ví dụ về loại joint này.

void HelloWorld::gearJoint() {
	b2RevoluteJointDef revoluteJointDef;
	revoluteJointDef1.Initialize(groundBody, m_bodyA, m_bodyA->GetWorldCenter());  
	revoluteJointDef1.bodyA = groundBody;
	revoluteJointDef1.bodyB = m_bodyA;
	revoluteJointDef1.localAnchorA.Set(0, 0);
	revoluteJointDef1.localAnchorB.Set(0, 0);

	m_revoluteJoint = (b2RevoluteJoint*)world->CreateJoint(&revoluteJointDef);

	b2Vec2 worldAxis = b2Vec2(1.0, 0.0);

	b2PrismaticJointDef prismaticJointDef;
	prismaticJointDef.Initialize(groundBody, m_bodyB, m_bodyB->GetWorldCenter(), worldAxis);
	prismaticJointDef.lowerTranslation = -5.0;
	prismaticJointDef.upperTranslation = 2.5;
	prismaticJointDef.enableLimit = true;
	prismaticJointDef.maxMotorForce = 1.0;
	prismaticJointDef.motorSpeed = 0.0;
	prismaticJointDef.enableMotor = true;

	b2PrismaticJoint* prismaticJoint = (b2PrismaticJoint*)world->CreateJoint(&prismaticJointDef);

	b2GearJointDef gearJointDef;

	gearJointDef.joint1 = m_revoluteJoint;
	gearJointDef.joint2 = prismaticJoint;
	gearJointDef.bodyA = m_bodyA;
	gearJointDef.bodyB = m_bodyB;
	gearJointDef.ratio = 2.0 *PI / (300 / PTM_RATIO);

	m_gearJoint = (b2GearJoint*)world->CreateJoint(&gearJointDef); 

Chú ý

Khi khởi tạo một gear joint, các thành phần kết hợp là revolure joint và prismatic joint phải có body tham gia đầu tiên phải là static body.

ss_1

Weld joit

Là loại joint giúp cho các bodies tham gia vào joint luôn cùng hướng với nhau.

Ví dụ

Trong class HelloWorld thêm một phương thức weldJoint() để ví dụ cho joint này.

void HelloWorld::weldJoint() {
	b2WeldJointDef weldJointDef;
	weldJointDef.Initialize(m_bodyA, m_bodyB, m_bodyA->GetWorldCenter());

	m_weldJoint = (b2WeldJoint*)world->CreateJoint(&weldJointDef);
}

Download

JointExample

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024