Reputation: 101
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
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
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