当子类化(可能是?)到另一个节点时,SpriteKit节点给我nil迅速

时间:2014-12-22 23:00:04

标签: ios swift sprite-kit null

好的,所以我正在尝试学习如何创建一个游戏...我想要一个节点作为摄像机,这样我就可以移动它并将视图居中到我的玩家节点。当我继承(我不知道它是否正确地说我将其子类化,可能不是......)播放器节点到世界节点时,应用程序崩溃了。当玩家只是一个节点时,一个&#34;子类&#34; GameScene(而不是&#34; world&#34;节点),它会很好&#34;,我的意思是我可以移动我的播放器(是的,但相机不起作用)。< / p>

所以这是我的代码(很少//意大利语行但不相关)

import SpriteKit

class GameScene: SKScene {

var world: SKNode? //root node! ogni altro nodo del world dev'essere sottoclasse di questo
var overlay: SKNode? //node per l'HUD e altre cose che devono stare sopra al world
var camera: SKNode? //camera node. muovo questo per cambiare le zone visibili

//world sprites
var player: SKSpriteNode!

override func didMoveToView(view: SKView) {
    self.anchorPoint = CGPoint(x: 0, y: 0) //center the scene's anchor point at the center of the screen

    //world setup
    self.world = SKNode()
    self.world!.name = "world"
    self.addChild(world!)

    //camera setup
    self.camera = SKNode()
    self.camera!.name = "camera"
    self.world!.addChild(self.camera!)

    //UI setup
    self.overlay = SKNode()
    self.overlay?.zPosition = 10
    self.overlay?.name = "overlay"
    addChild(self.overlay!)

    player = world!.childNodeWithName("player") as SKSpriteNode!

}

var directionToMove = CGVectorMake(0, 0)

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    for touch: AnyObject in touches {
        let location = touch.locationInNode(self)

        directionToMove = CGVectorMake((directionToMove.dx + (location.x - player!.position.x)), (directionToMove.dy + (location.y - player!.position.y)))
    }
}

override func update(currentTime: CFTimeInterval) {
 //*these both print the string*
    if player == nil {
        println("player is nil")
    }
    if player?.physicsBody == nil {
        println("player.physicsBody is nil")
    }
 //*here it crashes*
    player!.physicsBody!.applyForce(directionToMove)
}

override func didFinishUpdate() {
    if self.camera != nil {
        self.centerOnNode(self.camera!)
    }
}

func centerOnNode(node: SKNode) {
    let cameraPositionInTheScene: CGPoint = node.scene!.convertPoint(node.position, fromNode: node.parent!)
    node.parent!.position = CGPoint(x: node.parent!.position.x - cameraPositionInTheScene.x, y: node.parent!.position.y - cameraPositionInTheScene.y)
}
}

提前感谢:)

2 个答案:

答案 0 :(得分:1)

您的播放器为nil,因为您正在从world节点访问它,该节点为空。默认情况下,播放器是场景的孩子。您可以通过设置节点的父属性在场景编辑器中更改它(参见图1)。

enter image description here

图1. SpriteKit场景编辑器的属性检查器

我建议你做出以下改动:

  1. 在场景编辑器中创建worldoverlaycamera节点,并使用childNodeWithName
  2. 进行访问
  3. 将播放器添加到场景中,而不是世界中,并将其固定在场景中间
  4. 移动相机节点而不是播放器。 didFinishUpdate中的代码将自动调整世界以使相机在场景中居中。您可以将物理主体添加到相机并通过施加力/脉冲或设置其速度来移动它。
  5. 将其他精灵添加到世界(而不是场景)
  6. 如果您将其他精灵添加到世界中,当您调整世界位置以使摄像机居中时,它们将适当移动。然后,您需要相对于世界移动其他精灵。场景只是一个可以一次查看世界某个部分的窗口。

答案 1 :(得分:0)

我不确定为什么你到处都在使用选项。当变量可能为零时,您只需要使用可选项。您的worldoverlaycamera是否会变为零?我猜可能不会。

回答你的问题: 您试图从player获取world。我没有看到你已经向player节点添加了任何world精灵。它找不到它,你打开一个不在那里的可选项。所以你得到一个错误。

如果您在需要时只使用选项,那么您将获得更多运气。如果您将它们用于所有内容,那么您的代码将增加不必要的复杂性。

选项应该是例外,而不是规则。我可以尝试为您修复代码,但我不确定您对player精灵的意图是什么?

遵循简单的教程并从小处着手。随着时间的推移,事情会越来越有意义。