Sprite Kit检测碰撞?

时间:2013-12-20 09:35:41

标签: iphone ios7 xcode5 sprite-kit

如何检测碰撞是精灵套件?它需要使用我已经存在的代码,因为我尝试了一种方法,但它失败了。游戏目前有一枚从天空坠落的导弹,太空船必须躲避它们,我想要它,如果它们发生碰撞就会失去生命。这是我的代码

static const uint32_t shipCategory =  0x1 << 1;
static const uint32_t obstacleCategory =  0x1 << 1;

@implementation MyScene{

SKSpriteNode *ship;
SKSpriteNode *missile;
int score;
int HighScore;
SKAction *actionMoveRight;
SKAction *actionMoveLeft;
SKLabelNode *label;

}

-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
    self.backgroundColor = [SKColor whiteColor];
    [self addShip];

    //Making self delegate of physics World
    self.physicsWorld.gravity = CGVectorMake(0,0);
    self.physicsWorld.contactDelegate = self;

    //score
    score = 5;
    label = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    label.text = [NSString stringWithFormat:@"%d",score];
    label.fontSize = 40;
    label.fontColor = [SKColor blackColor];
    label.position = CGPointMake(self.size.width/2, self.size.height/2);
    [self addChild:label];

    //highscore
     HighScore  = [[NSUserDefaults standardUserDefaults] integerForKey:@"HighScore"];
    label = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    label.text = [NSString stringWithFormat:@"%d",HighScore];
    label.fontSize = 40;
    label.fontColor = [SKColor blackColor];
    label.position = CGPointMake(self.size.width/1, self.size.height/2);
    [self addChild:label];
    }

    return self;
}



-(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 = obstacleCategory;
    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)shootMissile
{
// Sprite Kit knows that we are working with images so we don't need to pass the image’s                extension
missile = [SKSpriteNode spriteNodeWithImageNamed:@"red-missile"];
[missile setScale:0.15];
// Position the missile outside the top
int r = arc4random() % 200;
missile.position = CGPointMake(20 + r, self.size.height + missile.size.height/2);
// Add the missile to the scene
[self addChild:missile];

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

- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast {

self.lastSpawnTimeInterval += timeSinceLast;
if (self.lastSpawnTimeInterval > 5) {
    self.lastSpawnTimeInterval = 0;
    [self shootMissile];
}
}
- (void)update:(NSTimeInterval)currentTime {
// Handle time delta.
// If we drop below 60fps, we still want everything to move the same distance.
CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;
self.lastUpdateTimeInterval = currentTime;
if (timeSinceLast > 1) { // more than a second since last update
    timeSinceLast = 1.0 / 60.0;
    self.lastUpdateTimeInterval = currentTime;
}

[self updateWithTimeSinceLastUpdate:timeSinceLast];

}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self.scene];
if(touchLocation.x >ship.position.x){
    if(ship.position.x < 270){
        [ship runAction:actionMoveLeft];
    }
}else{
    if(ship.position.x > 50){

        [ship runAction:actionMoveRight];
    }
}
}

- (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 & obstacleCategory) != 0)
{

    score ++;
    if (score > HighScore) {
        [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:score] forKey:@"HighScore"];
        [[NSUserDefaults standardUserDefaults] synchronize];
        SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
        SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size];
        [self.view presentScene:gameOverScene transition: reveal];
    }
}
}






@end

1 个答案:

答案 0 :(得分:2)

missile添加新类别:

static const uint32_t missileCategory =  0x1 << 2;

physicsBody定义missile

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

将此检查添加到didBeginContact方法:

if ((firstBody.categoryBitMask & shipCategory) != 0 &&
    (secondBody.categoryBitMask & missileCategory) != 0)
{
    // Do your stuff here
}

以下是修改后的代码:

static const uint32_t shipCategory =  0x1 << 1;
static const uint32_t obstacleCategory =  0x1 << 1;
static const uint32_t missileCategory =  0x1 << 2;

@implementation MyScene{

SKSpriteNode *ship;
SKSpriteNode *missile;
int score;
int HighScore;
SKAction *actionMoveRight;
SKAction *actionMoveLeft;
SKLabelNode *label;

}

-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
    self.backgroundColor = [SKColor whiteColor];
    [self addShip];

    //Making self delegate of physics World
    self.physicsWorld.gravity = CGVectorMake(0,0);
    self.physicsWorld.contactDelegate = self;

    //score
    score = 5;
    label = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    label.text = [NSString stringWithFormat:@"%d",score];
    label.fontSize = 40;
    label.fontColor = [SKColor blackColor];
    label.position = CGPointMake(self.size.width/2, self.size.height/2);
    [self addChild:label];

    //highscore
     HighScore  = [[NSUserDefaults standardUserDefaults] integerForKey:@"HighScore"];
    label = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    label.text = [NSString stringWithFormat:@"%d",HighScore];
    label.fontSize = 40;
    label.fontColor = [SKColor blackColor];
    label.position = CGPointMake(self.size.width/1, self.size.height/2);
    [self addChild:label];
    }

    return self;
}



-(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 = obstacleCategory | missileCategory;
    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)shootMissile
{
// Sprite Kit knows that we are working with images so we don't need to pass the image’s                extension
missile = [SKSpriteNode spriteNodeWithImageNamed:@"red-missile"];
[missile setScale:0.15];
// Position the missile outside the top
int r = arc4random() % 200;
missile.position = CGPointMake(20 + r, self.size.height + missile.size.height/2);


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

// Add the missile to the scene
[self addChild:missile];

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

- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast {

self.lastSpawnTimeInterval += timeSinceLast;
if (self.lastSpawnTimeInterval > 5) {
    self.lastSpawnTimeInterval = 0;
    [self shootMissile];
}
}
- (void)update:(NSTimeInterval)currentTime {
// Handle time delta.
// If we drop below 60fps, we still want everything to move the same distance.
CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;
self.lastUpdateTimeInterval = currentTime;
if (timeSinceLast > 1) { // more than a second since last update
    timeSinceLast = 1.0 / 60.0;
    self.lastUpdateTimeInterval = currentTime;
}

[self updateWithTimeSinceLastUpdate:timeSinceLast];

}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self.scene];
if(touchLocation.x >ship.position.x){
    if(ship.position.x < 270){
        [ship runAction:actionMoveLeft];
    }
}else{
    if(ship.position.x > 50){

        [ship runAction:actionMoveRight];
    }
}
}

- (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 & obstacleCategory) != 0)
{

    score ++;
    if (score > HighScore) {
        [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:score] forKey:@"HighScore"];
        [[NSUserDefaults standardUserDefaults] synchronize];
        SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
        SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size];
        [self.view presentScene:gameOverScene transition: reveal];
    }
}

if ((firstBody.categoryBitMask & shipCategory) != 0 &&
    (secondBody.categoryBitMask & missileCategory) != 0)
{
    // Do your stuff here
}
}
@end