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

Posted

技术标签:

【中文标题】使用 Swift 在 sprite kit 中的多个场景中重用相同的 sprite 节点【英文标题】:Reuse same sprite node within multiple scenes in sprite kit using Swift 【发布时间】:2016-03-07 06:32:01 【问题描述】:

我在GameScene 中创建精灵节点,如下所示。我想在其他SKScene 中重用createNodeA1nodeA1。我该怎么做?

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



【问题讨论】:

【参考方案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。

这有帮助吗?

【讨论】:

是的,很好的答案。谢谢你。我还要问一件事。如果我使用 init() 方法创建此 nodeA1 的子类,我是否也可以在同一个子类中拥有多个 init() 方法,例如,如果我想创建更多节点(nodeA1、nodeA2、nodeA3 等)在整个应用程序中使用?谢谢。 是的,你可以。您可以使用敌人类型在类方法上方创建一个枚举,然后将其传递给像 imageString 一样的 init 方法。比使用 if 语句根据敌人类型加载正确的 init() 。请记住,您可以根据需要多次恢复此类,因此您可以在屏幕上添加 20 个具有相同子类的敌人。这取决于你的敌人是什么,如果他们或多或少都一样,只有一个子类。 如果它们都不同,具有不同的操作等,那么创建更多子类而不是使用不同的 init 方法更好。如果您不介意,请将我的答案标记为正确。谢谢 您能否更新此答案以解释如何按照您的建议在类上方使用枚举。 还有一个问题!使用 loadNode 函数将其他场景子类化为场景的子类是处理此问题的最佳方式,还是使用 init() 方法在效率方面是更优选的方式?我将不得不将第一个场景的功能与将使用相同节点的其他 30 个场景进行子类化。谢谢。【参考方案2】:

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

【讨论】:

以上是关于使用 Swift 在 sprite kit 中的多个场景中重用相同的 sprite 节点的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift 在 Sprite Kit 游戏中重置高分

Swift Sprite Kit 中的游戏中心

游戏中的三角学——Sprite Kit 和 Swift 教程

游戏中的三角学——Sprite Kit 和 Swift 教程

如何通过 Sprite Kit 中的 CGPoints 数组制作动画 - Swift

使用 Swift 在 Sprite Kit 中构建棋盘游戏? [关闭]