2015-09-07 108 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或... –