Swift 3(SpriteKit):游戏结束后重置GameScene
我想’重置’并’重启’GameScene所以就好像GameScene首次被调用一样.我已经查看了不同的方法,但每次我收到警告,我正在尝试将节点添加到已有父节点的父节点.但是,在我的代码中,我删除了所有现有节点,所以我真的很困惑如何重置GameScene.这就是我现在这样做的方法(当我想从头开始重新启动GameScene并在GameScene类中调用时,会调用此代码):
let scene = GameScene(size: self.size) scene.scaleMode = .aspectFill let animation = SKTransition.fade(withDuration: 1.0) self.view?.presentScene(scene,transition: animation) self.removeAllChildren() self.removeAllActions() self.scene?.removeFromParent() 1.编辑:我意识到为什么我会收到这个警告:“我正在尝试将节点添加到已经拥有父节点的父节点”,因为我拥有类外部场景的所有变量以及全局变量.但是,现在当游戏重新开始时,游戏就在左下角.为什么会这样,我该如何解决这个问题呢? – 固定 2.Edited:现在一切正常,但现在我担心的是即使删除了每个节点并且fps不会随着时间的推移而丢失,也不会调用deinit {}.这是我在GameViewController中用于设置场景和我的GameScene中的内容(每个与场景相关的实例基本上都是相关的): import UIKit import SpriteKit import GameplayKit var screenSize = CGSize() class GameViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() if let view = self.view as! SKView? { // Load the SKScene from 'GameScene.sks' if let scene = SKScene(fileNamed: "GameScene") { // Set the scale mode to scale to fit the window scene.scaleMode = .aspectFill screenSize = scene.size // Present the scene view.presentScene(scene) } view.ignoresSiblingOrder = true view.showsFPS = true view.showsNodeCount = true } } 然后我的GameScene基本上是: import SpriteKit import GameplayKit class GameScene: SKScene,SKPhysicsContactDelegate { //Declare and initialise variables and enumerations here deinit{print("GameScene deinited")} override func didMove(to view: SKView) { //Setup scene and nodes } override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) { //Do other things depending on when and where you touch //When I want to reset the GameScene let newScene = GameScene(size: self.size) newScene.anchorPoint = CGPoint(x: 0.5,y: 0.5) newScene.scaleMode = self.scaleMode let animation = SKTransition.fade(withDuration: 1.0) self.view?.presentScene(newScene,transition: animation) } 任何答案将不胜感激:)
如何重置场景?
您只需要随时再次呈现一个新的相同场景.所以,你做得很好. 可能的泄漏问题? 此外,如果你的游戏中没有泄漏,意味着没有强大的参考周期,你甚至不需要self.removeAllChildren()和self.removeAllActions()……当然如果你明确想要在转换之前停止动作动画开始,使用这种方法是有道理的.关键是,当场景解除分配时,依赖于它的所有对象也应该/将要解除分配. 不过,如果你从一开始就不知道你在做什么以及如何防止泄漏,例如.你在块中使用强自我,这是一个动作序列的一部分,它永远重复,然后你肯定有一个泄漏,self.removeAllActions()可能会有所帮助(在很多情况下,但它不是一个最终的解决方案).我建议一般阅读有关捕获列表和ARC的内容,因为了解这些情况是如何工作的. 场景是根节点 在场景上调用removeFromParent()无效.场景是根节点,因此无法在当前上下文中删除它.如果你检查场景的父属性,你会发现它是零.当然可以将场景添加到另一个场景,但是在这种情况下,作为子场添加的场景将充当普通节点. 最后,如何呈现新场景?容易,像这样: override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) { let newScene = GameScene(size: self.size) newScene.scaleMode = self.scaleMode let animation = SKTransition.fade(withDuration: 1.0) self.view?.presentScene(newScene,transition: animation) } 如果某些内容对您不起作用,则可能是您有泄漏(意味着您的场景未被释放).要检查这一点,在GameScene中的某处覆盖deinit方法,如下所示: deinit{print("GameScene deinited")} 为了进一步向你解释……应该发生的是你应该呈现一个新场景,应该发生转换,应该取消分配旧场景,你应该看到一个具有初始状态的新场景. 覆盖deinit也会告诉您场景是否正确解除分配.但它不会告诉你原因.您可以在代码中找到保留场景的内容. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |