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

У меня есть два разных фиксированных SKPhysicsBody в SKScene. Единственная разница между ними - их categoryBitMask. У одного есть категория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 (масса, трение, categoryBitmask и т.д.) Я убедился, что определение между 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 SKPhysicsContact.bodyA связывается (т.е. право).

проблема

Поскольку в моей программе добавляются объекты *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;
}

licensed under cc by-sa 3.0 with attribution.