我在 main.storyboard 上创建了一个 UI 元素,我需要隐藏它直到游戏结束并且一旦玩家点击屏幕关闭。 Main.storyboard 链接到 GameViewController,因此我所有的 IBOutlets 和 IBActions 都在那里,我所有的游戏代码都在 GameScene 中。我如何将 View Controller 链接到场景,因为只有在游戏结束时才会出现弹出图像​​和按钮。非常感谢一些帮助,我已经坚持了很长一段时间了。

最佳答案

这似乎是人们在使用 SpriteKit 游戏时遇到的一个普遍问题,所以让我们来看看 SpriteKit 游戏和 UIKit 应用程序之间的区别。

当你制作一个普通的 UIKit 应用程序时,例如YouTube、Facebook,您会为您看到的每个屏幕/菜单(主屏幕、 channel 屏幕、订阅 channel 屏幕等)使用 ViewControllers、CollectionViews、Views 等。因此,您将为此使用 UIKit API,例如 UIButtons、UIImageViews、UILabels、UIViews、UICollectionViews 等。为了直观地做到这一点,我们将使用 Storyboard。

另一方面,在 SpriteKit 游戏中,它的工作方式有所不同。您为看到的每个屏幕(MenuScene、SettingsScene、GameScene、GameOverScene 等)使用 SKScene,并且只有 1 个 ViewController (GameViewController)。包含 SKView 的 GameViewController 将展示您的所有 SKScene。

因此,我们应该使用 SpriteKit API(例如 SKLabelNodes、SKSpriteNodes、SKNodes 等)将我们的 UI 直接添加到相关的 SKScene 中。为了直观地做到这一点,我们将使用 SpriteKit 场景级别编辑器而不是 Storyboard。

所以一般的逻辑是像往常一样从 GameViewController 加载你的第一个 SKScene,而不是从相关的 SKScene 中完成其余的工作。除了默认代码之外,您的 GameViewController 基本上应该没有任何代码。您还可以非常轻松地从一个场景过渡到另一个场景(GameScene -> GameOverScene)。

如果您将 GameViewController 用于您的 UI,如果您有多个 SKScene,它会很快变得困惑,因为 UI 将被添加到 GameViewController 中,因此会添加到所有 SKScenes。因此,当您在场景之间转换时,您必须删除/显示 UI,这太疯狂了。

要在 SpriteKit 中添加标签,它会是这样的

 class GameScene: SKScene {

  lazy var scoreLabel: SKLabelNode = {
      let label = SKLabelNode(fontNamed: "HelveticaNeue")
      label.text = "SomeText"
      label.fontSize = 22
      label.fontColor = .yellow
      label.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
      return label
  }()

  override func didMove(to view: SKView) {

      addChild(scoreLabel)
  }
}

要制作按钮,您本质上创建一个 SKSpriteNode 并为其命名,然后在 touchesBegan 或 touchesEnded 中查找它并在其上运行 SKAction 以获取动画和一些代码。
enum ButtonName: String {
     case play
     case share
}

class GameScene: SKScene {

       lazy var shareButton: SKSpriteNode = {
            let button = SKSpriteNode(imageNamed: "ShareButton")
            button.name = ButtonName.share.rawValue
            button.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
            return button
        }()

       override func didMove(to view: SKView) {

             addChild(shareButton)
       }

       /// Touches began
       override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

             for touch in touches {
                 let location = touch.location(in: self)
                 let node = atPoint(location)

                 if let nodeName = node.name {
                      switch nodeName {
                      case ButtonName.play.rawValue:
                          // run some SKAction animation and some code
                      case ButtonName.share.rawValue:

                          let action1 = SKAction.scale(to: 0.9, duration: 0.2)
                          let action2 = SKAction.scale(to: 1, duration: 0.2)
                          let action3 = SKAction.run { [weak self] in
                             self?.openShareMenu(value: "\(self!.score)", image: nil) // image is nil in this example, if you use a image just create a UIImage and pass it into the method
                          }
                          let sequence = SKAction.sequence([action1, action2, action3])
                          node.run(sequence)

                      default:
                          break
                    }
               }
          }
     }
}

为了使这更容易,我将创建一个按钮助手类,对于一个简单的例子,看看这个
https://nathandemick.com/2014/09/buttons-sprite-kit-using-swift/

您还可以查看 Apple 的示例游戏 DemoBots 以获得功能更丰富的示例。

这样你就可以在助手类中拥有诸如动画等内容,而不必为每个按钮重复代码。

为了分享,我实际上会使用 UIActivityController 而不是那些可能很快就会被弃用的旧社交 API。这也允许您通过 1 个 UI 共享到多个服务,并且您的应用程序中也只需要 1 个共享按钮。在您调用它的 SKScene 中,它可能是一个像这样的简单函数。
func openShareMenu(value: String, image: UIImage?) {
    guard let view = view else { return }

    // Activity items
    var activityItems = [AnyObject]()

    // Text
    let text = "Can you beat my score " + value
    activityItems.append(text as AnyObject)

    // Add image if valid
    if let image = image {
        activityItems.append(image)
    }

    // Activity controller
    let activityController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

    // iPad settings
    if Device.isPad {
        activityController.popoverPresentationController?.sourceView = view
        activityController.popoverPresentationController?.sourceRect = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
        activityController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.init(rawValue: 0)
    }

    // Excluded activity types
    activityController.excludedActivityTypes = [
        UIActivityType.airDrop,
        UIActivityType.print,
        UIActivityType.assignToContact,
        UIActivityType.addToReadingList,
    ]

    // Present
    view.window?.rootViewController?.present(activityController, animated: true)
}

然后在按下正确的按钮时像这样调用它(见上面的例子)
openShareMenu(value: "\(self.score)", image: SOMEUIIMAGE)

希望这可以帮助

关于ios - 将 GameViewController.swift 链接到 GameScene.swift,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40667861/

10-14 02:35