通常在Sprite套件游戏中,当呈现新场景时,旧场景中的所有节点及其内容会自动删除。现在是什么,如果像“HUD”这样的节点不应该被删除?在精灵套件中有没有什么方法可以创建节点一次,并在所有场景中使用它,而不必每次在每个新场景中一次又一次移除和创建节点?必须有一种技术使之成为可能。这是一个严重的精灵套件设计问题,如果这是不可能的。但我不这么认为。单身技术对于音频播放器来说非常有效,它只创建一次并用于所有场景。有一种方法可以只创建一次节点并在所有场景中使用它。感谢您的任何想法。Sprite Kit:只为所有场景创建节点一次
回答
您无法创建在场景之间持续存在的节点。一旦您呈现新场景,您需要将节点添加到此新场景中。
由于这个原因,我没有像苹果在文档中描述的那样使用SKScenes。不仅每次都需要将节点添加到新场景中,而且对于像后台节点这样总是应该存在的节点而言,效率非常低。
所以我做的是创建2个场景,一个用于游戏场景,另一个用于菜单(GUI)。
对于菜单场景,我将SKNodes分类为我的界面,然后使用这些节点上的SKActions在屏幕上呈现和解除它们,以便感觉用户正在场景之间转换。这可以为您提供完全的定制,因为您可以呈现多个节点,您可以永久保持屏幕上的节点等。
通过继承SKNode,您可以像组织场景一样组织代码。每个节点将代表您的应用程序中的一个“场景”。然后,您只需编写一个方法来呈现和解散这些节点。
我添加了下面的一些示例代码显示一个实现利用SKNodes
作为的“场景”。示例代码有一个我们继承的名为SceneNode
的基类(就像您将子类SKScene
一样)。在这个实现中,我使用GameScene
来处理场景节点*之间的所有转换。我还跟踪当前场景节点,以便在场景更改大小(例如旋转或窗口调整大小的OS X **)时更新其布局。你的游戏可能不需要这个,但它是动态布局节点的好方法。任何你想添加到背景或保持的东西,只需将它添加到GameScene
即可。任何你想添加到场景中的东西,仅仅是子类SceneNode
,过渡到它和你的好去处。
*您可以直接从其他场景节点直接呈现场景节点,而无需通过GameScene。但是我发现使用GameScene来处理节点之间的转换效果非常好,特别是当你有很多复杂转场的场景时。
** OS X有一个错误,调整窗口的大小不会调用场景的didChangeSize。你需要手动调用它。
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = GameScene(size:self.view.bounds.size)
scene.scaleMode = .ResizeFill
(self.view as! SKView).presentScene(scene)
}
}
class GameScene: SKScene {
var currentSceneNode: SceneNode!
override func didMoveToView(view: SKView) {
self.backgroundColor = SKColor.whiteColor()
transitionToScene(.Menu)
}
override func didChangeSize(oldSize: CGSize) {
currentSceneNode?.layout()
}
func transitionToScene(sceneType: SceneTransition) {
switch sceneType {
case .Menu:
currentSceneNode?.dismissWithAnimation(.Right)
currentSceneNode = MenuSceneNode(gameScene: self)
currentSceneNode.presentWithAnimation(.Right)
case .Scores:
currentSceneNode?.dismissWithAnimation(.Left)
currentSceneNode = ScoresSceneNode(gameScene: self)
currentSceneNode.presentWithAnimation(.Left)
default: fatalError("Unknown scene transition.")
}
}
}
class SceneNode: SKNode {
weak var gameScene: GameScene!
init(gameScene: GameScene) {
self.gameScene = gameScene
super.init()
}
func layout() {}
func presentWithAnimation(animation:Animation) {
layout()
let invert: CGFloat = animation == .Left ? 1 : -1
self.position = CGPoint(x: invert*gameScene.size.width, y: 0)
gameScene.addChild(self)
let action = SKAction.moveTo(CGPoint(x: 0, y: 0), duration: 0.3)
action.timingMode = SKActionTimingMode.EaseInEaseOut
self.runAction(action)
}
func dismissWithAnimation(animation:Animation) {
let invert: CGFloat = animation == .Left ? 1 : -1
self.position = CGPoint(x: 0, y: 0)
let action = SKAction.moveTo(CGPoint(x: invert*(-gameScene.size.width), y: 0), duration: 0.3)
action.timingMode = SKActionTimingMode.EaseInEaseOut
self.runAction(action, completion: {self.removeFromParent()})
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class MenuSceneNode: SceneNode {
var label: SKLabelNode
var container: SKSpriteNode
override func layout() {
container.position = CGPoint(x: gameScene.size.width/2.0, y: gameScene.size.height/2.0)
}
override init(gameScene: GameScene) {
label = SKLabelNode(text: "Menu Scene")
label.horizontalAlignmentMode = .Center
label.verticalAlignmentMode = .Center
container = SKSpriteNode(color: UIColor.blackColor(), size: CGSize(width: 200, height: 200))
container.addChild(label)
super.init(gameScene: gameScene)
self.addChild(container)
self.userInteractionEnabled = true
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.gameScene.transitionToScene(.Scores)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class ScoresSceneNode: SceneNode {
var label: SKLabelNode
var container: SKSpriteNode
override func layout() {
container.position = CGPoint(x: gameScene.size.width/2.0, y: gameScene.size.height/2.0)
}
override init(gameScene: GameScene) {
label = SKLabelNode(text: "Scores Scene")
label.horizontalAlignmentMode = .Center
label.verticalAlignmentMode = .Center
container = SKSpriteNode(color: UIColor.blackColor(), size: CGSize(width: 200, height: 200))
container.addChild(label)
super.init(gameScene: gameScene)
self.addChild(container)
self.userInteractionEnabled = true
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.gameScene.transitionToScene(.Menu)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
enum SceneTransition{
case Menu, Scores
}
enum Animation {
case Left, Right, None
}
非常感谢。这就是我的意思和我正在寻找的东西。国际海事组织(IMO)在精灵套件的概念/设计方面存在严重缺陷。我认为,必须可以在所有场景中使用相同的节点(例如背景发射器节点),而不是每次在每个新场景中创建它。正如你所描述的,我接受你的伟大答案,我会尽力去做。谢谢! – suyama 2015-03-31 19:11:21
- 1. 无法将节点添加到我的场景(Sprite Kit)
- 2. 如何初始化Sprite Kit中的所有场景?
- 3. Sprite Kit中的弹跳节点
- 4. Sprite kit节点在接触时口吃
- 5. Sprite-Kit:一个场景中有两种不同的重力矢量?
- 6. 模拟两个Sprite Kit节点的万有引力
- 7. 如何判断是否所有的特定节点都在Sprite-Kit中去掉
- 8. 如何更改Scene Kit中的场景?
- 9. 如何在Xcode sprite-kit中为不同的场景运行不同的代码?
- 10. Sprite-Kit错误
- 11. Sprite Kit SKPhysicsJoint
- 12. Sprite Kit Objective C
- 13. beginner swift sprite kit - 节点碰撞检测帮助(SKPhysicsContact)
- 14. 如何用核心运动来移动Sksprite节点? (sprite kit)
- 15. Swift - 使Sprite Kit节点仅受重力影响?
- 16. 黄瓜:在所有场景的钩子运行只有一次之前
- 17. Swift 3.0 - Sprite Kit - Multitouch
- 18. Sprite Kit中的多点触控手势
- 19. 创建节点只是为了存储父节点的属性
- 20. 现在的演练场景只有一次ios swift
- 21. 无法在Sprite Kit中创建静态HUD
- 22. 如何将节点定位到Sprite Kit中的圆周上的随机点?
- 23. 移动数组中的所有对象 - IOS和Sprite Kit
- 24. 为babylon.js场景创建模块
- 25. 如何为ARKit创建场景文件?
- 26. ios sprite kit bodyWithBody not working
- 27. Sprite Kit SKActions未开火
- 28. 启用Sprite Kit Multiple Touch
- 29. 如何创建照亮所有场景的照明?
- 30. 初学xcode swift sprite kit - 删除名称为sprite的精灵
到底在追求什么呢?它是实际创建节点的代码吗?存储值?都? – sangony 2015-03-31 12:22:10
@sangony我只说“HUD”。我正在努力的是,我只想创建一个节点(例如SKEmitterNode)一次并在所有游戏场景中使用它。当我创建一个节点并将其添加到场景中时,当出现新场景时,该节点将自动删除。我必须在新场景中再次创建节点。我必须一次又一次地在每个新场景中创建相同的节点。因此,我只想创建节点一次,并在所有场景中使用它,而无需在每个场景中移除和创建节点。我希望,现在很清楚,我正在努力。 Otherways让我知道。感谢您的任何想法。 – suyama 2015-03-31 12:56:37
好的... ...这将被称为类实例化。为节点创建一个自定义SKEmitterNode类,并在加载新场景时创建它的一个实例。 – sangony 2015-03-31 13:01:47