加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Swift 3(SpriteKit):游戏结束后重置GameScene

发布时间:2020-12-14 05:48:46 所属栏目:百科 来源:网络整理
导读:我想’重置’并’重启’GameScene所以就好像GameScene首次被调用一样.我已经查看了不同的方法,但每次我收到警告,我正在尝试将节点添加到已有父节点的父节点.但是,在我的代码中,我删除了所有现有节点,所以我真的很困惑如何重置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也会告诉您场景是否正确解除分配.但它不会告诉你原因.您可以在代码中找到保留场景的内容.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读