2016-11-09 15 views
0

我是新來編碼,所以要友好。我在Swift 3中創建了一個類似於Flappy Bird的遊戲,並且對我的分數節點有問題。我爲分數創建了一個標籤節點,但是當玩家聯繫scoreDetect節點時沒有添加分數。我無法確定是否編寫了錯誤地添加點或者物理代碼不正確的部分。任何幫助表示讚賞。謝謝。Swift 3更新標籤節點與整數遞增

import SpriteKit 
import GameplayKit 

struct PhysicsCategory { 

static let player : UInt32 = 0x1 << 1 
static let roof : UInt32 = 0x1 << 2 
static let floor : UInt32 = 0x1 << 3 
static let lowerObstacle : UInt32 = 0x1 << 4 
static let upperObstacle : UInt32 = 0x1 << 5 
static let scoreDetect : UInt32 = 0x1 << 6 

} 

class GameScene: SKScene, SKPhysicsContactDelegate { 

var bgColor = UIColor(red: 39/255, green: 41/255, blue: 56/255, alpha: 1.0) 
var roof = SKSpriteNode() 
var floor = SKSpriteNode() 
var lowerObstacle = SKSpriteNode() 
var upperObstacle = SKSpriteNode() 
var player = SKSpriteNode() 
var randomValue = Int() 
var scoreDetect = SKSpriteNode() 
var scoreLabel = SKLabelNode() 
var scoreValue = Int() 
var logo = SKSpriteNode() 
var gameStarted = Bool() 

override func didMove(to view: SKView) { 

     createPlayer() 
     createTiles() 
     createScoreLabel() 

     physicsWorld.contactDelegate = self 
     self.physicsWorld.gravity = CGVector(dx: 0.0, dy: -4.0) 
     backgroundColor = bgColor 

     let delay = SKAction.wait(forDuration: 3) 
     let repeatingAction = SKAction.run(repeatingSequence) 
     let sequence = SKAction.sequence([ delay, repeatingAction ]) 
     run(SKAction.repeatForever(sequence)) 

} 

// Random Selector For Obstacles 

func randomSelector() -> Int { 

    let array = [1, 2, 3] 
    return Int(arc4random_uniform(UInt32(array.count))) 

} 

// Player Rules 

func createPlayer() { 

    player = SKSpriteNode(imageNamed: "Player") 
    player.setScale(0.4) 
    player.position = CGPoint(x: -player.size.width, y: 0) 
    player.zPosition = 2 
    addChild(player) 

    player.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "Player"), size: player.size) 
    player.physicsBody?.categoryBitMask = PhysicsCategory.player 
    player.physicsBody?.collisionBitMask = PhysicsCategory.roof | PhysicsCategory.floor | PhysicsCategory.upperObstacle | PhysicsCategory.lowerObstacle | PhysicsCategory.scoreDetect 
    player.physicsBody?.contactTestBitMask = PhysicsCategory.roof | PhysicsCategory.floor | PhysicsCategory.upperObstacle | PhysicsCategory.lowerObstacle | PhysicsCategory.scoreDetect 
    player.physicsBody?.allowsRotation = false 
    player.physicsBody?.affectedByGravity = true 
    player.physicsBody?.isDynamic = false 

} 

// Create Background 

func createTiles() { 

    roof = SKSpriteNode(imageNamed: "Roof") 
    roof.position = CGPoint(x: 0, y: self.frame.height/2 - roof.size.height/2) 
    roof.zPosition = 1 
    addChild(roof) 

    roof.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "Roof"), size: roof.size) 
    roof.physicsBody?.categoryBitMask = PhysicsCategory.roof 
    roof.physicsBody?.collisionBitMask = PhysicsCategory.player 
    roof.physicsBody?.contactTestBitMask = PhysicsCategory.player 
    roof.physicsBody?.allowsRotation = false 
    roof.physicsBody?.affectedByGravity = false 
    roof.physicsBody?.isDynamic = false 

    floor = SKSpriteNode(imageNamed: "Floor") 
    floor.position = CGPoint(x: 0, y: -self.frame.height/2) 
    floor.zPosition = 1 
    addChild(floor) 

    floor.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "Floor"), size: floor.size) 
    floor.physicsBody?.categoryBitMask = PhysicsCategory.floor 
    floor.physicsBody?.collisionBitMask = PhysicsCategory.player 
    floor.physicsBody?.contactTestBitMask = PhysicsCategory.player 
    floor.physicsBody?.allowsRotation = false 
    floor.physicsBody?.affectedByGravity = false 
    floor.physicsBody?.isDynamic = false 

} 

// Obstacle Spawn Rules 

func createObstacle() { 

    if (randomSelector() == 1) { 
     lowerObstacle = SKSpriteNode(imageNamed: "Fire Barrel 1") 
     upperObstacle = SKSpriteNode(imageNamed: "Fire Barrel 3") 
     scoreDetect = SKSpriteNode(color: UIColor.red, size: CGSize(width: 32, height: frame.height)) 

     upperObstacle.position = CGPoint(x: self.frame.width/2 + upperObstacle.size.width/2, y: self.frame.height/2 - upperObstacle.size.height/2 + 12) 
     lowerObstacle.position = CGPoint(x: self.frame.width/2 + lowerObstacle.size.width/2, y: -self.frame.height/2 + lowerObstacle.size.height - 15) 
     scoreDetect.position = CGPoint(x: self.frame.width/2 + upperObstacle.size.width, y: 0) 
    } 
    else { 
     if (randomSelector() == 2) { 
      lowerObstacle = SKSpriteNode(imageNamed: "Fire Barrel 2") 
      upperObstacle = SKSpriteNode(imageNamed: "Fire Barrel 2") 
      scoreDetect = SKSpriteNode(color: UIColor.red, size: CGSize(width: 32, height: frame.height)) 

      upperObstacle.position = CGPoint(x: self.frame.width/2 + upperObstacle.size.width/2, y: self.frame.height/2 - upperObstacle.size.height/1.9) 
      lowerObstacle.position = CGPoint(x: self.frame.width/2 + lowerObstacle.size.width/2, y: -self.frame.height/2 + lowerObstacle.size.height/1.5) 
      scoreDetect.position = CGPoint(x: self.frame.width/2 + upperObstacle.size.width, y: 0) 
     } 
     else { 
      lowerObstacle = SKSpriteNode(imageNamed: "Fire Barrel 3") 
      upperObstacle = SKSpriteNode(imageNamed: "Fire Barrel 1") 
      scoreDetect = SKSpriteNode(color: UIColor.red, size: CGSize(width: 32, height: frame.height)) 

      upperObstacle.position = CGPoint(x: self.frame.width/2 + upperObstacle.size.width/2, y: self.frame.height/2 - upperObstacle.size.height/1.5 + 4) 
      lowerObstacle.position = CGPoint(x: self.frame.width/2 + lowerObstacle.size.width/2, y: -self.frame.height/2 + lowerObstacle.size.height/1.75 + 7) 
      scoreDetect.position = CGPoint(x: self.frame.width/2 + upperObstacle.size.width, y: 0) 
     } 
    } 

    lowerObstacle.zPosition = 2 
    lowerObstacle.setScale(0.8) 

    lowerObstacle.physicsBody = SKPhysicsBody(rectangleOf: lowerObstacle.size) 
    lowerObstacle.physicsBody?.categoryBitMask = PhysicsCategory.lowerObstacle 
    lowerObstacle.physicsBody?.collisionBitMask = PhysicsCategory.player 
    lowerObstacle.physicsBody?.contactTestBitMask = PhysicsCategory.player 
    lowerObstacle.physicsBody?.allowsRotation = false 
    lowerObstacle.physicsBody?.affectedByGravity = false 
    lowerObstacle.physicsBody?.isDynamic = false 

    upperObstacle.zPosition = 2 
    upperObstacle.setScale(0.8) 

    upperObstacle.physicsBody = SKPhysicsBody(rectangleOf: upperObstacle.size) 
    upperObstacle.physicsBody?.categoryBitMask = PhysicsCategory.upperObstacle 
    upperObstacle.physicsBody?.collisionBitMask = PhysicsCategory.player 
    upperObstacle.physicsBody?.contactTestBitMask = PhysicsCategory.player 
    upperObstacle.physicsBody?.allowsRotation = false 
    upperObstacle.physicsBody?.affectedByGravity = false 
    upperObstacle.physicsBody?.isDynamic = false 

    scoreDetect.physicsBody?.categoryBitMask = PhysicsCategory.scoreDetect 
    scoreDetect.physicsBody?.collisionBitMask = PhysicsCategory.player 
    scoreDetect.physicsBody?.contactTestBitMask = PhysicsCategory.player 
    scoreDetect.physicsBody?.allowsRotation = false 
    scoreDetect.physicsBody?.affectedByGravity = false 
    scoreDetect.physicsBody?.isDynamic = false 

    addChild(lowerObstacle) 
    addChild(upperObstacle) 
    addChild(scoreDetect) 
    lowerObstacle.run(
     SKAction.sequence([ 
      SKAction.wait(forDuration: 6), 
      SKAction.removeFromParent() 
     ]) 
    ) 
    upperObstacle.run(
     SKAction.sequence([ 
      SKAction.wait(forDuration: 6), 
      SKAction.removeFromParent() 
     ]) 
    ) 
    scoreDetect.run(
     SKAction.sequence([ 
      SKAction.wait(forDuration: 6), 
      SKAction.removeFromParent() 
      ]) 
    ) 
} 

// Create Spawn and Move Sequence 

func repeatingSequence() { 

    createObstacle() 
    let moveLowerObstacle = SKAction.moveBy(x: -self.frame.width - lowerObstacle.size.width * 2, y: 0, duration: 5) 
    lowerObstacle.run(moveLowerObstacle) 
    let moveUpperObstacle = SKAction.moveBy(x: -self.frame.width - upperObstacle.size.width * 2, y: 0, duration: 5) 
    upperObstacle.run(moveUpperObstacle) 
    let moveScoreDetect = SKAction.moveBy(x: -self.frame.width - upperObstacle.size.width * 2, y: 0, duration: 5) 
    scoreDetect.run(moveScoreDetect) 

} 

func createScoreLabel() { 

    scoreLabel = SKLabelNode(fontNamed: "Arial") 
    scoreLabel.fontSize = 22 
    scoreLabel.position = CGPoint(x: 305, y: -638) 
    scoreLabel.horizontalAlignmentMode = .center 
    scoreLabel.verticalAlignmentMode = .center 
    scoreLabel.text = "SCORE: \(scoreValue)" 
    scoreLabel.fontColor = UIColor.white 
    scoreLabel.zPosition = 4 

    addChild(scoreLabel) 

} 

func didBegin(_ contact: SKPhysicsContact) { 
    let firstBody = contact.bodyA 
    let secondBody = contact.bodyB 

    if firstBody.categoryBitMask == PhysicsCategory.scoreDetect && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.scoreDetect { 
      scoreValue += 1 
    } 
} 

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 

    player.physicsBody?.isDynamic = true 
    let impulse = CGVector(dx: 0, dy: 200) 
    player.physicsBody?.velocity = CGVector(dx: 0, dy: 0) 
    player.physicsBody?.applyImpulse(impulse) 

} 

override func update(_ currentTime: TimeInterval) { 

} 

} 

回答

3

您正在更新scoreValue屬性。但是,您還需要更新scoreLabel中顯示的內容,以相應地更新爲scoreValue的新值。

所以用這個

var scoreValue = Int() { 
    didSet { 
     scoreLabel.text = self.scoreValue.description 
    } 
} 

現在每次scoreValue變化替換此

var scoreValue = Int() 

,該scoreLabel自動更新。

+0

感謝您的迴應。我已經做出了你所建議的改變,但它仍然不能按預期工作,這使我相信也許錯誤與檢測本身有關? –

+0

繼續我的最後,我注意到'scoreDetect'節點沒有分配物理體來解決問題。但是,現在發生碰撞時,每次檢測到碰撞時,得分值都會上升到大約35。有任何想法嗎? –

+0

@MartinJones:因爲func didBegin(_ contact:SKPhysicsContact)'可以在兩個物體碰撞時被多次調用。 [看這個](http://stackoverflow.com/questions/24228274/why-are-didbegincontact-called-multiple-times/38364703#38364703)。 –