Cocos2d-x Physic: Chipmunk Vs Box2D (1/2) - Minn Game

Thực tại, một trong những yếu tố mà Game muốn khoác lên mình để diễn tả thật giống và sinh động nhất về thế giới thực, đan xen với đó là tính giải trí, thư giãn. Phần lớn các game được tạo ra đều mang yếu tố thực tại này ở một mức độ nào đó. Chẳng hạn, dòng game 2D platform cũng đã mang yếu tố vật lý như: body, force, velocity, gravity, collision, vv; mảng 3D mang lại nhiều trải nghiệm về thế giới thực hơn, rất gần gũi với con người do cải tiến đáng kể về mặt đồ họa 3D và vật lý (game GTA-5).

Tuy nhiên, một game engine thuần túy game 2D như Cocos2d-x thì chỉ cần yếu tố vật lý Physics là đã ổn thỏa.

Cocos2d-x hỗ trợ 2 kiểu Physics: Chipmunk và Box2D hay còn có thể gọi là Vật lý mềm và Vật lý cứng (tại sao tôi lại nói như vậy?, sẽ giải thích bên dưới).

Chipmunk

Các thành phần cơ bản

PhysicBody

Một physicBody nắm giữ các thuộc tính của một đối tượng, bao gồm: trọng lượng (mass), ví trí (position), độ quay (moment), vận tốc (velocity) và độ tắt dần (damping). Ta có thể coi đối tượng PhysicBody chính là xương sống cho hình dạng của đối tượng Node (1 Sprite). Các chỉ số quan trọng (một Physic Material):

  • Độ dày đặc (Density)
  • Ma sát (Friction)
  • Độ đàn hồi (Restitution)

Một PhysicBody định nghĩa Shape (hình dạng) cụ thể cho bản thân, nó có thể có nhiều Shape sao cho phù hợp với đối tượng Node. Mỗi một Shape đều có chứa các thuộc tính:

  • Type (loại): hình tròn (Circle), hình hộp (Box), đa giác (Polygon), …
  • Area: Dùng để tính trọng lượng của Body. Độ dày đặc và diện tích sẽ cho ra trọng lượng.
  • Mass: Lượng vật chất mà Body nắm giữ, nó sẽ chịu lực tác động của trọng lực.
  • Moment: Xác định moment cần thiết cho một gia tốc góc.
  • Offset: Sự bù trù trọng lực trung tâm lên tọa độ của Body.
  • Tag: Xác định hình dạng.

(phần lớn các thuộc tính của Shape tôi không đả đụng vào)

Ví dụ: Tạo 1 physicBody box và add vào 1 Sprite.

auto physicsBody = PhysicsBody::createBox(Size(65.0f, 81.0f), PhysicsMaterial(0.1f, 1.0f, 0.0f)); // density, friction, restitution physicsBody->setDynamic(false); auto sprite = Sprite::create("whiteSprite.png"); sprite->setPosition(0f, 0f); addChild(sprite); //apply physicsBody to the sprite sprite->addComponent(physicsBody);

PhysicWorld

Một đối tượng PhysicWorld là đối tượng cốt lõi để mô phỏng Vật lý trong game. Trong Game chỉ nên có và chỉ có một đối tượng PhysicWorld để có thể xử lý mọi sự kiện và vật lý. Một vài thuộc tính quan trọng đi kèm:

  • Gravity: Trọng lực (bạn có thể set tùy ý)
  • Speed: Tốc độ mô phỏng vật lý, mặc định 1.0f
  • UpdateRate: Thiết lập tốc độ update
  • SubStep: Số subStep trong một lần update.

Muốn sử dụng Chipmunk Physic và có PhysicWorld mặc định trong Scene của bạn, cài đặt như sau:

auto scene = Scene::createWithPhysics();

Collision

Va chạm xảy ra khi các PhysicBody tiếp xúc với nhau. Để có thể lắng nghe được các va chạm này giữa 2 vật thể bất kỳ trong PhysicWorld, Cocos2d-x hỗ trợ sự kiện lắng nghe: EventListenerPhyscicsContact. Tuy nhiên, để có thể sử dụng Event này, ta cần có bộ lọc va chạm.

Bộ lọc va chạm

Bộ lọc va chạm cho phép 2 PhysicBody có thể hoặc bị ngăn chặn va chạm với nhau. Nó sử dụng 2 thuộc tính:

  • Category (Loại)
  • Group Bitmask (Nhóm các bitmask)

Các PhysicBody sẽ được phân loại va chạm bằng các hàm (chú ý, các biến integer này nên được đưa về số mũ 2 (1, 2, 4, 8, 16, 32, …):

setCollisionBitmask(int bitmask); // ex: 0x01 (Hệ hexa: 2) setCategoryBitmask(int categoryBitmask); // ex: 0x02 (4)

Nếu 2 PhysicBody cùng bitmask và categoryBitmask, chúng sẽ không va chạm với nhau.

PhysicBody cần đăng ký Event để có thể lắng nghe, như hàm sau

setContactTestBitmask(true);

Contacts / Joints

Một liên kết hình thành giữa 2 Body, ta sẽ gọi là Joint. Hai Body được kết nối với nhau thông qua các Joint như vậy với 2 điểm kết nối (có thể nằm trên body hoặc không). Có nhiều kiểu Joint khác nhau:

  • PhysicsJointFixed: A fixed joint fuses the two bodies together at a reference point. Fixed joints are useful for creating complex shapes that can be broken apart later.
  • PhysicsJointLimit: A limit joint imposes a maximum distance between the two bodies, as if they were connected by a rope.
  • PhysicsJointPin: A pin joint allows the two bodies to independently rotate around the anchor point as if pinned together.
  • PhysicsJointDistance: Set the fixed distance with two bodies
  • PhysicsJointSpring: Connecting two physics bodies together with a spring
  • PhysicsJointGroove: Attach body a to a line, and attach body b to a dot
  • PhysicsJointRotarySpring: Likes a spring joint, but works with rotary
  • PhysicsJointRotaryLimit: Likes a limit joint, but works with rotary
  • PhysicsJointRatchet: Works like a socket wrench
  • PhysicsJointGear: Keeps the angular velocity ratio of a pair of bodies constant
  • PhysicsJointMotor: Keeps the relative angular velocity of a pair of bodies constant
joints.PNG
Các loại Joint.

(cá nhân tôi chưa bao giờ dùng các Joint này trong Chipmunk)

Collision Detection

Khi chúng ta dùng Event như trên kia đã nói để filter va chạm thì khi 2 Body va chạm với nhau ta sẽ xử lý nó ở đâu, Collision Detection sẽ trả lời câu hỏi đó.

Phần lớn, chúng ta sẽ xử lý ngay khi va chạm xảy ra giữa 2 Body với nhau, do vậy thường ta sẽ sử dụng hàm onContactBegin().

bool onContactBegin(PhysicsContact& contact) { auto nodeA = contact.getShapeA()->getBody()->getNode(); auto nodeB = contact.getShapeB()->getBody()->getNode(); if (nodeA && nodeB) { { /* your handle */ } return true; }

Ngoài ra, còn có onContactEnd() để handle khi 2 va chạm kết thúc.

Queries

Checking các body bằng raycast, … (chưa dùng bao giờ, bên Unity thì dùng nhiều hơn), giống như việc các body có khả năng nghe nhìn thế giới vậy :v.

Debug

CollisionProcessing.gif
DrawDebug.

Với Chipmunk rất dễ dàng để hiện thị body tiện cho việc debug, ta viết như sau:

world->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL); // world: PhysicWorld object

Giải thích qua một chút về việc tại sao lại gọi Chipmunk là Vật lý mềm, khi các body được va chạm với nhau thì khi đó, 2 Node (Sprite) di chuyển follow theo body của chúng tiến đến va chạm và cho ta cảm giác chúng có bề mặt mềm nhũn và lún xuống -> bật nảy ra khỏi nhau. Điều này khá tệ do đa phần game không cho phép hiện tượng như thế xảy ra, lúc ta ta sẽ cần đến Box2D (Vật lý cứng, 1 Physic ngoài lề của bên thứ 3).

Có một điều khá hay về Chipmunk là ta không cần phải update Node (Sprite) theo body của nó, Chipmunk sẽ xử lý chúng. Điều này ngược lại so với Box2D, khiến nhiều khi ta muốn quay về Chipmunk =)).

Bài viết xin tạm dừng ở đây, bài tiếp theo sẽ giới thiệu nốt về Box2D (Cocos2d-x Physic: Chipmunk vs Box2D (2/2)), những ưu, nhược điểm khi đối sánh với Chipmunk.

Share this:

  • Twitter
  • Facebook
Like Loading...

Related

Từ khóa » Chipmunk Vs Box2d