2017-01-08 4 views
1

J'ai deux SKPhysicsBody fixes différentes dans un SKScene. La seule différence entre les deux est leur categoryBitMask. On a un categoryBitMask de 512, l'autre 1024.Comment les bodyA et bodyB sont-ils déterminés dans SKPhysicsContact?

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

Dans mon programme, j'ai un gestionnaire de contact standard appelé de -(void)didBeginContact:(SKPhysicsContact *)contact qui commence:

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

Dans mon programme, je dois déterminer la vecteur de contact entre un corps dynamique et l'un des deux corps fixes. Pour ce faire, j'accéder à la propriété contactNormal du SKPhysicsContact

CGVector c = contact.contactNormal; 

Ce que je remarque, cependant, est que les vecteurs de contact étaient incompatibles et je déterminé c'était parce que parfois Bodya du SKPhysicsContact était le corps fixe, parfois bodyA était le corps dynamique. Par exemple, quand une balle (corps dynamique) frappe un bâtiment (corps fixe) à partir de la gauche, je veux que le vecteur de contact soit (-1,0) chaque fois. Actuellement, le vecteur de contact est parfois (-1,0) (à partir de la gauche) et parfois (1,0) (à partir de la droite) tout dépend de quel corps contact.bodyA est.

Ma question: étant donné que toutes les autres choses sont égales (propriétés physiques, etc.), qu'est-ce qui détermine ce qu'est bodyA et qu'est ce que bodyB dans un SKPhysicsContact?

Répondre

1

Après bricoler avec plusieurs aspects de chaque SKPhysicsBody (masse, friction, categoryBitmask, etc.), je l'ai constaté que la détermination entre SKPhysicsContact.bodyA et SKPhysicsContact.bodyB est basée uniquement lorsque le SKPhysicsBody est ajouté à la scène

Un exemple pour mettre en évidence la différence:

SKPhysicsBody *bullet coups SKPhysicsBody *building de la gauche.

Cas 1: Si *building a été ajouté à la scène avant*bullet, le SKPhysicsContact.contactNormal est: (-1,0) Parce que SKPhysicsContact.bodyA est *building donc le vecteur de contact est où le *building est être mis en contact à partir (à savoir la gauche).

Cas n ° 2: Si *building a été ajouté à la scène après*bullet, le SKPhysicsContact.contactNormal est: (1,0) Parce que SKPhysicsContact.bodyA est maintenant *bullet donc le vecteur de contact est où le *bullet est être mis en contact à partir (à savoir le droit).

Problème

Parce que *bullet et *building entités sont ajoutées à plusieurs reprises dans mon programme, je devais mettre en œuvre une méthode dans laquelle j'ai toujours su ce que SKPhysicsContact.bodyA et SKPhysicsContact.bodyB ont été et, plus important encore, une façon de garder le SKPhysicsContact.contactNormal cohérent.

Solution

Déterminer la SKPhysicsBody que vous devez déterminer où les collisions viennent de et définir le 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 

Ensuite, dans le gestionnaire de contact:

-(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; 
} 
+1

C'est génial. Votre conclusion selon laquelle il faut toujours tester quel corps est ce qui est important (en supposant que cela a de l'importance pour ce que fait votre contact), mais il y a un problème en cours de route: la raison de toujours tester n'est pas difficile Entrez dans la scène. Apple ne promet pas que les corps A et B seront dans * un * ordre déterministe - vous l'avez corrélé à l'ordre de création, mais il n'y a aucune garantie que ce soit la même chose sur tous les appareils et versions OS. – rickster