Search…

Chipmunk - Phần 1: Giới Thiệu

30/09/20208 min read
Giới thiệu thư viện xử lý vật lý Chipmunk và giới thiệu các khái niệm, thuật ngữ liên quan.

Thư viện xử lý vật lý Chipmunk

Chipmunk là một thư viện hỗ trợ xử lý vật lý 2D, trong đó sẽ giả lập một thế giới với trọng lực, quản lý các đối tượng vật lý với tính chất của chúng như trọng lượng, kích thước, sự ma sát và thực hiện việc tính toán các tương tác vật lý được xảy ra. Người lập trình sẽ ánh xạ sự thay đổi trong thế giới vật lý này tương ứng sự hiển thị của các đối tượng đồ hoạ.

Chipmunk được viết bằng ngôn ngữ C, được tích hợp sâu trong Cocos2d-x nên việc sử dụng tương đối đơn giản.

Một số thuật ngữ và khái niệm

Chipmunk và Box2D đều là các thư viện vật lý 2D. Bộ tính năng của Chipmunk rất giống với Box2D, thậm chí cách làm việc của cả hai cũng tương tự nhau mặc dù thuật ngữ có một số điểm khác biệt.

Space

  • Thế giới vật lý giả lập được tạo ra bởi Chipmunk, trong thế giới này trọng lực được quy định.
  • Các đối tượng vật lý và tính chất của chúng được thêm vào, Chipmunk sẽ dựa vào đó mô phỏng  các hiện tượng theo các điều kiện mà đã được thiết kế (trọng lực, ngoại lực tác động, va chạm giữa các body). Và cập nhật các tọa độ của bodies theo các tọa độ của sprites tương ứng.

Boies và shapes

Để tạo một body, cần thêm vào fixtures (Trong Chipmunk được gọi là Shapes). Shapes chứa hình dạng và tính chất vật lý của một body. Một body có thể có nhiều shapes. Trong chipmunk có hai loại body.

  1. Dynamic body: Là các body có thể di chuyển trong space khi bị tác động bởi một lực.
  2. Static body: Là các body không bao giờ di chuyển.

Các tính chất của shapes:

  1. Friction: Thể hiện cho hai đối tượng trượt trên nhau. Được thiết lập từ mức 0 (rất trơn trượt) đến 1 hoặc cao hơn (không trơn trượt).
  2. Elasticity: Thể thiện độ đàn hồi cho một đối tượng. Được thiết lập từ mức 0 (Không có độ đàn hồi) đến 1 (lực tác động có giá trị không đổi) và khi cao hơn 1 (lực tác động lớn hơn ban đầu).
  3. Density: Thể hiện tỷ trọng, mật độ trong body của đối tượng.
  4. Shape: hình dạng, ví dụ như hình vuông, hình tròn ...

Constraints

Đặc tả sự ràng buộc của các đối tượng vật lý với nhau, ví dụ như mô phỏng một dây xích trong đó các mắt xích sẽ ràng buộc với nhau bởi điểm đầu cuối và không thể tách rời (trừ mắt mở đầu và mắt kết).

Chipmunk và Box2D

  • Chipmunk được viết bằng C, Box2D được viết bằng C ++. Ngoài ra, có một số Chipmunk helper được viết bằng Objective-C có thể được sử dụng nếu trong trường hợp không muốn sử dụng C hoặc C++.
  • Chipmunk không yêu cầu chuyển đổi các điểm đến mét. Do đó, không cần phải sử dụng tỷ lệ point-to-meter (PTM_RATIO) để chuyển đổi tọa độ trong Chipmunk như trong Box2D, điều này góp phần giúp cho code của giảm khả năng bị lỗi và dễ đọc hơn.
  • Code được sử dụng trong Chipmunk thường ngắn gọn hơn.
  • Joints Box2D và constraints Chipmunk có một số khác biệt. Ví dụ: Khi tạo ra một revolute trong Box2D, cũng có thể thiết lập các giới hạn về bao nhiêu joints có thể di chuyển và đặt một động cơ trên joint. Trong Chipmunk, để thực hiện tác dụng tương tự, phải phải sự khó khăn hơn vì Box2D  có các tùy chọn bổ sung. Tuy nhiên, có một vài joints trong Chipmunk có mà Box2D không có.
  • Box2D có một tính năng luôn luôn phát hiện va chạm liên tục ngăn chặn việc các đối tượng (Dynamic body) thâm nhập vào các đối tượng tĩnh (Static bodies) như mặt đất. Trong những trường hợp nhất định, các đối tượng trong Chipmunk có thể bị mắc kẹt trong các đối tượng tĩnh hoặc thậm chí đi qua.

Ưu điểm lớn nhất của Chipmunk là đơn giản cho người mới tiếp cận. Tuy nhiên, một điều không thể chối cãi là cả hai đều cung cấp một cách tuyệt vời về tính năng và dễ sử dụng, đều có một cộng đồng mạnh mẽ.

Ví dụ 

Hãy bắt đầu đơn giản bằng cách tạo ra một scene Chipmunk cơ bản thực hiện theo trình tự:

  •  Tạo ra một Physics World.
  •  Thêm một đối tượng hình tròn, và tạo ra các bức tường xung quanh màn hình để tránh đối tượng được tạo rơi ra khỏi màn hình do tác động của trọng lực.

Khởi tạo Physics World

Đây là nơi sẽ chứa các đối tượng trong trò chơi của bạn (Ở đây là một đối tượng hình tròn) và mô phỏng vật lý. Các file có ban đầu khi khởi tạo project.

  • HelloWorld.h
  • HelloWorld.cpp

Trong file HelloWorld.cpp. Tại phương thức createScene() hiện như sau:

Scene* HelloWorld::createScene()
{
    auto scene = Scene::createWithPhysics();                                 // 1
    scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL); // 2
    Vect gravity(0.0f, 10.0f);                                               // 3
    scene->getPhysicsWorld()->setGravity(gravity);                           // 4
	
    auto layer = HelloWorld::create();

    scene->addChild(layer);

    return scene;
}

Phân tích

  1. Khởi tạo thế giới vật lý.
  2. Có tác dụng vẽ lên màn hình hình dạng của bodies. Tác dụng giống như Debug Draw của Box2D. Dùng để kiểm tra độ chính xác về các thiết kế của bạn do vậy nên thường xuyên sử dụng.
  3. Khởi tạo một giá trị gravity (Trọng lực).
  4. Đặt giá trị trọng lực cho Physics World, giá trị này một vector 2 chiều.

Khởi tạo đối tượng

Bước tiếp theo sau khi tạo thế giới vật lý

  1. Tạo ra bức tường bao quanh màn hình.
  2. Tạo một body physics cho đối tượng và thêm nó vào space.

Trong file HelloWorld.h và HelloWorld.cpp, thêm phương thức addWall() dùng để tạo bức tường xung quanh màn hình.

void HelloWorld::addWall()
{
    Size visibleSize = Director::getInstance()->getVisible();
    
    auto spWall = Sprite::create();                                              // 1
	auto bodyWall = PhysicsBody::createEdgeBox(visibleSize,
                                  PHYSICSBODY_MATERIAL_DEFAULT, 3);              // 2
	bodyWall->getShape(0)->setRestitution(1.0f);                                 // 3
    bodyWall->getShape(0)->setFriction(0.0f);                                    // 4
    bodyWall->getShape(0)->setDensity(1.0f);                                     // 5
    spWall->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));   // 6
    spWall->setPhysicsBody(bodyWall);                                            // 7
    bodyWall->setContactTestBitmask(0x000001);                                   // 8
  	this->addChild(spWall);                                                      // 9
	spWall->setTag(TYPE_WALL);                                                   // 10
}

Phân tích

  1. Khởi tạo một đối tượng có tên là spWall. Đây chính là khung bao bọc màn hình giúp cho các đối tượng được tạo không rơi ra khỏi màn hình.
  2. Tạo hình dạng cho bức tường bao bọc màn hình là hình vuông. Lưu ý các điểm chính sau:
    • Phương thức PhysicsBody::createEdgeBox: Xác định hình dáng của body là hình hộp có dạng rỗng.
    • Tham số visibleSize : Kích thước của hình hộp. Ở đây hình hộp có giá trị chiều dài là visibleSize.width và giá trị chiều rộng là visibleSize.height.
    • Tham số giá trị 3 : Độ dày của bức tường.
  3. Thiết lập giá trị đàn hồi cho body.
  4. Thiết lập giá trị ma sát cho body.
  5. Thiết lập giá trị mật độ, tỷ trọng cho body.
  6. Thiết lập vị trí của body. Ở đây đặt tâm của body vô chính giữa màn hình.
  7. Đặt physics body vô đối tượng wall.
  8. Thiết lập giá trị bitmask. Ở đây sử dụng cho trường hợp các bodies va chạm với nhau. Cần phải thiết lập giá trị bitmask mới có sự va chạm giữa các đối tượng.
  9. Thêm đối tượng wall vào scenen hiện tại.
  10. Đặt giá trị tag cho đối tượng giúp bạn phân biệt được rằng nếu có sự va chạm giữa các bodies.

Dưới đây cũng là một cách tạo ra các bức tường. Bản chất là tạo ra 4 bodies kiểu static có hình chữ nhật.

void HelloWorld::addWall(float &_positionX, float &_positionY, float &_width, float &_height)
{
    Size sizeBox = Size(ccp(_width, _height));

    auto spWall = Sprite::create();
    auto bodyWall= PhysicsBody::createBox(sizeBox, PHYSICSBODY_MATERIAL_DEFAULT);

    bodyWall->getShape(0)->setRestitution(1.0f);
    bodyWall->getShape(0)->setFriction(0.0f);
    bodyWall->getShape(0)->setDensity(1.0f);
    bodyWall->setDynamic(false);

	spWall->setPosition(Point(_positionX, _positionY));
	spWall->setPhysicsBody(bodyWall);
	bodyWall->setContactTestBitmask(0x000001); 
	spWall->setTag(TYPE_WALL);
	this->addChild(spWall);
}

Phân tích

Hàm ở trên có tác dụng tạo ra một body hình hộp đặc, có tham số là lần lượt là vị trí của body trên màn hình và kích thước của hình hộp đó. Với việc tạo ra một khung màn hình gồm 4 cạnh bao quanh: trên, phải, dưới, trái. Kích thước của màn hình là này là visibleSize.

addWall(visibleSize.width / 2, visibleSize.height, visibleSize.width, 1);   // Trên
addWall(visibleSize.width, visibleSize.height / 2, 1,  visibleSize.height); // Phải
addWall(visibleSize.width / 2, 0, visibleSize.width, 1);                    // Dưới
addWall(0, visibleSize.height / 2, 1, visibleSize.height);                  // Trái

Sau khi tạo xong các bức tường. Tiếp đến sẽ tạo ra đối tượng có dạng hình tròn ở một tọa độ xác định trong màn hình.

void HelloWorld::addBall(float &_positionX, float &_postionY)
{
	auto ball= Sprite::create();
	ball->setPosition(_positionX, _positionY);

	auto bodyBall= PhysicsBody::createCircle(100.0f);      // 1
	bodyBall->getShape(0)->setRestitution(1.0f);
	bodyBall->getShape(0)->setFriction(0.0f);
	bodyBall->getShape(0)->setDensity(1.0f);
	bodyBall->setGravityEnable(true);                       // 2
    bodyBall->setDynamic(false);                            // 3

	ball->setPhysicsBody(bodyEnemy); 
	bodyBall->setContactTestBitmask(0x000001); 
	ball->setTag(TYPE_BALL);
	this->addChild(ball);
}

Phân tích

  1. Tạo hình dạng cho body là hình tròn có bán kính là 100.0f.
  2. Set trọng lực của đối tượng là có ảnh hưởng. Nếu không muốn bị ảnh hưởng chỉ việc thay tham số truyền vô là false. Mặc định của Cocos2d-x là true.
  3. Set loại body của đối tượng là static bodies. Mặc định của Cocos2d-x là false.

Build và Run

ss.1

Điểm khác biệt mà dễ dàng thấy nhất giữa Box2D và Chipmunk:

  • Box2D: Tọa độ của sprites bạn sử dụng phải theo tọa độ của bodies.
  • Chipmunk: Tọa độ của bodies phải theo sprites.
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