14

我在 SO 上没有看到这个问题的答案,这让我担心它非常简单,我只是错过了一些东西,但这里有。

背景,随意跳过:我需要一门我多年前跳过的学士学位课程。理论上它是计算机图形学,但自从我离开后,它变得更像是游戏开发。这很棒,因为对我来说,它比填充算法和翻译以及过去的其他东西更有趣。这是每隔一年才开设的第 4 年课程,但我设法说服该部门让我对同一主题进行第 4 年的独立研究,并称这已经足够好了。

“运行”独立研究的教授不教授实际的计算机图形学课程,所以虽然他是一个聪明人,但这并不是他真正的领域。所以我的大部分问题都留给了我,一本教科书和互联网。你知道......就像一个独立的研究应该是。:)

/背景

我有一个喜欢开发游戏系统的朋友。我计划将他的一款桌面游戏制作成使用 XNA 的电脑游戏。

我没有预见到游戏机制有任何无法克服的挑战,但我很好奇的一件事是大多数游戏如何保存它们的内容?我的意思是通过几种方式,希望我能清楚地表达出来。

以您玩过的任何 RPG 为例。您可以点击“保存”按钮并保存世界、您的角色信息以及任何其他必要的信息。然后稍后您可以点击“加载”按钮并将其恢复。

还是NPC对话的情况。当我碰到 Merchant #853 时,他随机吐出 3 种不同的问候语之一。

还有其他我能想到的,但它们实际上只是同一主题的变体。即使有这两个例子,在我看来也可以使用相同的机制,但那个机制是什么?

我从事 Web 开发已有多年,所以我的思绪会自动跳到“数据库!”。数据库是任何问题的解决方案。我可以看到它在这里是如何工作的,但开销似乎相当陡峭。“这是我的 6mb 编译游戏……哦,还有 68mb 的 MySQL 安装。” 或者更糟糕的是,因为我使用的是 XNA,也许我需要找到一种方法来捆绑 SQL Server。:)

我想也许是 XML,但这对我来说也不合适。如果我想在 Xbox 上运行,它将如何工作?还是祖尼?(这些对于我正在做的事情不是必需的,但必须有一个解决方案将它们考虑在内。)

有谁知道其中的秘密?还是有一些想法?

谢谢杰夫

4

6 回答 6

11

保存游戏的方式主要有两种,一种是简单的,一种是复杂的。第一种方法是简单地存储当前级别、当前分数和一些其他统计数据。这在诸如超级马里奥银河之类的游戏和大多数早期基于控制台模块的游戏中都可以看到。保存游戏不会恢复您的确切位置,而只会恢复您已完成的关卡。这些存档游戏通常非常简单,并且只需要很少的内存。

第二种方式不仅存储了你的整体进度,还存储了每一个小细节,比如敌人的位置、他们当前的动画帧等等,这样加载一个保存游戏就会把你放在你停下来的确切位置,所有敌人就在原地,而不是回到关卡的开始。这些存档游戏往往比其他版本大得多,因此主要出现在 PC 游戏中。

这两种方案都没有使用数据库,因为数据库的目的是提供动态查询数据结构的能力,但游戏需要的不是查询单个片段的方法,而只是一种静态存储它们的方法。加载存档游戏时,它会完全加载到内存中,然后游戏引擎会从那里处理数据。有少数例外,例如 MMORPG 可以在数据库上运行,但单人游戏通常不能。

数据的实际存储方式取决于游戏。最常见的似乎是简单的二进制数据格式,因为它们在磁盘空间方面比 XML 要好得多。在较旧的游戏中,那些二进制格式通常会原始转储游戏进程的一段内存,因此它们没有任何经过深思熟虑的结构,并且在发布补丁或不同版本的游戏时经常会崩溃,在一些现代游戏中游戏仍然如此。也可以使用 XML 以及任何其他基于文本的文件格式。

在很大程度上,这更像是一个游戏设计问题,而不是一个编程问题,因为他们保存游戏的方式可以极大地改变游戏的玩法。简单的方法,您只需保存关卡编号和一些统计信息,但实现起来要容易得多,因为它只需几行代码。而第二个需要序列化你的大部分类,这对于复杂的游戏可能是一个相当棘手的问题,并导致许多微妙的错误。

于 2009-05-11T01:22:41.843 回答
6

一种方法是使用 .net 序列化。

确保您的游戏状态是一个完全连接的图,并且该图中的每个类都标记为可序列化(使用 SerializableAttribute),保存(和加载)您可以使用正常的 .net 序列化。

您可以查看Project Xenocide(开源 XNA 游戏)的代码库,了解它是如何完成的。

于 2009-05-09T21:42:45.830 回答
5

您可以使用带有SQLite.NET 包装器的SQLite数据库。我用过这个,发现它很简单。整个 DLL 只有 850KB,数据库本身位于一个文件中(根据需要创建临时文件)。所以你的用户不应该有问题。

但您也可以使用简单的 XML 文件,或自制的二进制格式。这完全取决于您将如何查询数据,以及涉及多少数据。没有一个答案。

于 2009-05-09T21:52:21.970 回答
2

正如其他人所指出的,序列化是要走的路。而 Gamasutra 刚刚发表了一篇关于数据烘焙的文章。

于 2009-05-09T22:52:11.733 回答
1

从我有限的游戏开发经验来看,保存游戏真的不会占用太多存储空间。正如 tvanfosson 所说,您通常在玩游戏时将大部分内容存储在内存中,因此将状态保存到磁盘不是问题。

这是一个简短的例子。假设是单人角色扮演游戏,如果您只需要保存角色的位置,您可能需要一个级别编号、xyz 坐标以及您所面对的方向。那只是几个字节。

现在假设您需要保存诸如健康包、板条箱、敌人、角色的健康和拾取的物品等的状态/位置。您最多可以有几百个这样的东西,很容易小于 10KB。

显然,对于更复杂的游戏,事情会变得非常复杂。诀窍是只存储重新创建玩家体验真正需要的内容。很多游戏只让你在某些地方保存,比如关卡结束。在这种情况下,您只需要存储新的关卡编号加上之前关卡的结果(例如剩余生命值、拾取物品)。

即使您允许任意保存点,您也可以忽略您无法返回的任何地点/关卡的状态。而且您可能不希望用户能够保存中跳。

编辑:关于文件格式......使用任何方便数据类型的方式!XML 是一种很好的做事方式。不确定数据库的有效性,因为对于 RPG 来说,每个数据片段都可能非常不同;您最终可能会得到一堆表,每个表都有一行。

大多数游戏使用自己的二进制文件格式。首先,这大大减少了存储量。其次,它可以通过手动编辑保存游戏来帮助防止用户作弊 - 如果您有 XML 之类<health value="10"/>的文件,则可以很容易地编辑文件以读取<health value="100"/>。二进制的缺点是调试起来要困难得多。

于 2009-05-09T22:33:44.787 回答
0

在游戏运行时,我会尝试将与当前上下文相关的所有内容保存在内存中。您的初始化可以以某种合适的序列化格式保存并在启动时读取。XML 可以工作,但它有点冗长。自定义的紧凑二进制格式可能更合适。保存状态也是如此。加载保存的游戏时需要重新初始化的任何对象都应序列化为自定义二进制格式,然后在加载时重新构建。如果遇到内存问题,为速度优化的小型自定义数据库将是另一种选择。它可以在安装时预先填充。

于 2009-05-09T21:45:33.063 回答