使用Swift在sprite kit中的多个场景中重用相同的sprite节点

时间:2016-03-07 06:32:01

标签: swift

我在GameScene中创建精灵节点,如下所示。我想在其他createNodeA1中重复使用nodeA1SKScene。我怎么能这样做?

import SpriteKit

class GameScene: SKScene {

var nodeA1: SKNode!

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override init(size: CGSize) {
    super.init(size: size)

    // Add sprite node to the scene        
    nodeA1 = createNodeA1()
    addChild(nodeA1)

    }
}

// Create dot 1
func createNodeA1() -> SKNode {
    let spriteNode = SKNode()
    spriteNode.position = CGPointMake(CGRectGetMidX(self.frame)/1.5, CGRectGetMidY(self.frame)/2.0)

    let sprite = SKSpriteNode(imageNamed: "dot_1")
    sprite.zPosition = 3.0
    sprite.name = "A1_Broj"
    spriteNode.addChild(sprite)

    return spriteNode
}

}

2 个答案:

答案 0 :(得分:1)

有几种方法可以做到这一点。

您可以使用loadNode函数将您的其他场景子类化为场景的子类,该函数为这些场景提供对该函数的访问。

去年我问了一个关于这个问题的问题

Swift multiple level scenes

如果您对场景子类化不熟悉,另一种可能更容易的方法就是创建节点本身的子类。

所以你创建了一个类

enum EnemyType {
   case Normal
   case Special
} 


class NodeA1: SKSpriteNode {

   init(imageNamed: String, enemyType: EnemyType) {
      let texture = SKTexture(imageNamed: imageNamed)

      if enemyType == .Normal {
           super.init(texture: texture, color: SKColor.clearColor(), size: texture.size())
      else {
         // other init
      }

     self.zPosition = 1
     self.name = ""
     // add physics body, other properties or methods for the node

    }
}

在您的SKScenes中,您可以在init方法中添加节点,如此

  nodeA1 = NodeA1(imageNamed: "ImageName", enemyType: .Normal)
  nodeA1.position = ....
  addChild(nodeA1)

这种方式,您添加节点的场景将使用子类,因此包括该节点的所有属性,设置等。子类化的另一个好处是您可以使用

遍历所有节点
self.enumerateChildNodesWithName...

并在所有节点上调用自定义方法。

如果你想要创建你的baseScene

你的场景的子类
 class BaseScene: SKScene {

     // set up all shared stuff in didMoveToView
     // have your node function here 
     // touches began
     // physics word and contact collision 
     // all other stuff that needs to be shared between all level scenes

   }

比后续级别的场景看起来像这样

  class Level1Scene: BaseScene {

     override func didMoveToView(view: SKView) {
           super.didMoveToView(view) // This lines imports all stuff in BaseScene didMoveToView


       // do level 1 specific setUps.
       // you can call any function or property from BaseScene, e.g the loadNode function.
  }

您可以照常加载级别场景,例如转换到1级场景,它将自动使用/访问所有超类方法和精灵(BaseScene)。 所以你永远不会直接调用baseScene,它会被自动调用。

这也适用于baseScene中的其他方法,所以说你在BaseScene中有一个Update方法。

 override func update(currentTime: CFTimeInterval) {.... }

这将适用于作为BaseScene的子类的所有级别场景。

但是如果你需要在更新方法中添加一些特定的东西,只在1级场景而不是所有级别场景中都会发生什么呢? 这将是相同的过程,您在LevelScene中创建一个新的更新功能并调用super。

 override func update(currentTime: CFTimeInterval) {
     super.update(currentTime) // this calls the baseScene Update method

    /// specific stuff for that level only
  }

Super简单地表示currentScene的超类,如果场景是它的子类,则为BaseScene。

这有帮助吗?

答案 1 :(得分:0)

这是baseScene子类方面的补充答案信息。我们可以在baseScene中创建所有node1node10。然后在作为baseScene的子类的Leve1Scene中,我们所要做的就是在Level1Scene中我们需要的每个节点的didMoveToView函数状态node1.position = CGPointMake(....)中指定节点的位置。 例如,如果我们不需要加载Level1Scene中的所有10个节点,假设我们不需要加载到场景node10我们只需在didMoveToView函数中加载状态node10.removeFromParent()即可节点不会加载到Level1Scene,但其余9个节点将加载。 请注意,此示例仅使用10个节点,但您可以使用baseScene中的任意数量的节点。 这种子类化方式将在子类中为您节省大量可重复的代码。