2015-12-26 93 views
0

所以我創建了一個空氣曲棍球遊戲,並且有5個主要的SKSpriteNodes。我需要檢測冰球與goal1和goal2之間的碰撞。當它檢測到碰撞時,它需要在SKELabelNode的scoreLeft或scoreRight上加1。我已經使用Gamescene.sks文件來製作可視化表示。我評論了didBeginContact,因爲它不起作用。先謝謝你。如何檢測Swift/SpriteKit中超過2個對象的碰撞

class GameScene: SKScene, SKPhysicsContactDelegate { 

let paddle1CategoryName = "paddle1" 
let paddle2CategoryName = "paddle2" 
let puckCategoryName = "puck" 
let goal1CategoryName = "goal1" 
let goal2CategoryName = "goal2" 
let scoreLeftCategoryName = "scoreLeft" 
let scoreRightCategoryName = "scoreRight" 
var isFingerOnPaddle1 = false 
var isFingerOnPaddle2 = false 


var paddle1Category: UInt32 = 0x1 << 0 
var paddle2Category: UInt32 = 0x1 << 1 
var puckCategory: UInt32 = 0x1 << 2 
var goal1Category: UInt32 = 0x1 << 3 
var goal2Category: UInt32 = 0x1 << 4 

override func didMoveToView(view: SKView) { 
    /* Setup your scene here */ 
    let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame) 
    borderBody.friction = 0 
    self.physicsBody = borderBody 
    let paddle1 = childNodeWithName(paddle1CategoryName) as! SKSpriteNode 
    let paddle2 = childNodeWithName(paddle2CategoryName) as! SKSpriteNode 
    let puck = childNodeWithName(puckCategoryName) as! SKSpriteNode 
    let goal1 = childNodeWithName(goal1CategoryName) as! SKSpriteNode 
    let goal2 = childNodeWithName(goal2CategoryName) as! SKSpriteNode 
    let scoreLeft = childNodeWithName(scoreLeftCategoryName) as! SKLabelNode 
    let scoreRight = childNodeWithName(scoreRightCategoryName) as! SKLabelNode 

} 

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    /* Called when a touch begins */ 
    var touch = touches.first! as UITouch 
    var location = touch.locationInNode(self) 
    if let body = physicsWorld.bodyAtPoint(location){ 
     if body.node!.name == paddle1CategoryName { 
      print("The game has begun.") 
      isFingerOnPaddle1 = true 
     } else if body.node!.name == paddle2CategoryName{ 
      print("The game has begun.") 
      isFingerOnPaddle2 = true 
     } 
    } 
} 
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    let paddle1 = childNodeWithName(paddle1CategoryName) as! SKSpriteNode 
    let paddle2 = childNodeWithName(paddle2CategoryName) as! SKSpriteNode 
    let puck = childNodeWithName(puckCategoryName) as! SKSpriteNode 
    let goal1 = childNodeWithName(goal1CategoryName) as! SKSpriteNode 
    let goal2 = childNodeWithName(goal2CategoryName) as! SKSpriteNode 
    var touch = touches.first! as UITouch 
    var touchLocation = touch.locationInNode(self) 
    var previousLocation = touch.previousLocationInNode(self) 



    if isFingerOnPaddle1{ 

    let paddle1X = paddle1.position.x + (touchLocation.x - previousLocation.x) 
    let paddle1Y = paddle1.position.y + (touchLocation.y - previousLocation.y) 
    if (touchLocation.x <= paddle1.position.x && (touchLocation.y <= paddle1.position.y || touchLocation.y >= paddle1.position.y)){ 
    paddle1.position = CGPoint(x: paddle1X, y: paddle1Y) 
    } 
    } 
    if isFingerOnPaddle2{ 
    let paddle2X = paddle2.position.x + (touchLocation.x - previousLocation.x) 
    let paddle2Y = paddle2.position.y + (touchLocation.y - previousLocation.y) 

    if (touchLocation.x >= paddle2X && (touchLocation.y >= paddle2Y || touchLocation.y < paddle2.position.y)){ 
     paddle2.position = CGPoint(x: paddle2X, y: paddle2Y) 
    } 
    } 

} 
/* 
func didBeginContact(contact: SKPhysicsContact) { 
    let scoreLeft = childNodeWithName(scoreLeftCategoryName) as! SKLabelNode 
    let scoreRight = childNodeWithName(scoreRightCategoryName) as! SKLabelNode 
    var score = 0 
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask 


    switch contactMask{ 
    case puckCategory | goal1Category: 
     if contact.bodyA.categoryBitMask == puckCategory{ 
      puckCategory = contact.bodyA.categoryBitMask 
      goal1Category = contact.bodyB.categoryBitMask 
      score++ 
      scoreRight.text = "\(score)" 
     }else{ 
      puckCategory = contact.bodyB.categoryBitMask 
      goal1Category = contact.bodyA.categoryBitMask 
      score++ 
      scoreRight.text = "\(score)" 
     } 
    case puckCategory | goal2Category: 
     if contact.bodyA.categoryBitMask == puckCategory{ 
      puckCategory = contact.bodyA.categoryBitMask 
      goal2Category = contact.bodyB.categoryBitMask 
      score++ 
      scoreLeft.text = "\(score)" 
     }else{ 
      puckCategory = contact.bodyB.categoryBitMask 
      goal2Category = contact.bodyA.categoryBitMask 
      score++ 
      scoreLeft.text = "\(score)" 
     } 
    default: 

     // Nobody expects this, so satisfy the compiler and catch 
     // ourselves if we do something we didn't plan to 
     fatalError("other collision: \(contactMask)") 

    } 
}*/ 
override func update(currentTime: CFTimeInterval) { 
    /* Called before each frame is rendered */ 
} 

}

回答

1

的一個問題是,在你的函數開始使用本地var score = 0。去掉它。得分應該存儲在遊戲模型中,以便可以應用關於獲勝的邏輯,但是匹配您的代碼,至少可以這樣做。

if let score = Int(scoreLeft.text) { 
    scoreLeft.text = "\(score + 1)" 
} 

此外,還有與

case puckCategory | goal1Category: 
     if contact.bodyA.categoryBitMask == puckCategory{ 
      puckCategory = contact.bodyA.categoryBitMask 

一個問題你所說的是,如果contact.bodyA.categoryBitMask等於puckCategory,然後設置puckCategorycontact.bodyA.categoryBitMask。這是一個無操作,沒有任何變化,更重要的是,你不想改變你的子節點與比較的位掩碼。使puckCategory,goal1Categoygoal2Category常數。祝你好運。

跟進OP評論:

所以,扔掉didBeginContact的代碼,設置類別面具變量有兩個原因。 1)將變量puckCatergory設置爲相同的值會造成浪費和混亂。 2)由於像puckCategory這樣的變量與子節點位掩碼進行比較,如果它們發生變化,將會是災難性的。該功能應該看起來像這樣。在你太過分之前,還要確保爲其他類型的聯繫人添加處理程序。

func didBeginContact(contact: SKPhysicsContact) { 
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask 

    switch contactMask { 
    case puckCategory | goal1Category: 
     let scoreRight = childNodeWithName(scoreRightCategoryName) as! SKLabelNode 
     if let score = Int(scoreRight.text) { 
      scoreRight.text = "\(score + 1)" 
     } 
    case puckCategory | goal2Category: 
     let scoreLeft = childNodeWithName(scoreLeftCategoryName) as! SKLabelNode 
     if let score = Int(scoreLeft.text) { 
      scoreLeft.text = "\(score + 1)" 
     } 
    default: 
     // There are other contacts that need to be handled; paddle+puck,puck+wall, etc 
     fatalError("other collision: \(contactMask)") 
    } 
} 
+0

我應該怎樣改變代碼佈局?你說他們是「沒有操作」,那麼我應該怎樣改變它以使它「操作」?另外你是什麼意思的「讓puckCategory,goal1Categoy和goal2Category常量」?對不起,我是一個快速入門的初學者,我不太明白。 – Rohorao

+0

沒關係我想出了什麼常量,但我的第一個問題仍然是一樣的:我應該改變我的代碼,以便它是「操作」。 – Rohorao

+0

你的代碼有問題,或者我在GameScene.sks中製作標籤時弄錯了。問題在於:冰球擊中了球門,但是......得分並沒有上升一個點。 – Rohorao