Ios 如何在与Singleton的swift Sprite Kit游戏中显示分数标签
几天来,我一直在尝试实现一个单例方法来更新我正在制作的每一个游戏级别的分数。我想不出实施它的正确方法。我在构建和运行项目时没有错误,但在运行游戏时不会显示分数标签。我不知道为什么,但我知道这与singleton方法没有正确实现有关。任何意见都将不胜感激。下面的代码是我的第一个和第一个场景,到目前为止没有显示分数标签或分数 这是游戏的第一关:Ios 如何在与Singleton的swift Sprite Kit游戏中显示分数标签,ios,swift,sprite-kit,singleton,Ios,Swift,Sprite Kit,Singleton,几天来,我一直在尝试实现一个单例方法来更新我正在制作的每一个游戏级别的分数。我想不出实施它的正确方法。我在构建和运行项目时没有错误,但在运行游戏时不会显示分数标签。我不知道为什么,但我知道这与singleton方法没有正确实现有关。任何意见都将不胜感激。下面的代码是我的第一个和第一个场景,到目前为止没有显示分数标签或分数 这是游戏的第一关: import SpriteKit class Singleton { static let sharedInstance = Singleton() v
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 */
}
}
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()
}
}
我想一个新的问题是,除了更改变量的名称之外,我是否还需要做一些其他事情来让singleton方法在不同的场景中工作?(你不知道) 除此之外,这不太好
static let ScoreLabel = Singleton()
static let Score = Singleton()
您创建了两个Singleton实例,这是错误的
还有一个实例变量与ScoreLabel同名,这也不如其他人所说的创建2个单例 要正确使用它,您应该只在singleton类中执行此操作
static let sharedInstance = Singelton()
而不是在游戏场景中使用你的分数属性或其他属性/方法,你会这么说
Singleton.sharedInstance.score++
Singleton.sharedInstance.scoreLabel ...
Singleton.sharedInstance.displayGameScore()
你们也可以在游戏场景中这样写
let singleton = Singleton.sharedInstance
singleton.score++
singleton.scoreLabel...
singleton.displayGameScore()
作为补充说明,最好这样编写属性/方法
var score...
func displayGameScore()...
不是
另一方面,如果您使用SpriteKit API,您可能应该使用它,因此您应该使用SKLabelNodes而不是UILabel。此外,display gameScore方法可能会进入游戏场景,而不仅仅是引用Singleton中的score属性。首先,您需要了解在Swift中是什么以及如何使用它。我想您刚刚开始编程,但是代码中有很多不好的示例,在深入研究更复杂的内容之前,您应该真正学习基础知识。例如,这没有意义:
ScoreLabel.addSubview(Singleton.ScoreLabel.ScoreLabel)
您正在将UILabel作为子视图添加到自身中。我不会为此使用Singleton,创建关卡时只需将分数对象传递到关卡中即可。@vikingosegundo这是什么意思?我的意思是,创建关卡时,我不会使用单件,而是传递分数对象。单身汉制造的问题比他们解决的要多。我该怎么做呢?你能给我举个例子吗@VikingoSegundo如果我要创建singleton类wold,我还要在游戏场景中编写“let singleton=singleton.sharedInstance”我已经编辑了我的代码,现在我可以在第一个场景中显示分数标签,但是当我切换到下一个游戏场景并升级到下一个级别时,分数停止更新,当我进入游戏结束场景时,分数不会像应该的那样出现在结束场景中。如果你愿意的话,我会编辑我的代码给你看。嘿,你可以在游戏场景中编写singleton=singleton.sharedInstance来缩短子序列代码,你不必这样做。你可以说Singleton.sharedInstance.yourMethod/Property。你说的分数不断更新是什么意思?我的意思是分数会随着计数而更新,然后显示标签“1”,然后是“2”,直到我进入二级游戏场景,然后当分数上升时,例如子弹与“坏人”碰撞时,分数不再增加
var score...
func displayGameScore()...
var Score....
func DisplayGameScore() ...