2015-09-07 109 views
1

我使用SpriteKit在XCode中制作游戏。游戏中有一名玩家和他必须避免的不同类型的射弹。当玩家与射弹碰撞时,分数改变并且射弹消失。但是,当两枚弹丸碰撞时,它们会弹开。 我希望每次发生两次射弹碰撞时,它们都像没有发生任何事情一样行动,并且继续沿着原始路径前进。我该怎么办?SpriteKit中的精灵之间的碰撞

*注意:这不是整个代码,它只是重要的。

import SpriteKit 

    struct Physics { 
     static let player : UInt32 = 1 
     static let missileOne : UInt32 = 2 
     static let missileTwo : UInt32 = 3 
    } 

class GameScene: SKScene, SKPhysicsContactDelegate { 

    var player = SKSpriteNode(imageNamed: "p1.png") 

    override func didMoveToView(view: SKView) { 

     physicsWorld.contactDelegate = self 

     player.position = CGPointMake(self.size.width/2, self.size.height/5) 
     player.physicsBody = SKPhysicsBody(rectangleOfSize: player.size) 
     player.physicsBody?.affectedByGravity = false 
     player.physicsBody?.dynamic = false 
     player.physicsBody?.categoryBitMask = Physics.player 
     player.physicsBody?.collisionBitMask = Physics.missileOne 
     player.physicsBody?.collisionBitMask = Physics.missileTwo 

     var missileOneTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("SpawnMissileOne"), userInfo: nil, repeats: true) 
     var missileTwoTimer = NSTimer.scheduledTimerWithTimeInterval(1.2, target: self, selector: Selector("SpawnMissileTwo"), userInfo: nil, repeats: true) 

     self.addChild(player) 
    } 

    //When contact happens 
func didBeginContact(contact: SKPhysicsContact) { 
    var firstBody : SKPhysicsBody = contact.bodyA 
    var secondBody : SKPhysicsBody = contact.bodyB 

    if ((firstBody.categoryBitMask == Physics.player) && (secondBody.categoryBitMask == Physics.missileOne)) { 

     CollisionWithMissileOne(firstBody.node as SKSpriteNode, missileOne: secondBody.node as SKSpriteNode) 

    } else if ((firstBody.categoryBitMask == Physics.player) && (secondBody.categoryBitMask == Physics.missileTwo)){ 

     CollisionWithMissileTwo(firstBody.node as SKSpriteNode, missileTwo: secondBody.node as SKSpriteNode) 

    } else if ((firstBody.categoryBitMask == Physics.missileOne)&&(secondBody.categoryBitMask == Physics.missileTwo)) { 

     CollisionBetweenMissiles(firstBody.node as SKSpriteNode, missileTwo: secondBody.node as SKSpriteNode) 

     } 

    } 

//For Player and MissileOne 
    func CollisionWithMissileOne(player: SKSpriteNode, missileOne: SKSpriteNode) { 

     missileOne.removeFromParent() 
    } 

//For Player and MissileTwo 
    func CollisionWithMissileOne(player: SKSpriteNode, missileTwo: SKSpriteNode) { 

     missileTwo.removeFromParent() 
    } 

//For MissileOne and MissileTwo 
     func CollisionBetweenMissiles(missileOne: SKSpriteNode, missileTwo: SKSpriteNode) { 

     ???WHAT SHOULD I CODE HERE??? 

    } 

} 

回答

2

的混乱是,collisionBitMask用于定义其中physicsBodies,在physicsModel相互作用。你真正想要的是contactTestBitmask

此外,您的物理不返回适当的值用于位掩码。作为纯粹的INTS他们应该是1,2,4,8等


这里是你的代码改变的东西,(希望)的作品,我评论,无论我做了他们的变化。

struct Physics { 
     static let player : UInt32 = 1 
     static let missileOne : UInt32 = 2 
     static let missileTwo : UInt32 = 4 // to work properly as bit masks 
    } 

如果您想检查与多种类型的physicsBody.categoryBitMask的联系,则此更改是必需的。在didMoveToView退房player.physicsBody?.contactTestBitMask = ...

override func didMoveToView(view: SKView) { 
    physicsWorld.contactDelegate = self 
    // All your existing player-stuff is fine until... 
    // contactTest, not collision but contact, also: use bitwise OR 
    player.physicsBody?.contactTestBitMask = Physics.missileOne | Physics.missileTwo 
    self.addChild(player) 

    // It is not recommended to use NSTimer for SpriteKit, use SKActions instead 
    let missileOneWait = SKAction.waitForDuration(1) 
    let callSpawnOneAction = SKAction.runBlock({ self.spawnMissileOne() }) 
    let missileOneRepeat = SKAction.repeatActionForever(SKAction.sequence([missileOneWait, callSpawnOneAction])) 
    runAction(missileOneRepeat) 

    let missileTwoWait = SKAction.waitForDuration(1.2) 
    let callSpawnTwoAction = SKAction.runBlock({ self.spawnMissileTwo() }) 
    let missileTwoRepeat = SKAction.repeatActionForever(SKAction.sequence([missileTwoWait, callSpawnTwoAction])) 
    runAction(missileTwoRepeat) 
} 

差不多改写didBeginContact的东西,我相信读和尺度好了很多:

func didBeginContact(contact: SKPhysicsContact) { 
    var firstBody = contact.bodyA 
    var secondBody = contact.bodyB 

    // Rewritten with dynamic variables 
    var playerNode : SKSpriteNode? { 
     if firstBody.categoryBitMask == Physics.player { 
      return firstBody.node as? SKSpriteNode 
     } else if secondBody.categoryBitMask == Physics.player { 
      return secondBody.node as? SKSpriteNode 
     } 
     return nil 
    } 

    // If you want to handle contact between missiles you need to split this 
    // into two different variables 
    var missileNode : SKSpriteNode? { 
     let bitmask1 = firstBody.categoryBitMask 
     let bitmask2 = secondBody.categoryBitMask 

     if bitmask1 == Physics.missileOne || bitmask1 == Physics.missileTwo { 
      return firstBody.node as? SKSpriteNode 
     } else if bitmask2 == Physics.missileOne || bitmask2 == Physics.missileTwo { 
      return secondBody.node as? SKSpriteNode 
     } 
     return nil 
    } 

    if playerNode != nil { 
     collisionBetweenPlayer(playerNode, missile: missileNode) 
    } 
} 

然后你只需要对导弹之间的接触一个功能和球员:

func collisionBetweenPlayer(player: SKSpriteNode?, missile: SKSpriteNode?) { 
    missile?.removeFromParent() 
} 
+0

感谢您的答案,但它改变了一切!请你(或其他人)向我解释如何使两枚导弹相互通过而不发生碰撞? – Gabe12

+0

它并没有真正改变一切,你仍然可以保持你的didBeginContact功能,因为它是例如。如果你不想使用我的建议,那很好,但你仍然需要使用contactBitMask而不是collisionBitMask。对于你的问题,很简单:''missileSprite.physicsBody.collisionBitMask = 0' –

+0

所以你唯一需要从我的答案中拿走的东西是用'contact'而不是'collisionBitMasks'来检查(你指的是什么)为碰撞。此外,BitMasks,需要有适当的BitMask值(1,2,4,8)等,以便与BitWise或... –