我正在使用Swift创建一个基本的太空飞船游戏,一切运行良好,直到我尝试添加一个功能,每当用户刷卡时,飞船就会向上移动。我添加了一个UISwipeGestureRecognizer并将其与我的GameViewController中的IBAction连接,然后我打算在我的GameScene中调用一个方法来使太空船向上移动。
import UIKit
import SpriteKit
extension SKNode {
class func unarchiveFromFile(file : NSString) -> SKNode? {
if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as GameScene
archiver.finishDecoding()
return scene
} else {
return nil
}
}
}
class GameViewController: UIViewController {
let scene: GameScene!
@IBAction func swipeUp(sender: UISwipeGestureRecognizer){
scene.movePlaneUp()
}
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
let skView = self.view as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> Int {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
} else {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
所有内容都会编译并且应用程序会运行,但是,每当我尝试向上滑动时,都会出现致命错误:在行中打开可选值时意外地发现nil
scene.movePlaneUp()
我理解错误的发生是因为场景的值是nil,但是如何使场景实际上具有GameScene的值?
这是我的GameScene代码:
import SpriteKit
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
let bg = SKSpriteNode(imageNamed: "Background")
bg.size = self.frame.size
bg.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
self.addChild(bg)
let sprite = SKSpriteNode(imageNamed: "Spaceship")
sprite.xScale = 0.6
sprite.yScale = 0.5
sprite.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMinY(self.frame)+CGRectGetMaxY(sprite.frame))
sprite.name = "spaceship"
self.addChild(sprite)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
var t = touches.allObjects[0]
let location = t.locationInNode(self)
let action = SKAction.moveToX(location.x, duration:0.1)
let n = self.childNodeWithName("spaceship")
n?.runAction(action)
let bullet = SKSpriteNode(imageNamed: "Spaceship")
bullet.xScale = 0.05
bullet.yScale = 0.05
bullet.position = CGPoint(x: location.x, y: 200+bullet.position.y)
bullet.runAction(SKAction.moveToY(1000, duration: 0.75))
self.addChild(bullet)
}
func movePlaneUp(){
let n = childNodeWithName("spaceship")
n?.removeAllActions()
let action = SKAction.moveBy(CGVector(dx: 0, dy: 100), duration: 1)
n?.runAction(action)
}
}
答案 0 :(得分:0)
我意识到我遇到错误的原因是因为我从未向场景分配过任何东西。我通过改变
解决了我的问题let scene: GameScene!
到
let myScene: GameScene!
然后我将viewDidLoad改为
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
let skView = self.view as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
myScene = scene
}
}
然后实际为myScene分配了一个值
答案 1 :(得分:0)
我知道这有点晚了...如果你使用self.scene = scene
它也会有效。这是由于使用scene
创建的if let scene
var,会覆盖if let
范围内具有相同名称的任何其他变量。你现在可能已经知道了(因为它已经创建了两年了):)但是,我希望它对这门语言的新手有用。