将GameViewController.swift链接到GameScene.swift

我已经在main.storyboard上创建了一个UI元素,我需要将其隐藏起来,直到游戏结束,玩家点击屏幕才能解除。 Main.storyboard链接到GameViewController,因为我所有的IBOutlets和IBActions都在那里,我所有的游戏代码都在GameScene中。 如何将视图控制器链接到场景,以便弹出图像和按钮仅在游戏结束时出现。 非常感谢一些帮助,我已经坚持了很长一段时间了。

这似乎是人们对SpriteKit游戏的一个常见问题,所以让我们来看看SpriteKit游戏和UIKit应用程序之间的区别。

当您制作常规UIKit应用程序(例如YouTube,Facebook)时,您将使用ViewControllers,CollectionViews,Views等为您看到的每个屏幕/菜单(主屏幕,频道屏幕,订阅频道屏幕等)。 因此,你可以使用UIKit API,如UIButtons,UIImageViews,UILabels,UIViews,UICollectionViews等。为了做到这一点,我们将使用故事板。

另一方面,在SpriteKit游戏中它的工作方式不同。 您可以使用SKScenes查看您看到的每个屏幕(MenuScene,SettingsScene,GameScene,GameOverScene等),并且只有1个ViewController(GameViewController)。 具有SKView的GameViewController将呈现您的所有SKScenes。

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

因此,一般的逻辑是像往常一样从GameViewController加载你的第一个SKScene,而不是从相关的SKScenes中加载其余的。 除了默认代码之外,你的GameViewController基本上应该没有代码。 您也可以非常轻松地从1个场景转换到另一个场景(GameScene – > GameOverScene)。

如果您的UI使用GameViewController,如果您有多个SKScenes,它将会很快变得混乱,因为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, 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,获取更多function丰富的示例。

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

对于共享,我实际上会使用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) 

希望这可以帮助

像这样在GameScene类中创建GameViewController的引用

 class GameScene: SKScene, SKPhysicsContactDelegate { var referenceOfGameViewController : GameViewController! } 

在GameViewController中以这种方式传递引用

  class GameViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() if let view = self.view as! SKView? { // Load the SKScene from 'GameScene.sks' if let scene = GameScene(fileNamed: "GameScene") { // Set the scale mode to scale to fit the window scene.scaleMode = .aspectFill scene.referenceOfGameViewController = self // Present the scene view.presentScene(scene) } view.ignoresSiblingOrder = true view.showsFPS = true view.showsNodeCount = true } } } 

通过使用此行,您可以传递对GameScene类的引用

  scene.referenceOfGameViewController = self 

现在在GameScene类中,您可以像这样访问GameViewController的所有变量

 referenceOfGameViewController.fbButton.hidden = false referenceOfGameViewController.gameOverPopUP.hidden = false