Как bodyA и bodyB определяются в SKPhysicsContact?

У меня есть два разных фиксированных SKPhysicsBody в SKScene. Единственная разница между ними - их категория BitMask. Один имеет категорию BitMask 512, другой 1024.

static const u_int32_t kWallCategory = 0x1 << 9;         //512  
static const u_int32_t kStructureCategory = 0x1 << 10;    //1024

В моей программе у меня есть стандартный обработчик контактов, вызываемый из -(void)didBeginContact:(SKPhysicsContact *)contact что начинается:

-(void)handleContact:(SKPhysicsContact*)contact {
     SKPhysicsBody *bodyA = contact.bodyA;
     SKPhysicsBody *bodyB = contact.bodyB;
     int type1 = contact.bodyA.categoryBitMask;
     int type2 = contact.bodyB.categoryBitMask;

В моей программе мне нужно определить вектор контакта между динамическим телом и одним из двух неподвижных тел. Для этого я получаю доступ к свойству contactNormal в SKPhysicsContact.

CGVector c = contact.contactNormal;

Однако я заметил, что контактные векторы были непоследовательными, и я определил, что это потому, что иногда bodyA SKPhysicsContact было фиксированным телом, иногда bodyA было динамическим телом.

Например, когда пуля (динамическое тело) попадает в здание (неподвижное тело) слева, я хочу, чтобы вектор контакта был (-1,0) каждый раз. В настоящее время контактный вектор иногда (-1,0) (слева), а иногда (1,0) (справа) все зависит от того, какой орган contact.bodyA является.

Мой вопрос: при прочих равных условиях (физические свойства и т. Д.), Что определяет, что такое bodyA и что такое bodyB в SKPhysicsContact?

1 ответ

После работы с несколькими аспектами каждого SKPhysicsBody (масса, трение, категория маски и т. д.), я установил, что определение между SKPhysicsContact.bodyA а также SKPhysicsContact.bodyB основывается исключительно на том, когда SKPhysicsBody добавляется на сцену

Пример, чтобы подчеркнуть разницу:

SKPhysicsBody *bullet хиты SKPhysicsBody *building слева.

Случай 1: если *building был добавлен к сцене раньше *bullet, SKPhysicsContact.contactNormal является: (-1,0) Так как SKPhysicsContact.bodyA является *building поэтому контактный вектор где *building связывается с (т.е. слева).

Случай 2: если *building был добавлен на сцену после *bullet, SKPhysicsContact.contactNormal является: (1,0) Так как SKPhysicsContact.bodyA сейчас *bullet поэтому контактный вектор где *bullet связывается с (т.е. справа).

проблема

Так как *bullet а также *building сущности добавляются в разное время в моей программе, мне нужно было реализовать метод, в котором я всегда знал, что SKPhysicsContact.bodyA а также SKPhysicsContact.bodyB были и, что более важно, способ сохранить SKPhysicsContact.contactNormal последовательны.

Решение

Обозначить SKPhysicsBody что вам нужно определить, откуда происходят столкновения и установить physicsBody.categoryBitMask

static const u_int32_t kProjectileCategory = 0x1 << 1;  //Dynamic body 
//Make everything with bitmask > 32 will be set for the fixed bodies
static const u_int32_t kStructureCategory = 0x1 << 10;  //Fixed body

Затем в обработчике контактов:

-(void)handleContact:(SKPhysicsContact*)contact {
//bodyA will be the SKPhysicsBody that was added to the SKScene before bodyB
SKPhysicsBody *bodyA = contact.bodyA;

//bodyB will be the SKPhysicsBody that was added to the SKScene after bodyA
SKPhysicsBody *bodyB = contact.bodyB;

int categoryBitmask1 = contact.bodyA.categoryBitMask;
int categoryBitmask2 = contact.bodyB.categoryBitMask;

CGVector v;

//If the categoryBitmask of bodyA is lower, we will get the contact vector from the Dynamic body, which we don't want
if (categoryBitmask1 < categoryBitmask2)
{
    //Since we always want the contact vector determined FROM the fixed body (higher category bitmask), we have to get the reciprocal contact vector in the case that bodyA is the dynamic (non-fixed) body
    v = CGVectorMake(contact.contactNormal.dx * -1, contact.contactNormal.dy * -1);
} else {
    //If the categoryBitmask
    v = contact.contactNormal;
}
Другие вопросы по тегам