Как 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;
}