2017-03-03 53 views
0

請幫助!我一直在努力弄清楚這個問題。我搜查了互聯網,我找不到任何幫助我的東西。如何讓敵人擁有獨立的生命?

我目前正在製作一款遊戲,其中你是中間的一艘太空飛船,敵艦正朝着你移動,而你必須向他們開槍。一些敵人有不同的生活。例如:一艘紅色的船隻需要一槍爆炸,藍色的船隻需要3艘等等。我擁有一切只爲了生活而工作。例如:每當一艘藍色的船被召喚到屏幕上,我就會拍攝一次,所以它的生命降到2,但是每當另一艘藍色的船被稱爲第一艘藍色的船時,它的生命又會重新回到3。無論如何,我可以做到這一點,以便每當船舶失去生命時,即使其他船舶被召喚,它仍然如此?

這是我的船函數被調用,並增加了敵人的太空飛船到屏幕上:

func VillainRight(){ 
    let TooMuch = self.size.width 
    let point = UInt32(TooMuch) 
    life = 3 
    let VillainR = SKSpriteNode(imageNamed: "BlueVillain") 

    VillainR.zPosition = 2 
    VillainR.position = CGPoint(x: self.frame.minX,y: CGFloat(arc4random_uniform(point))) 

    //This code makes the villain's Zposition point towards the SpaceShip 
    let angle = atan2(SpaceShip.position.y - VillainR.position.y, SpaceShip.position.x - VillainR.position.x) 
    VillainR.zRotation = angle - CGFloat(M_PI_2) 


    let MoveToCenter = SKAction.move(to: CGPoint(x: self.frame.midX, y: self.frame.midY), duration: 15) 

    //Physics World 
    VillainR.physicsBody = SKPhysicsBody(rectangleOf: VillainR.size) 
    VillainR.physicsBody?.categoryBitMask = NumberingPhysics.RightV 
    VillainR.physicsBody?.contactTestBitMask = NumberingPhysics.Laser | NumberingPhysics.SpaceShip 
    VillainR.physicsBody?.affectedByGravity = false 
    VillainR.physicsBody?.isDynamic = true 






    VillainR.run(MoveToCenter) 
    addChild(VillainR) 
    } 

這是調用這個函數的代碼:

_ = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(Level1.VillainRight), userInfo: nil, repeats: true) 

我使用的spritekit迅速。 非常感謝您提前!

+1

注意,在使用SpriteKit定時器可以帶領你進入一些問題,如果你還沒有實現的[自定義暫停功能](http://stackoverflow.com/a/34398582/3402095)。例如,如果您進入背景,並在一兩分鐘後返回遊戲,您可能會看到一個充滿敵人的屏幕。這是因爲Timer不受節點場景或視圖暫停狀態的影響,並且在應用程序進入後臺後不會立即暫停。另一方面,與SKActions,這是自動處理。 – Whirlwind

+1

此外,您應該嘗試遵循命名約定:類型和協議的名稱是UpperCamelCase。其他一切都是較低的。意思是'villainR.run(moveToCenter)'而不是'VillainR.run(MoveToCenter)';)這會讓你的代碼更容易被別人理解...... – Whirlwind

回答

1

發生這種情況的原因是life變量被聲明爲場景的屬性,並且它不是局部的特定節點(敵方船隻)。您可以在幾個方面解決這個問題......第一種方法是使用節點的userData屬性:

import SpriteKit 

let kEnergyKey = "kEnergyKey" 

class GameScene: SKScene, SKPhysicsContactDelegate { 

    override func didMove(to view: SKView) { 


     let blueShip = getShip(energy: 3) 
     let greenShip = getShip(energy: 2) 
     let redShip = getShip(energy: 1) 

     if let blueShipEnergy = blueShip.userData?.value(forKey: kEnergyKey) as? Int { 

      print("Blue ship has \(blueShipEnergy) lives left") 
      //hit the ship 
      blueShip.userData?.setValue(blueShipEnergy-1, forKey: kEnergyKey) 

      if let energyAfterBeingHit = blueShip.userData?.value(forKey: kEnergyKey) as? Int { 

       print("Blue ship has \(energyAfterBeingHit) lives left") 
      } 
     } 
    } 

    func getShip(energy:Int)->SKSpriteNode{ 
     //determine which texture to load here based on energy value 
     let ship = SKSpriteNode(color: .purple, size: CGSize(width: 50, height: 50)) 

     ship.userData = [kEnergyKey:energy] 

     return ship 
    } 
} 

這就是文檔說怎麼樣userData屬性:

您可以使用此屬性來存儲您的自己的數據在一個節點。例如, 您可以存儲關於您的遊戲邏輯中使用的每個節點的遊戲特定數據。這可以是創建自己的節點 子類來保存遊戲數據的有用替代方法。

正如你所看到的,這種替代是繼承的節點(SKSpriteNode):

class Enemy:SKSpriteNode { 

    private var energy:Int 
    //do initialization here 
} 
+0

好的.....你能告訴我需要什麼嗎?當子彈節點與敵人節點進行接觸以便生命將減少1時,就進入「開始接觸」函數中去? –

+0

@AlexMerlin它很簡單。在'didBegin(contact:)'你訪問這艘船,然後訪問它的userData,然後減少'energy'變量並根據船的種類,最終刪除它?合理? – Whirlwind

+0

好的很好......我會盡快實現這一點,並讓你知道它是怎麼回事。非常感謝 –