【问题标题】:SpriteKit "START" button that calls start() in the scene its in在场景中调用 start() 的 SpriteKit“开始”按钮
【发布时间】:2016-12-11 23:47:45
【问题描述】:

如何在 StartButton 类中编写一个 touchesBegun 命令,该命令在场景中调用 start() 的任何实例已放置在其中?

我知道...可能是 OOP 101。但今天远远超出我的范围。

更新:

这是我目前(部分)解决问题的方法。感觉不对,但它在某种程度上有效。没有我想要的那么多:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    SoundManager.playSceneStartSound()
    run(ready)
     if CEO.startButtonIsActive{
        print("We're STARTING NOW...")
        if let menuScene = self.scene as? Menu_Memory {
            menuScene.startTheGame()
            }
        else
        if let menuScene = self.scene as? Menu_Chaser {
            menuScene.startTheGame()
            }
        else
        if let menuScene = self.scene as? Menu_Picker {
            menuScene.startTheGame()
            }
        else
        if let menuScene = self.scene as? Menu_Q_AndA {
            menuScene.startTheGame()
            }
        else
        {print("Houston, we have a problem... no gameScene")}
        }
    else
    {
    print("You still have some preparation to do, amigo!")
    }
}

或者,传递类类型的能力也会有所帮助。这几乎是一个单独的问题,但事实上我认为它们可能非常密切相关。

无论如何:在按钮中,尝试创建对类类型的引用,我尝试了很多变体,但都没有运气。

我的一些荒谬的尝试,都失败了:

Menu_Memory 是一个 SKScene

    var menuClass01: Menu_Memory.self
    var menuClass02: AnyClass = Menu_Memory.self
    var menuClass03: AnyClass = Menu_Memory(self)
    var menuClass04: AnyClass as! Menu_Memory.self
    var menuClass05: AnyClass as! Menu_Memory(self)

【问题讨论】:

  • 您的意思是如何从另一个类(可能是 SKSpriteNode 的子类)中调用场景中定义的方法?如果是这样,请使用委托。我已经回答过几次类似的问题。您需要的是场景将遵循的协议,按钮上的委托属性。因此,当您按下按钮时,它将执行 self.delegate.start() 。 start() 是您应该在协议中声明并在场景中实现它的方法。按钮的委托属性应在按钮创建后设置。
  • 这在我看来很像希腊语。没有协议,这能做到吗?
  • 这就是您想要实现的目标?这不是希腊语,你会看到的。我将向您发布我的答案之一的示例,其中对此进行了详细说明。另一种方式......嗯......可能还有更多的方式。尝试扩展您的问题以解释确切的情况,我或其他人会告诉您什么是好方法。
  • 我对如何使用协议的理解非常有限,对如何使用委托和委托的理解更是少之又少。尽管使用了几次,并且它在我正在从事的项目中......我正在查看自己的代码,对它的理解为零。
  • 明天我将在我们的 SKA Slack 频道中向您解释委托模式和协议。我对类似问题的回答之一:stackoverflow.com/a/36524132

标签: swift sprite-kit


【解决方案1】:

更新 现在我知道你在做什么了。应该是不言自明的。如果不是就骂我:

public extension SKScene {
  func startGame() { // Because startTheGame is a terriblename..
    // Override in your subclasses of SKScene if desired.
  }
}

enum Menu { // Used as namespace for chaser and menu classes

  final class Chaser: SKScene {
    override func startGame() {
      print("chaser started")
    }
  }

  final class Memory: SKScene {
      override func startGame() {
      print("memory started")
    }
  }
}

.

final class Button: SKNode {
  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    scene!.startGame() // No need for guard / if-let,
                       // because how can you click the node if its scene is nil :)?
  }
}

【讨论】:

  • 就个人而言,您可能希望避开 OOP 往往需要的东西,例如复杂的委托和继承等......您是更多的过程型程序员,并且您在程序中输入的状态(变量)越多,它就会变得越混乱/越难调试。不过协议很好。耦合可以是好的,虽然它被普遍回避..如果它对你有意义,那么这样做比没有(代表)更好。这就是为什么我倾向于尽量减少类并只使用函数,因为相比之下,这两个选项都不好/复杂
  • 虽然在 OOP 框架中工作时,很难与之抗争......所以我不会制作委托,而是将 vars / funcs 拉出并将它们放在文件范围内(例如具有多个视图控制器的应用程序)。另一种选择是manager 类或耦合,或聪明的功能。
  • 查看问题的更新,看看我想出什么来解决开始按钮知道它在哪里的部分问题......
  • 至于您的 cmets 关于 OOP 方法等...如果我知道您在说什么,我可能不需要问这些问题 ;)
  • @Fluidity 所以,按照这种模式,你可能会得到一个场景,其中有很多方法什么都不做,不是吗?假设您需要更多方法。像 endGame()、pauseGame() ... 还有一些场景...例如 MenuScene、GameplayScene、LevelSelectScene 、 SettingsScene 等。 endGame() 和 pauseGame() 方法特定于 GameplayScene()... 但其他三个场景也会有所有这些方法,实际上什么都不做,意味着它们根本没有目的。你怎么看?就个人而言,我认为您的解决方案会起作用,但它不是一个理想的设计......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多