如何使用Singleton在快速Sprite Kit游戏中显示乐谱标签

时间:2016-02-03 05:42:02

标签: ios swift sprite-kit singleton

我已经尝试了几天来实现单例方法来更新我正在制作的游戏的每个级别的分数。我无法弄清楚实现它的正确方法。我在构建和运行项目时没有错误,但是当我运行游戏时,分数标签不会显示。我不知道为什么,但我知道它与单例方法无法正确实现有关。任何输入都将非常感激。下面的代码是我的第一个和开场景,它现在没有显示分数标签或分数。

这是游戏的第一个级别:

import SpriteKit

class Singleton {

static let sharedInstance = Singleton()
var ScoreLabel = UILabel()
var Score : Int = 0


}



struct PhysicsCategory {
static let Enemy : UInt32 = 1
static let Bullet : UInt32 = 2
static let Player : UInt32 = 3
}



class GameScene: SKScene, SKPhysicsContactDelegate {
var HighScore = Int()
var Player = SKSpriteNode(imageNamed: "GoodGuy.png")
var Level1Label = UILabel()


override func didMoveToView(view: SKView) {
    /* Setup your scene here */

    var timer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "update", userInfo: nil, repeats: true)

    var HighScoreDefault = NSUserDefaults.standardUserDefaults()
    if (HighScoreDefault.valueForKey("HighScore") != nil){

        HighScore = HighScoreDefault.valueForKey("HighScore") as! NSInteger
    }
    else{
        HighScore = 0
    }




    physicsWorld.contactDelegate = self

    self.scene?.backgroundColor = UIColor.blackColor()

    self.scene?.size = CGSize(width:640, height: 1136)

    self.addChild(SKEmitterNode(fileNamed: "MagicParticle")!)

    Player.position = CGPointMake(self.size.width/2, self.size.height/8)
    Player.physicsBody = SKPhysicsBody (rectangleOfSize: Player.size)
    Player.physicsBody?.affectedByGravity = false
    Player.physicsBody?.categoryBitMask = PhysicsCategory.Player
    Player.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy
    Player.physicsBody?.dynamic = false

    Level1Label = UILabel (frame: CGRect(x:0, y:0, width: view.frame.size.width/3, height: 30))
    Level1Label.center = CGPoint(x: view.frame.size.width/1.675 , y: view.frame.size.height/1.05)
    Level1Label.textColor = UIColor.whiteColor()
    Level1Label.text = "Level 1"
    self.view?.addSubview(Level1Label)

    Singleton.sharedInstance.ScoreLabel.text = "\(Singleton.sharedInstance.Score)"
    Singleton.sharedInstance.ScoreLabel = UILabel(frame: CGRect(x:0, y:0, width:100, height:20))
    Singleton.sharedInstance.ScoreLabel.backgroundColor = UIColor.clearColor()
    Singleton.sharedInstance.ScoreLabel.textColor = UIColor.whiteColor()
    self.view?.addSubview(Singleton.sharedInstance.ScoreLabel)


    var Timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("SpawnBullets"), userInfo: nil, repeats: true)

    var Enemytimer = NSTimer.scheduledTimerWithTimeInterval(1.5, target: self, selector: Selector("SpawnEnemies"), userInfo: nil, repeats: true)



    self.addChild(Player)





}

func update() {
    self.view?.presentScene(GameScene2())
    Level1Label.removeFromSuperview()
}

func didBeginContact(contact: SKPhysicsContact) {
    var firstBody : SKPhysicsBody = contact.bodyA
    var secondBody : SKPhysicsBody = contact.bodyB
    if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.Bullet) ||
        (firstBody.categoryBitMask == PhysicsCategory.Bullet) && (secondBody.categoryBitMask == PhysicsCategory.Enemy)){

        CollisionWithBullet(firstBody.node as! SKSpriteNode, Bullet: secondBody.node as! SKSpriteNode)

    }

    else if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.Player) ||
        (firstBody.categoryBitMask == PhysicsCategory.Player) && (secondBody.categoryBitMask == PhysicsCategory.Enemy)){

            CollisionWithPlayer(firstBody.node as! SKSpriteNode, Player: secondBody.node as! SKSpriteNode)
    }


}


func CollisionWithBullet(Enemy: SKSpriteNode, Bullet: SKSpriteNode){
    Enemy.removeFromParent()
    Bullet.removeFromParent()
    Singleton.sharedInstance.Score++


    Singleton.sharedInstance.ScoreLabel.text = "\(Singleton.sharedInstance.Score)"
}



func CollisionWithPlayer(Enemy: SKSpriteNode, Player: SKSpriteNode){
    var ScoreDefault = NSUserDefaults.standardUserDefaults()
    ScoreDefault.setValue(Singleton.sharedInstance.Score, forKey: "Score")
    ScoreDefault.synchronize()


    if (Singleton.sharedInstance.Score > HighScore){

    var HighScoreDefault = NSUserDefaults.standardUserDefaults()
    HighScoreDefault.setValue(Singleton.sharedInstance.Score, forKey: "HighScore")

    }


    Enemy.removeFromParent()
    Player.removeFromParent()
    self.view?.presentScene(EndScene())
    Level1Label.removeFromSuperview()

        }

func SpawnBullets(){
    var Bullet = SKSpriteNode(imageNamed: "Bullet.png")
    Bullet.zPosition = -5
    Bullet.position = CGPointMake(Player.position.x, Player.position.y)

    let action = SKAction.moveToY(self.size.height + 30, duration: 1.0)
    let actionDone = SKAction.removeFromParent()
    Bullet.runAction(SKAction.sequence([action, actionDone]))


    Bullet.physicsBody = SKPhysicsBody(rectangleOfSize: Bullet.size)
    Bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
    Bullet.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy
    Bullet.physicsBody?.affectedByGravity = false
    Bullet.physicsBody?.dynamic = false
    self.addChild(Bullet)
}

func SpawnEnemies(){
    var Enemy = SKSpriteNode(imageNamed: "BadGuy.png")
    var MinValue = self.size.width/8
    var MaxValue = self.size.width - 150
    let SpawnPoint = UInt32(MaxValue - MinValue)
    Enemy.position = CGPoint(x: CGFloat(arc4random_uniform(SpawnPoint)), y: self.size.height)
    Enemy.physicsBody = SKPhysicsBody(rectangleOfSize: Enemy.size)
    Enemy.physicsBody?.categoryBitMask = PhysicsCategory.Enemy
    Enemy.physicsBody?.contactTestBitMask = PhysicsCategory.Bullet
    Enemy.physicsBody?.affectedByGravity = false
    Enemy.physicsBody?.dynamic = true

    let action = SKAction.moveToY(-70, duration: 3.0)
    let actionDone = SKAction.removeFromParent()
    Enemy.runAction(SKAction.sequence([action, actionDone]))

    Enemy.runAction(SKAction.repeatActionForever(action))

    self.addChild(Enemy)

}



override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* Called when a touch begins */

    for touch in touches {
        let location = touch.locationInNode(self)

        Player.position.x = location.x

    }
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch in touches {
        let location = touch.locationInNode(self)

        Player.position.x = location.x

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

这是游戏的第二级:

导入SpriteKit

struct PhysicsCategory2 {
static let Enemy : UInt32 = 1//00000000000000000000000000000001
static let Bullet : UInt32 = 2//00000000000000000000000000000010
static let Player : UInt32 = 3//00000000000000000000000000000100
}


class GameScene2: SKScene, SKPhysicsContactDelegate {
var HighScore = Int()
var Player = SKSpriteNode(imageNamed: "GoodGuy.png")
var Level2Label = UILabel()


override func didMoveToView(view: SKView) {
    /* Setup your scene here */

    var HighScoreDefault = NSUserDefaults.standardUserDefaults()
    if (HighScoreDefault.valueForKey("HighScore") != nil){

        HighScore = HighScoreDefault.valueForKey("HighScore") as! NSInteger
    }
    else{
        HighScore = 0
    }



    physicsWorld.contactDelegate = self

    self.scene?.backgroundColor = UIColor.blackColor()

    self.scene?.size = CGSize(width:640, height: 1136)

    self.addChild(SKEmitterNode(fileNamed: "MagicParticle")!)

    Player.position = CGPointMake(self.size.width/2, self.size.height/8)
    Player.physicsBody = SKPhysicsBody (rectangleOfSize: Player.size)
    Player.physicsBody?.affectedByGravity = false
    Player.physicsBody?.categoryBitMask = PhysicsCategory2.Player
    Player.physicsBody?.contactTestBitMask = PhysicsCategory2.Enemy
    Player.physicsBody?.dynamic = false

    Level2Label = UILabel (frame: CGRect(x:0, y:0, width: view.frame.size.width/3, height: 30))
    Level2Label.center = CGPoint(x: view.frame.size.width/1.675 , y: view.frame.size.height/1.05)
    Level2Label.textColor = UIColor.whiteColor()
    Level2Label.text = "Level 2"
    self.view?.addSubview(Level2Label)


    var Timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("SpawnBullets"), userInfo: nil, repeats: true)

    var Enemytimer = NSTimer.scheduledTimerWithTimeInterval(1.5, target: self, selector: Selector("SpawnEnemies"), userInfo: nil, repeats: true)



    self.addChild(Player)

    Singleton.sharedInstance.ScoreLabel.text = "\(Singleton.sharedInstance.Score)"
    Singleton.sharedInstance.ScoreLabel = UILabel(frame: CGRect(x:0, y:0, width:100, height:20))
    Singleton.sharedInstance.ScoreLabel.backgroundColor = UIColor.clearColor()
    Singleton.sharedInstance.ScoreLabel.textColor = UIColor.whiteColor()



}

func didBeginContact(contact: SKPhysicsContact) {
    var firstBody : SKPhysicsBody = contact.bodyA
    var secondBody : SKPhysicsBody = contact.bodyB
    if ((firstBody.categoryBitMask == PhysicsCategory2.Enemy) && (secondBody.categoryBitMask == PhysicsCategory2.Bullet) ||
        (firstBody.categoryBitMask == PhysicsCategory2.Bullet) && (secondBody.categoryBitMask == PhysicsCategory2.Enemy)){

            CollisionWithBullet(firstBody.node as! SKSpriteNode, Bullet: secondBody.node as! SKSpriteNode)

    }

    else if ((firstBody.categoryBitMask == PhysicsCategory2.Enemy) && (secondBody.categoryBitMask == PhysicsCategory2.Player) ||
        (firstBody.categoryBitMask == PhysicsCategory2.Player) && (secondBody.categoryBitMask == PhysicsCategory2.Enemy)){

            CollisionWithPlayer(firstBody.node as! SKSpriteNode, Player: secondBody.node as! SKSpriteNode)
    }


    }


    func CollisionWithBullet(Enemy: SKSpriteNode, Bullet: SKSpriteNode){
    Enemy.removeFromParent()
    Bullet.removeFromParent()
    Singleton.sharedInstance.Score++


    Singleton.sharedInstance.ScoreLabel.text = "\(Singleton.sharedInstance.Score)"
}




func CollisionWithPlayer(Enemy: SKSpriteNode, Player: SKSpriteNode){
    var ScoreDefault = NSUserDefaults.standardUserDefaults()
    ScoreDefault.setValue(Singleton.sharedInstance.Score, forKey: "Score")
    ScoreDefault.synchronize()

    if (Singleton.sharedInstance.Score > HighScore){

        var HighScoreDefault = NSUserDefaults.standardUserDefaults()
        HighScoreDefault.setValue(Singleton.sharedInstance.Score, forKey: "HighScore")

    }


    Enemy.removeFromParent()
    Player.removeFromParent()
    self.view?.presentScene(EndScene())
    Level2Label.removeFromSuperview()
    Singleton.sharedInstance.ScoreLabel.removeFromSuperview()

    }

    func SpawnBullets(){
    var Bullet = SKSpriteNode(imageNamed: "Bullet.png")
    Bullet.zPosition = -5
    Bullet.position = CGPointMake(Player.position.x, Player.position.y)

    let action = SKAction.moveToY(self.size.height + 30, duration: 1.0)
    let actionDone = SKAction.removeFromParent()
    Bullet.runAction(SKAction.sequence([action, actionDone]))


    Bullet.physicsBody = SKPhysicsBody(rectangleOfSize: Bullet.size)
    Bullet.physicsBody?.categoryBitMask = PhysicsCategory2.Bullet
    Bullet.physicsBody?.contactTestBitMask = PhysicsCategory2.Enemy
    Bullet.physicsBody?.affectedByGravity = false
    Bullet.physicsBody?.dynamic = false
    self.addChild(Bullet)
    }

    func SpawnEnemies(){
    var Enemy = SKSpriteNode(imageNamed: "BadGuy.png")
    var MinValue = self.size.width/8
    var MaxValue = self.size.width - 150
    let SpawnPoint = UInt32(MaxValue - MinValue)
    Enemy.position = CGPoint(x: CGFloat(arc4random_uniform(SpawnPoint)), y: self.size.height)
    Enemy.physicsBody = SKPhysicsBody(rectangleOfSize: Enemy.size)
    Enemy.physicsBody?.categoryBitMask = PhysicsCategory2.Enemy
    Enemy.physicsBody?.contactTestBitMask = PhysicsCategory2.Bullet
    Enemy.physicsBody?.affectedByGravity = false
    Enemy.physicsBody?.dynamic = true

    let action = SKAction.moveToY(-70, duration: 3.0)
    let actionDone = SKAction.removeFromParent()
    Enemy.runAction(SKAction.sequence([action, actionDone]))

    Enemy.runAction(SKAction.repeatActionForever(action))

    self.addChild(Enemy)

    }



    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    /* Called when a touch begins */

    for touch in touches {
        let location = touch.locationInNode(self)

        Player.position.x = location.x

    }
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch in touches {
        let location = touch.locationInNode(self)

        Player.position.x = location.x

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

这是游戏的Game Over页面:

import Foundation
import SpriteKit

class EndScene: SKScene {

var RestartButton : UIButton!
var HighScore : Int!
var HighScoreLabel : UILabel!
var GameOverLabel : UILabel!
override func didMoveToView(view: SKView) {

    self.scene?.backgroundColor = UIColor.blackColor()

    self.scene?.size = CGSize(width:640, height: 1136)

    self.addChild(SKEmitterNode(fileNamed: "MagicParticle")!)

    RestartButton = UIButton(frame: CGRect(x:0, y:0, width: view.frame.size.width/3
        , height: 30))
    RestartButton.titleLabel?.adjustsFontSizeToFitWidth = true
    RestartButton.center = CGPoint(x: view.frame.size.width/2 , y: view.frame.size.height/1.5)
    RestartButton.setTitle("Restart", forState: UIControlState.Normal)
    RestartButton.showsTouchWhenHighlighted = true
    RestartButton.setTitleColor(UIColor.whiteColor(), forState:  UIControlState.Normal)
    RestartButton.addTarget(self, action: Selector("Restart"), forControlEvents: UIControlEvents.TouchUpInside)
    self.view?.addSubview(RestartButton)

    var ScoreDefault = NSUserDefaults.standardUserDefaults()
    var Score = ScoreDefault.valueForKey("Score") as! NSInteger

    var HighScoreDefault = NSUserDefaults.standardUserDefaults()
    HighScore = HighScoreDefault.valueForKey("HighScore") as! NSInteger

    Singleton.sharedInstance.ScoreLabel = UILabel (frame: CGRect(x:0, y:0, width: view.frame.size.width/3, height: 30))
    Singleton.sharedInstance.ScoreLabel.center = CGPoint(x: view.frame.size.width/1.6 , y: view.frame.size.height/2.5)
    Singleton.sharedInstance.ScoreLabel.text = "\(Singleton.sharedInstance.Score)"
    Singleton.sharedInstance.ScoreLabel.textColor = UIColor.whiteColor()
    self.view?.addSubview(Singleton.sharedInstance.ScoreLabel)

    HighScoreLabel = UILabel (frame: CGRect(x:0, y:0, width: view.frame.size.width/3, height: 30))
    HighScoreLabel.center = CGPoint(x: view.frame.size.width/1.6 , y: view.frame.size.height/2)
    HighScoreLabel.textColor = UIColor.whiteColor()
    HighScoreLabel.text = "\(HighScore)"
    self.view?.addSubview(HighScoreLabel)

    GameOverLabel = UILabel (frame: CGRect(x:0, y:0, width: view.frame.size.width/3.8, height: 30))
    GameOverLabel.center = CGPoint(x: view.frame.size.width/2 , y: view.frame.size.height/10)
    GameOverLabel.textColor = UIColor.whiteColor()
    GameOverLabel.text = "Game Over"
    self.view?.addSubview(GameOverLabel)

}

func Restart(){
    self.view?.presentScene(GameScene(), transition: SKTransition.crossFadeWithDuration(0.3))
    RestartButton.removeFromSuperview()
    HighScoreLabel.removeFromSuperview()
    Singleton.sharedInstance.ScoreLabel.removeFromSuperview()
    GameOverLabel.removeFromSuperview()

}
}

我想一个新的问题是,如果除了更改变量的名称之外还需要做其他事情以使单例方法在场景之间工作

2 个答案:

答案 0 :(得分:0)

你在哪里调用DisplayGameScore()? (你不要)

除此之外,这不是那么好

static let ScoreLabel = Singleton()
static let Score = Singleton()

你创建了两个单例的错误

的实例

然后你有一个名为ScoreLabel的实例变量,这也是不太好的

答案 1 :(得分:0)

正如其他人所说,你创造了2个单身人士。

要正确使用它,您应该只在单身类

中执行此操作
static let sharedInstance = Singelton()

而不是在游戏场景中使用你的得分属性或其他属性/方法,你会说这个

Singleton.sharedInstance.score++ 
Singleton.sharedInstance.scoreLabel ...
Singleton.sharedInstance.displayGameScore()

你也可以在GameScene

中这样写
 let singleton = Singleton.sharedInstance
 singleton.score++
 singleton.scoreLabel...
 singleton.displayGameScore()

作为旁注,最好的做法是编写像这样的属性/方法

var score...
func displayGameScore()...

var Score....
func DisplayGameScore() ...

另一方面注意,如果你使用它,你应该使用SpriteKit Apis,所以你应该使用SKLabelNodes而不是UILabel。此外,显示gameScore方法可能会进入你的GameScene而不是你只是从你的Singleton引用得分属性。