Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 精灵套件游戏生命周期、属性和全局变量?_Ios_Swift_Sprite Kit - Fatal编程技术网

Ios 精灵套件游戏生命周期、属性和全局变量?

Ios 精灵套件游戏生命周期、属性和全局变量?,ios,swift,sprite-kit,Ios,Swift,Sprite Kit,在我的精灵套件游戏中,我的游戏经历了各种场景,我希望在这些场景中可以使用某些变量。见下图: 因此,标题屏幕加载游戏主屏幕。当“波浪”结束时(所有目标完成或所有生命损失),结束场景将显示一些统计信息。然后,如果玩家已经离开,则再次加载主游戏,如果没有,则再次显示标题屏幕 我希望玩家的分数和剩余的生命数在游戏主场景和结束场景中都可用;所有场景都应保持高分 对于这些,我使用全局变量,而我的大多数变量都是在类下定义的属性 第一次我必须这样做(在我添加高分或多个生命之前,我的分数属性)我在每个场景中使用

在我的精灵套件游戏中,我的游戏经历了各种场景,我希望在这些场景中可以使用某些变量。见下图:

因此,标题屏幕加载游戏主屏幕。当“波浪”结束时(所有目标完成或所有生命损失),结束场景将显示一些统计信息。然后,如果玩家已经离开,则再次加载主游戏,如果没有,则再次显示标题屏幕

我希望玩家的分数和剩余的生命数在游戏主场景和结束场景中都可用;所有场景都应保持高分

对于这些,我使用全局变量,而我的大多数变量都是在类下定义的属性

第一次我必须这样做(在我添加高分或多个生命之前,我的分数属性)我在每个场景中使用分数属性,并在下一个场景的当前场景中在场景之间传递它,但这看起来很笨拙,尤其是当我不得不添加更多变量时

是否有最佳实践,即是否应使用/不使用全局变量,如果没有,是否有正确的方法来处理属性,可能由初始化属性的位置控制,例如在
init
中,与
didMoveToView
相比,后者确定在再次显示场景时是否重新初始化属性

编辑:


当我从End Wave场景返回到主游戏屏幕时,导致主屏幕再次初始化,我是否做错了什么?有没有办法保存它(及其所有属性),这样它就不会被完全重新初始化,但它的didMoveToView会被再次调用?

一般经验法则:如果可以避免全局变量,就这样做

现在每个节点都有一个称为
userData
的可变字典。这是用来将数据保存到节点的

创建新场景后,从旧场景传输所需的任何数据

let scene = SKScene(fileNamed:....)
scene.userData["highscore"] = self.highscore
view.presentScene(scene)
现在,在新的场景
didMove(视图:)
方法中,您可以从所说的
userData

正如0x141E所指出的,请记住,您需要初始化
userData
,因为您可能有一个自定义类,您可以在init方法中这样做,只需记住重写所有指定的init,这样您就可以访问便利方法

此外,正如Whirlwind和我之间的评论所述,
SKNode
符合
NSCoding
的要求,因此当您去保存信息时,您可以将
SKNode
作为一个整体保存,
userData
也会随之保存


这意味着您只需为
SKNode
编写一个扩展来保存/加载节点,这样就不必担心管理另一个类。

在游戏执行过程中,可能会发生很多事情,游戏崩溃,玩家关闭应用程序,互联网停止,节点可能会从父节点暂停(因此,当场景处理动作时,它将被跳过)。因此,我同意Simone Pistecchia的评论:您可以准备一个“存储管理器”类来加载和保存玩家统计数据,使用NSCoding来声明和初始化它们,使用共享实例类在整个项目中处理它们。通过这种方式,您可以在需要时加载和保存您的变量,并在游戏之外显示它们(到“高分”场景的主菜单,例如,在您想要的任何地方)

我知道很多人都使用诸如“不要使用全局变量”或“单身是邪恶的”之类的通用规则。这些智慧之词有时可能适用,但另一种看待它们的方式是将其作为工具,让你更有效地完成游戏

有时全局/单例是有用的。游戏和嵌入式系统按照不同于传统应用程序的规则运行。这些通常是资源受限的“应用程序”再加上性能要求。全局变量比你想象的更为普遍。单例变量也普遍使用。我在嵌入式系统和游戏方面都有工作,可以说在我从事的每个项目中,他们要么使用全局变量,要么使用单例变量,要么两者都使用

实践中,我用单体来处理全局变量。主要是因为我不必担心在哪里推全局和它的头文件。注意,为什么会不同于所有的SWIFTs。对于我来说,这些东西是在C++中用一些Obj-C和Swift。 管理游戏生命周期的需要与

SpriteKit
无关。我看到的许多
SpriteKit
帖子都让开发者将游戏状态嵌入场景或VC中。他们通常在如何将状态移动到下一个场景上面临一些难题。而这种方法可能有利于我所说的“本地状态”(即当前屏幕、舞台等的状态),这不利于全局游戏状态。例如,如果您从主屏幕过渡到选项屏幕,然后再回到主屏幕,然后在游戏中,您如何跟踪这些选项的更改(例如更改游戏难度)?是的,你当然可以传递字典、结构或你所拥有的东西。但在某个时候,你会发现拥有一个通用且方便的垃圾场更方便。这个“垃圾场”将是全局/单例

现在,在你开始对我大喊大叫之前,所有关于全球人和单身人士的疯狂讨论都有一个陷阱。我不是说创造大量的全球人/单身人士。相反,要控制你何时/如果你雇用全球人/单身人士

我说的不是无数,我说的就像一个(虽然我通常有一把)。输入我们虚构的朋友,
GameManager

让我们来看一个非常简单的太空射手场景。假设我有多个屏幕,如标题屏幕、主屏幕、游戏中屏幕和结束屏幕
class GameManager : NSObject {
    // Overall game state, GameState is probably some enum
    var state:GameState
    var lastState:GameState

    // Sometimes tracking scenes is useful
    var currentScene:SKScene?
    var nextScene:SKScene? // Sometimes helpful if you need to construct the next scene and it takes a non-trivial amount of time

    // These are the globals we need to share to different "parts" of the game
    var score: UInt
    var highscore: UInt
    var lives: Uint
    var stage: Uint

    var highscores:[Uint]   // A list of all the high score for the user. You would probably want HS based on other users too

    // Egads a singleton!
    static let sharedInstance = GameManager()
}
myScore += 100

// Do logic to find out if we get an extra life. 
// Is this done in a method and if so where does this method live?
// Or is it straight up code which will be duplicated?
class GameManager : NSObject {
    // Overall game state, GameState is probably some enum
    var state:GameState
    var lastState:GameState

    // Sometimes tracking scenes is useful
    var currentScene:SKScene?
    var nextScene:SKScene? // Sometimes helpful if you need to construct the next scene and it takes a non-trivial amount of time

    // These are the globals we need to share to different "parts" of the game
    // Note player state is done through this object. This way I can pass around only player when needed.
    var player: Player

    var stage: Uint

    var highscores:[Uint]   // A list of all the high score for the user. You would probably want HS based on other users too

    // Egads a singleton!
    static let sharedInstance = GameManager()
}
class PlayerState {
    var score:Uint
    var highscore:Uint
    var lives:Uint
}

// Simplified GameManager
class GameManager {
    var state:GameState
    var lastState:GameState

    var player:PlayerState

    // Egads a singleton!
    static let sharedInstance = GameManager()
}
func doSomething(playerState:PlayerState) {
    var score = playerState.score   

    // Blah blah blah
}
func doSomething() {
    // Whee I have singleton
    var score = GameManager.player.score

    // Blah blah blah
}