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
và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àybars
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ủasprite2
và body củasprite3
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ủasprite2
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