这似乎是人们在使用 SpriteKit 游戏时经常遇到的问题,所以让我们来看看 SpriteKit 游戏和 UIKit 应用程序之间的区别。
当你制作一个常规的 UIKit 应用程序时,例如YouTube、Facebook,您将为您看到的每个屏幕/菜单(主屏幕、频道屏幕、订阅频道屏幕等)使用 ViewControllers、CollectionViews、Views 等。因此,您可以为此使用 UIKit API,例如 UIButtons、UIImageViews、UILabels、UIViews、UICollectionViews 等。为了直观地做到这一点,我们将使用故事板。
另一方面,在 SpriteKit 游戏中,它的工作方式有所不同。您为您看到的每个屏幕(MenuScene、SettingsScene、GameScene、GameOverScene 等)使用 SKScene,并且只有 1 个 ViewController (GameViewController)。包含 SKView 的 GameViewController 将呈现您的所有 SKScene。
因此,我们应该使用 SpriteKit API(例如 SKLabelNodes、SKSpriteNodes、SKNodes 等)直接将我们的 UI 添加到相关的 SKScene 中。要直观地做到这一点,我们将使用 SpriteKit 场景关卡编辑器而不是故事板。
所以一般逻辑是像往常一样从 GameViewController 加载您的第一个 SKScene,而不是从相关的 SKScene 中加载其余部分。除了默认代码之外,您的 GameViewController 基本上应该没有代码。您还可以非常轻松地从一个场景过渡到另一个场景(GameScene -> GameOverScene)。
如果您将 GameViewController 用于您的 UI,如果您有多个 SKScene,它会很快变得混乱,因为 UI 将被添加到 GameViewController 并因此添加到所有 SKScene。因此,当您在场景之间转换时,您将不得不删除/显示 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)
希望对你有帮助