user3110546
user3110546

Reputation: 101

Sprite Kit Keeps calling first If statement

Im programming a sprite kit game and I've got 8 numbers which spawn at the top of the screen and fall to the bottom. each number has different settings, for example if number 1 is called upon it adds 1 to the score, if 5 is called it removes a life. Now this occurs whenever the number comes in contact with the ship, but instead of calling which method it is meant to it calls the first one, so it cools upon score++. Here is my code, hopefully you can understand it.

- (void)didBeginContact:(SKPhysicsContact *)contact
{
    SKPhysicsBody *firstBody, *secondBody;
    if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
    {
        firstBody = contact.bodyA;
        secondBody = contact.bodyB;
    }
    else
    {
        firstBody = contact.bodyB;
        secondBody = contact.bodyA;
    }

     if ((firstBody.categoryBitMask & shipCategory) != 0 &&
        (secondBody.categoryBitMask & DonutCategory) != 0)
    {
        //score
        score ++;
        scorelabel.text = [NSString stringWithFormat:@"%d",score];
        //highscore
        if (score > HighScore) {
            [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:score] forKey:@"HighScore"];
            [[NSUserDefaults standardUserDefaults] synchronize];
            HighScore  = [[NSUserDefaults standardUserDefaults] integerForKey:@"HighScore"];
            highscorelabel.text = [NSString stringWithFormat:@"%.f",HighScore];
        }


    }
    else if ((firstBody.categoryBitMask & shipCategory) != 0 &&
        (secondBody.categoryBitMask & PizzaCategory) != 0)
    {
        //score
        score ++;
        scorelabel.text = [NSString stringWithFormat:@"%d",score];
        //highscore
        if (score > HighScore) {
            [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:score] forKey:@"HighScore"];
            [[NSUserDefaults standardUserDefaults] synchronize];
            HighScore  = [[NSUserDefaults standardUserDefaults] integerForKey:@"HighScore"];
            highscorelabel.text = [NSString stringWithFormat:@"%.f",HighScore];
        }


    }
    else if ((firstBody.categoryBitMask & shipCategory) != 0 &&
        (secondBody.categoryBitMask & ChocolateCategory) != 0)
    {
        //score
        score ++;
        scorelabel.text = [NSString stringWithFormat:@"%d",score];
        //highscore
        if (score > HighScore) {
            [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:score] forKey:@"HighScore"];
            [[NSUserDefaults standardUserDefaults] synchronize];
            HighScore  = [[NSUserDefaults standardUserDefaults] integerForKey:@"HighScore"];
            highscorelabel.text = [NSString stringWithFormat:@"%.f",HighScore];
        }


    }

   else if ((firstBody.categoryBitMask & shipCategory) != 0 &&
        (secondBody.categoryBitMask & SoftCategory) != 0)
    {
        //score
        score ++;
        Life ++;
        scorelabel.text = [NSString stringWithFormat:@"%d",score];
        //highscore
        if (score > HighScore) {
            [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:score] forKey:@"HighScore"];
            [[NSUserDefaults standardUserDefaults] synchronize];
            HighScore  = [[NSUserDefaults standardUserDefaults] integerForKey:@"HighScore"];
            highscorelabel.text = [NSString stringWithFormat:@"%.f",HighScore];
        }

    }

   else if ((firstBody.categoryBitMask & shipCategory) != 0 &&
        (secondBody.categoryBitMask & AppleCategory) != 0)
    {
        Life--;
        lifelabel.text = [NSString stringWithFormat:@"%d",Life];
        if(Life <= 0) {
            SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
            SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size];
            [self.view presentScene:gameOverScene transition: reveal];

        }

    }

   else if ((firstBody.categoryBitMask & shipCategory) != 0 &&
        (secondBody.categoryBitMask & GrapeCategory) != 0)
    {
        //lifes
        Life--;
        lifelabel.text = [NSString stringWithFormat:@"%d",Life];
        if(Life <= 0) {
            SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
            SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size];
            [self.view presentScene:gameOverScene transition: reveal];

        }

    }

   else if ((firstBody.categoryBitMask & shipCategory) != 0 &&
        (secondBody.categoryBitMask & OrangeCategory) != 0)
    {
        //lifes
        Life--;
        lifelabel.text = [NSString stringWithFormat:@"%d",Life];
        if(Life <= 0) {
            SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
            SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size];
            [self.view presentScene:gameOverScene transition: reveal];

        }

    }

   else if ((firstBody.categoryBitMask & shipCategory) != 0 &&
        (secondBody.categoryBitMask & BananaCategory) != 0)
    {
        //lifes
        Life--;
        lifelabel.text = [NSString stringWithFormat:@"%d",Life];
        if(Life <= 0) {
            SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
            SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size];
            [self.view presentScene:gameOverScene transition: reveal];

        }

    }

}

Here is the ship and number 1 physics

-(void)addShip
{
    //initalizing spaceship node
    ship = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
    [ship setScale:0.5];
    ship.zRotation = - M_PI / 2;

    //Adding SpriteKit physicsBody for collision detection
    ship.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ship.size];
    ship.physicsBody.categoryBitMask = shipCategory;
    ship.physicsBody.dynamic = YES;
    ship.physicsBody.contactTestBitMask = DonutCategory | PizzaCategory | ChocolateCategory | SoftCategory | AppleCategory | GrapeCategory | OrangeCategory | BananaCategory;
    ship.physicsBody.collisionBitMask = 0;
    ship.physicsBody.usesPreciseCollisionDetection = YES;
    ship.name = @"ship";
    ship.position = CGPointMake(260,30);
    actionMoveRight = [SKAction moveByX:-30 y:0 duration:.2];
    actionMoveLeft = [SKAction moveByX:30 y:0 duration:.2];

    [self addChild:ship];
}

- (void)shoot1 //donut
{
    // Sprite Kit knows that we are working with images so we don't need to pass the image’s                extension
    Donut = [SKSpriteNode spriteNodeWithImageNamed:@"1"];
    [Donut setScale:0.15];
    // Position the Donut outside the top
    int r = arc4random() % 300;
    Donut.position = CGPointMake(20 + r, self.size.height + Donut.size.height/2);


    Donut.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Donut.size];
    Donut.physicsBody.categoryBitMask = DonutCategory;
    Donut.physicsBody.dynamic = YES;
    Donut.physicsBody.contactTestBitMask = shipCategory;
    Donut.physicsBody.collisionBitMask = 0;
    Donut.physicsBody.usesPreciseCollisionDetection = YES;

    // Add the Dount to the scene
    [self addChild:Donut];

    // Here is the Magic
    // Run a sequence
    [Donut runAction:[SKAction sequence:@[
    // Move the Dount and Specify the animation time
    [SKAction moveByX:0 y:-(self.size.height + Donut.size.height) duration:5],
    // When the Dount is outside the bottom
    // The Dount will disappear
    [SKAction removeFromParent]]]];
}

Categories i don't know much about these!

static const uint32_t shipCategory =  0x1 << 1;
static const uint32_t DonutCategory =  0x1 << 2;
static const uint32_t PizzaCategory =  0x1 << 2;
static const uint32_t ChocolateCategory =  0x1 << 2;
static const uint32_t SoftCategory =  0x1 << 2;
static const uint32_t AppleCategory =  0x1 << 2;
static const uint32_t GrapeCategory =  0x1 << 2;
static const uint32_t OrangeCategory =  0x1 << 2;
static const uint32_t BananaCategory =  0x1 << 2;

Upvotes: 1

Views: 343

Answers (2)

Batalia
Batalia

Reputation: 2425

Your bitmasks for all categories other than the ship are the same, so your first if condition is always true.

Change your bitmasks to differ from one another:

static const uint32_t shipCategory =  1;
static const uint32_t DonutCategory =  2;
static const uint32_t PizzaCategory =  4;
static const uint32_t ChocolateCategory =  8;
static const uint32_t SoftCategory =  16;
static const uint32_t AppleCategory =  32;
static const uint32_t GrapeCategory =  64;
static const uint32_t OrangeCategory =  128;
static const uint32_t BananaCategory =  256;

Ensure that the ints are a power of 2. This is for readability of you don't know much about bitmasks.

The bitmasks are 32-bit, so you can use up to 32 categories (231) - in the future, you may want to start using the bitwise operator to easily reflect even high numbers in bit masks, as the other tip here does. So, expanding on your own code, the same values as above would be:

static const uint32_t shipCategory =  0x1 << 0;  // 1
static const uint32_t DonutCategory =  0x1 << 1;
static const uint32_t PizzaCategory =  0x1 << 2;
static const uint32_t ChocolateCategory =  0x1 << 3;
static const uint32_t SoftCategory =  0x1 << 4;
static const uint32_t AppleCategory =  0x1 << 5;
static const uint32_t GrapeCategory =  0x1 << 6;
static const uint32_t OrangeCategory =  0x1 << 7;
static const uint32_t BananaCategory =  0x1 << 8; // 256

Upvotes: 2

molbdnilo
molbdnilo

Reputation: 66371

All your categories are the same value, so they will all give the same result.

Do this instead

enum Category
{
    shipCategory  = 0x1,                      // 00000001 
    donutCategory = shipCategory << 1,        // 00000010
    pizzaCategory = donutCategory << 1,       // 00000100
    chocolateCategory = pizzaCategory << 1,   // 00001000
   // ... and so on ...
};

Upvotes: 0

Related Questions