Search…

Chipmunk - Phần 2: Một Số Thuật Ngữ Và Khái Niệm

30/09/20204 min read
Giới thiệu về một số thuật ngữ và khái niệm khác trong Chipmunk như cách làm cho các bodies di chuyển, cách kiểm tra khi có một va chạm.

Di chuyển một body

Implules và Force

Đây chính là hai cách tác động lực chính lên một body trong Chipmunk.

  • Impulse: Tác động vào body theo thời gian để thay đổi vận tốc của body.
  • Force: Tác động vào body để có thể thay đổi vận tốc ngay lập tức.

Chú ý: Tất cả các lực trên đều tác động vào trung tâm của body. Vì thế khi tác động các lực này lên các body dạng rỗng, body sẽ không di chuyển.

Vect impulse = Vect(0.0f, 1010000.0f); 
Vect offset = Vect(1.0f, 0.0f);

ballBody->applyImpulse(impulse, offset);

Vect force = Vect(0.0f, 1010000.0f);
ballBody->applyForce(force, offset);

Phân tích:

Ở trên đây là các phương thức để tác động lực impules hay force. Ở đây có 3 tham số là implules, force, offset. 

  • impulse force: Là lực tác động ban đầu. 
  • offset: Là lực tác động thêm. Giả sử với ballBody ở trên, giá trị offset được thêm vào có giá trị là (1,0) thì lúc này bars sẽ di chuyển lên đồng thời quay ngược chiều kim đồng hồ. Với giá trị (-1,0) thì sẽ quay ngược chiều kim đồng hồ.
  • Giá trị mặc định của offset là (0,0).
  • Độ lớn lực phụ thuộc vào giá trị mass (khối lượng) của vật thể. Giả sử giá trị mass của body là 1000, chịu tác động một lực impule có giá trị là 100000, điều này có nghĩa là là body của vật sẽ di chuyển với tốc độ 100000/100 = 1000 đơn vị/giây. Xét trên màn hình của thiết bị với đơn vị là pixel, với độ phân giải của màn hình là 1024px thì body cần hơn 10s để di chuyển hết màn hình.

Có thể thiết lập một vận tốc ban đầu cho body để cho chúng di chuyển. Với cách này bạn có thể làm một đối tượng có body dạng rỗng di chuyển.

Ngoài việc tác động một lực vào vật thể để tạo động lực di chuyển, hàm setVelocity có tác dụng làm cho một vật di chuyển với một vận tốc và phương có sẵn:

ballBody->setVelocity(Vec2(10.0f, 10.0f));

Collisions

Va chạm là yếu tố cốt lõi trong thế giới vật lý. Trong Chipmunk, thông qua contact listener với thuộc tính là một hàm được chỉ định, mỗi khi có va chạm xảy ra giữa 2 đối tượng, hàm này sẽ được gọi và logic xử lý khi va chạm xảy ra sẽ thực hiện trong hàm.

Code minh hoạ việc khởi tạo một contactListener

auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

Code minh hoạ hàm xử lý khi 2 đối tượng có sự va chạm

bool HelloWorld::onContactBegin(cocos2d::PhysicsContact& contact) {
    auto spriteA = (Sprite*)contact.getShapeA()->getBody()->getNode(); // 1
    auto spriteB = (Sprite*)contact.getShapeB()->getBody()->getNode(); // 2
   
    int tagA = spriteA->getTag();                                      // 3
    int tagB = spriteB->getTag();                                      // 4
   
    // logic                                                           // 5
    return true;
}

Phân tích:

  • Dòng 1-2: Lấy đối tượng đầu tiên và đối tượng thứ hai trong va chạm.
  • Dòng 4-5: Định danh các đối tượng

Chú ý: Chipmunk chỉ trả về 2 đối tượng xảy ra va chạm, định danh của chúng được xác định thông qua giá trị tag

if((tagA == typeA) || (tagB == typeA)) {
    // code 
}

Filtering collisions

Filtering collisions là cơ chế giúp kiểm soát sự va chạm giữa các đối tượng, với một filtering collisions được cấu hình phù hợp sẽ giới hạn chỉ các đối tượng được chỉ định mới xảy ra va chạm và lược bỏ các đối tượng không liên quan.

Filtering collisions hỗ trợ tối đa 32 nhóm đối tượng được phép va chạm nhau, các nhóm này được xác định là chung nhóm bằng giá trị masking bits. Nếu kết quả phép AND của 2 nhóm khác 0, khi ấy chúng được tính là một nhóm và có sự tương tác va chạm với nhau.

auto sprite = addSpriteAtPosition(Vec2(s_centre.x - 150,s_centre.y));
sprite->getPhysicsBody()->setCategoryBitmask(0x02);    // 0010
sprite->getPhysicsBody()->setCollisionBitmask(0x01);   // 0001

sprite1 = addSpriteAtPosition(Vec2(s_centre.x - 150,s_centre.y + 100));
sprite1->getPhysicsBody()->setCategoryBitmask(0x02);    // 0010
sprite1->getPhysicsBody()->setCollisionBitmask(0x01);   // 0001

auto sprite2 = addSpriteAtPosition(Vec2(s_centre.x + 150,s_centre.y),1);
sprite2->getPhysicsBody()->setCategoryBitmask(0x01);    // 0001
sprite2->getPhysicsBody()->setCollisionBitmask(0x02);   // 0010

auto sprite3 = addSpriteAtPosition(Vec2(s_centre.x + 150,s_centre.y + 100),2);
sprite3->getPhysicsBody()->setCategoryBitmask(0x03);    // 0011
sprite3->getPhysicsBody()->setCollisionBitmask(0x03);   // 0011

Kết quả:

  • Body của sprite và body của sprite1 không va chạm với nhau (đi xuyên qua nhau). Body của sprite2 và body của sprite3 va chạm với nhau.
  • Body của sprite hoặc body của sprite1 đều có xảy ra va chạm với cả body của sprite2 và body của sprite3.

Kiểm tra va chạm đặc biệt là loại filtering collision bằng cách kiểm tra category và collision bitmask

if ((shapeA->getCategoryBitmask() & shapeB->getCollisionBitmask()) == 0
   || (shapeB->getCategoryBitmask() & shapeA->getCollisionBitmask()) == 0)
{
    // code
}

Để bắt các sự kiệm quan tâm đến bodies, shapes hoặc groups bạn có thể sử dụng:

  • EventListenerPhysicsContactWithBodies
  • EventListenerPhysicsContactWithShapes
  • EvnetListenerPhysicsContactWithGroup
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