Sprite Kit иногда игнорирует контакт

#xcode5 #sprite-kit

#xcode5 #спрайт-набор

Вопрос:

Привет, коллеги-разработчики,

Я новичок в Sprite Kit и только начал внедрять физику в свою игру. У меня есть только два спрайта, которые должны вступить в контакт. Один из них — главный герой, бабочка «bfly», а другой — энергетический шар, который дает здоровье главному персонажу при контакте.

Однако в моей игре происходит что-то странное, несмотря на то, что я реализовал все свои линии, чтобы физика работала, иногда, при определенных условиях, которые я не понимаю, энергетический шар просто проходит прямо через главного героя и игнорирует, что контакт и эффекты, которые реализует контакт, должны произойти. Затем я должен активно искать энергетический шар, чтобы это произошло, и пытаться касаться его несколько раз, чтобы добиться успеха.

Я хочу, чтобы контакт всегда происходил, независимо от того, случайно ли энергия попала в меня, или я активно ее ищу. Когда эти два спрайта каким-либо образом касаются друг друга, должен произойти контакт. Я перепробовал все и, наконец, решил обратиться за помощью.

Вот мой делегат:

 @interface CloudScene () <SKPhysicsContactDelegate>
 

Обратите внимание, что я добавил эти свойства в надежде устранить проблему, но проблема была там до них:

 @property(assign, nonatomic) uint32_t contactTestBitMask;
@property(nonatomic) BOOL usesPreciseCollisionDetection;

static const uint32_t bflyCategory = 0x1 << 0;
static const uint32_t energyCategory = 0x1 << 1;
 

Метод initWithSize:

 self.physicsWorld.gravity = CGVectorMake(0, 0);
self.physicsWorld.contactDelegate = self;
 

Физика обоих (обратите внимание, что столкновения были установлены на 0 раньше, и проблема все еще существовала, я добавил их только в надежде, что эффект отскока, по крайней мере, не позволит мячу пройти прямо через символ bfly, но не сработал) :

     _bfly.name = @"bflyNode";
    _bfly.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_bfly.frame.size];
    _bfly.physicsBody.categoryBitMask = bflyCategory;
    _bfly.physicsBody.contactTestBitMask = energyCategory;
    _bfly.physicsBody.collisionBitMask = bflyCategory | energyCategory;
    _bfly.physicsBody.usesPreciseCollisionDetection = YES;
    _bfly.physicsBody.dynamic = YES;
    _bfly.physicsBody.affectedByGravity = NO;
    _bfly.physicsBody.mass = 1;


energyball.name = @"energyballNode";
energyball.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:energyball.frame.size];
energyball.physicsBody.categoryBitMask = energyCategory;
energyball.physicsBody.contactTestBitMask = bflyCategory;
energyball.physicsBody.collisionBitMask = energyCategory | bflyCategory;
energyball.physicsBody.usesPreciseCollisionDetection = YES;
energyball.physicsBody.dynamic = YES;
energyball.physicsBody.affectedByGravity = NO;
energyball.physicsBody.mass = 1;
 

И, наконец, вот мой метод didBeginContact:

 -(void)didBeginContact:(SKPhysicsContact *)contact{

SKPhysicsBody *bfly;
SKPhysicsBody *energyball;

if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
    bfly = contact.bodyA;
    energyball = contact.bodyB;
}
else
{
    bfly = contact.bodyB;
    energyball = contact.bodyA;
}

if ((bfly.categoryBitMask amp; bflyCategory) != 0)
{

    SKNode * energyball = (contact.bodyA.categoryBitMask amp; bflyCategory) ? contact.bodyB.node : contact.bodyA.node;
    SKAction*energySound = [SKAction playSoundFileNamed:@"Energybell.m4a" waitForCompletion:NO];
    [energyball runAction:energySound];
    energyball.hidden = YES;
    [self addChild:[self FenergyNode:@"energy"]];
    [self adjustScoreBy:2];
    [scoreLabel setText: [NSString stringWithFormat:@"Score: %d", [GameState sharedInstance].score]];
    _bflyHP =MAX(0, _bflyHP 100);
    [energyball runAction:[SKAction removeFromParent]];


}

}
 

Заранее спасибо !

Ответ №1:

Я думаю, вы стреляете себе в ногу этой строкой:

 SKNode * energyball = (contact.bodyA.categoryBitMask amp; bflyCategory) ?
                                            contact.bodyB.node : contact.bodyA.node;
 

Если я правильно понимаю ваш код, energy balls categoryBitMask никогда не устанавливается на bflyCategory . Следовательно, вы всегда выбираете узел bodyA. Поскольку A и B могут измениться в любое время, полагаясь на то, что energyBall всегда является bodyA, в какой-то момент может произойти сбой.

Более того, вы уже выбрали SKPhysicsBody* energyBall ранее, что вы должны были использовать вместо этого. Что также должно вызвать предупреждение компилятора типа «x затеняет локальную переменную y», потому что они используют один и тот же идентификатор (имя переменной).

Попробуйте заменить строку выше на эту:

 SKNode* ball = energyball.node;
 

И измените любое использование SKNode* energyball на ball .