Sprite Kit有时会忽略联系

时间:2014-06-28 12:50:10

标签: xcode5 sprite-kit

Hello开发人员,

我是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角色但是没有工作):< / p>

    _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 & bflyCategory) != 0)
{

    SKNode * energyball = (contact.bodyA.categoryBitMask & 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]];


}

}

提前致谢!

2 个答案:

答案 0 :(得分:0)

我认为你用这条线射击自己:

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

如果我正确理解您的代码,则能量球categoryBitMask永远不会设置为bflyCategory。因此,您总是选择bodyA的节点。由于A和B可以随时依赖于energyBall而改变,因此bodyA在某些时候容易失败。

此外,您之前已经选择了SKPhysicsBody* energyBall,而您应该使用它。这也应该提出一个编译器警告,例如&#34; x阴影局部变量y&#34;因为他们使用相同的标识符(变量名)。

尝试用以下代码替换上面的行:

SKNode* ball = energyball.node;

并将SKNode* energyball的任何用途更改为ball

答案 1 :(得分:0)

即使修复代码,问题仍然存在。但是我现在已经对它进行了更深入的研究,并且可以解释联系如何更好地失败。

似乎能量球只在主角(bfly)远离它时检测到接触。一切都很完美。

然而,如果我朝向它,完全忽略了联系。

就好像能量球正在选择框架的特定部分,或者移动是有效的部分。

我的目标是让这两个精灵接触,无论我朝哪个方向前进,或者它接触的精灵角度是什么。

我的猜测是问题可能出在这些代码行中:

_bfly.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_bfly.frame.size];

energyball.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:energyball.frame.size];
或许我应该尝试其他类型的物理机构?或者问题是在另一个领域?

无论如何,这是我的新代码:

@interface CloudScene () <SKPhysicsContactDelegate>

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

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

中的 - (id)initWithSize:“...”:

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

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

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

最后我的全新的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 & bflyCategory) != 0 &&
    (energyball.categoryBitMask & energyCategory) != 0)
{
    //EDITED HERE

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


}

}

希望有人可以找到这个问题的解决方案,因为我已经在我的代码上苦苦挣扎了8天而现在没有任何结果。

我试着在评论中写这个,但是这个网站太短了,所以我无法解释我的情况深度。

提前再次感谢。