我在SpriteKit(Obj-C)中检测到多个不同的碰撞时遇到问题

时间:2015-08-17 01:44:03

标签: ios objective-c sprite-kit

我正在使用Objective-C和SpriteKit构建游戏。在这个游戏中,有一些小行星落在玩家身上,他们必须避开它们。小行星每0.5秒产生一次。还有另一种类型的小行星,"黄金小行星"在游戏中使用不同的变量,可以拍摄以获得硬币。

游戏的另一部分涉及购买新的"船舶"通过小行星导航。一艘船具有能够射击常规小行星以摧毁它们以及金色小行星的特殊能力。这就是问题的出发点。

这是检测常规小行星和子弹之间碰撞的代码。许多代码来自Sangony在this StackOverflow帖子上的答案。

NSString *playerImage = [[NSUserDefaults standardUserDefaults]
                         stringForKey:@"playerImage"];

if ([playerImage  isEqual: @"crazyben.png"]) //make sure the ship is the one with the special ability to destroy regular asteroids, not where the issue is
{
    NSLog(@"Crazy Ben Enabled");
    uint32_t collision3 = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);

    if (collision3 == (bulletCategory | asteroidCategory))
    {
        NSLog(@"collision3");
        for (SKSpriteNode * object in self.asteroidArray);
        {
            NSLog(@"for statement");
            if ([contact.bodyA.node.name
                  isEqualToString:[NSString stringWithFormat:@"asteroid-%i", self.asteroidCounter]] ||[contact.bodyB.node.name isEqualToString:[NSString stringWithFormat:@"asteroid-%i", self.asteroidCounter]]) //broken here, it only allows you to detect a collision between the bullet and the asteroid that currently matches up to the "self.asteroidCounter" int
            {
                NSLog(@"crazyhit");
                [self runAction:[SKAction playSoundFileNamed:@"gunshot.mp3" waitForCompletion:NO]];
                [self.bullet removeFromParent];
                [self.asteroid removeFromParent];
            }
        }

    }
}

被破坏的部分是检测碰撞时的部分。使用此代码,您只能销毁与self.asteroidCounter整数相对应的小行星,该星号是最近生成的小行星。如果我删除该行

NSLog(@"for statement");
            if ([contact.bodyA.node.name
                  isEqualToString:[NSString stringWithFormat:@"asteroid-%i", self.asteroidCounter]] ||[contact.bodyB.node.name isEqualToString:[NSString stringWithFormat:@"asteroid-%i", self.asteroidCounter]])

允许它破坏小行星,无论它是否与self.asteroidCounter具有相同的数字,而不是破坏被击中的特定小行星,它似乎只是破坏了屏幕上的随机小行星。

我想要的是实际击中的小行星从父母身上移除。

提前致谢,如果有任何信息缺失或者您想要澄清,我很乐意添加或澄清它。

编辑:我编辑了代码,并通过J. asteroidCounterB = asteroidCounterA - 1,asteroidCounterC = asteroidCounterB - 1添加了asteroidCounter B的变量,依此类推。有了这个,我得到的行为与我用相同的名称处理它们时相同,而不是使用asteroidCounter变量来识别它们。现在我认为问题在于代码

[self.asteroid removeFromParent];

当它这样做时,它不会从父节点中删除特定的小行星,它只是从父节点中删除其中一个。如果我删除所有的asteroidCounter变量(除了原始变量),有没有办法可以说出这样的话?

[self.asteroid-%i removeFromParent];

显然,这不起作用,但如果有办法获得类似的东西会很棒。

2 个答案:

答案 0 :(得分:0)

如果您要为每个节点使用唯一的名称,一种简单的方法是在名称的末尾添加一个数字。

self.objectID++;
myNode.name = [NSString stringWithFormat:@"myNode-%lu",self.objectID];

self.object是一个属性@property (nonatomic) long objectID;

检查您的哪个myNode'对象涉及碰撞,你可以这样做:

if (collision == (bulletCategory | asteroidCategory)) {

    for(SKSpriteNode *object in self.asteroidArray) {
        if(([object.name isEqualToString:contact.bodyB.node.name]) || ([object.name isEqualToString:contact.bodyA.node.name])) {
                // your code
        }
    }
}

答案 1 :(得分:0)

更容易单独测试每个不同的案例。首先设置不同的静态类别位掩码,就像您已经完成的那样

static const uint32_t normalAstroidCategory = 0x1 << 0;
static const uint32_t goldAstroidCategory = 0x1 << 1;
static const uint32_t normalBullets = 0x1 << 2;
static const uint32_t specialBullets = 0x1 << 3;

然后确保您设置正确的项目符号以及CategoryBitMasks。

//Code used for special bullets
specialBullet.categoryBitMask = specialBullet;
specialBullet.contactTestBitMask = normalAstroidCategory | goldAstroidCategory
//Code used for normal bullets
normalBullet.categoryBitMask = normalBullet;
normalBullet.contactTestBitMask = normalAstroidCategory

确保您也为星号设置正确的位掩码

-(void)didBeginContact:(SKPhysicsContact*)contact{
    if (contact.bodyA == normalBullets || contact.bodyB == normalBullets 
        || contact.bodyA == specialBullets || contact.bodyB == specialBullets)
    {
        if (contact.bodyA.categoryBitMask == goldAstroidCategory || contact.bodyB.categoryBitMask == goldAstroidCategory){
            gold++;
        }
    }
}

如果你担心船只与星座碰撞,你可能需要增加额外的逻辑。还尝试在NSUserDefaults中保存船型而不是图像名称,因为它更可靠或使用枚举可能看看船是否属于某种类型