数学问题:星系的程序生成

时间:2008-12-07 23:32:52

标签: procedural-generation

我将制作一个完全由程序生成的太空/交易/战斗游戏。但是,我知道将整个星系的所有细节存储在记忆中是不可能的。因此,我一直认为我可以使用种子来生成太阳系,并且从太阳系中,您可以使用跳跃门来前往其他太阳系。问题是,如果我从起始太阳系跳到另一个太阳系,我需要能够回到具有相同特征(行星,小行星等)的完全相同的起始太阳系。

基本上,我需要能够从一个数字生成整个星系。从生成一个太阳系的那个数字开始,我需要能够生成所有其他太阳系,这些太阳系从第一个和所有与之相连的太阳系连接起来,依此类推。如果我回到它们,每个太阳系必须保持完全相同的特征。此外,每个太阳系的链接数量可以是随机的,也可以是固定的,您的选择。随机会更好。

19 个答案:

答案 0 :(得分:23)

如果你感到勇敢,那么你可能会比看看Ian Bell did it对原版精英

的看法更糟糕

答案 1 :(得分:15)

答案 2 :(得分:7)

这是我理解的基本想法。假设你已经到达了星系统#42,你需要找出其中的内容。它有nplanets个行星 - 一个0到10之间的数字,比如说:

>>> star_system = 42
>>> nplanets = hash('nplanets%d' % star_system) % (10 + 1)
>>> nplanets
4

好的,那么在第2号星球上,在游戏开始时有多少空间站在轨道上?找到0到3之间的数字:

>>> planet = 2
>>> nstations = hash('nstations%d/%d' % (star_system, planet)) % (3 + 1)
>>> nstations
1

等等。这些数字都是指数的散列函数(星系统#42,行星#2,在这种情况下),减少到适当的范围。由于散列函数是确定性的但是“随机”,每次都是相同的,但随机地看向播放器。

当然,散列具有长序列(如'nstations')的字符串并不是最快的方法,但它显示了这个想法。

答案 3 :(得分:6)

看一下原来的Worms游戏。 我认为它声称有大约40亿个可能的水平。 每个级别都是基于可能包含20个字符的短种子字符串生成的。 确定

  • 关卡的主题(北极,森林等......)
  • 景观的形状
  • 地面的滑溜
  • 预建水平细节(雪人,岩石......)的位置
  • 你的蠕虫,地雷和武器箱的安置。

如果您喜欢某个级别,您可以记下种子字符串,并在以后使用它来重新生成相同的级别。

这是一个非常复杂但确定性的函数的示例,具有单个输入参数。我认为这是你需要的基本概念。

答案 4 :(得分:5)

我认为值得注意的是,

  1. 为同一输入产生相同的随机输出的生成器称为伪随机数生成器“PRNG”。通常,您在一开始就给它一个“种子”输入数字,然后从中拉出随机数,在没有进一步输入的情况下调用它。注意:你不能“回到”前面的数字,至少在没有开始的情况下也是如此。

  2. 类似PRNG的函数,使用坐标作为每个调用的输入调用通常是“噪声”函数。在这里你没有“不能回头”的问题 - 只需再次使用“早期”输入。 噪声函数使用PRNG(作为后端;或者至少可以),它仍然可以在一开始播种,因此您不会丢失“超出一个数字”的特征。

  3. 虽然你每次都可以使用PRNG并将星系坐标组合成“种子”,但你最多只能获得“白噪声”,没有其他属性。噪音功能更适合这项工作,因为它可以选择甚至调整,以给你平铺/平滑/螺旋状外观/等。结果。 例如,搜索使用perlin噪声制作的纹理图像。 我希望你能看到具有相同噪音功能的产品,例如成千上万的随机云,但通过根据您的需要调整噪声函数(不仅仅是种子或坐标),您可能会得到熔岩或星系。尽管如此,调整它可能并非易事。

  4. 每个调用的输入坐标数决定了噪声函数的维数,因此对于二维地图(或纹理等),您可以使用二维噪声函数。然后你每次都称它为noise2d(x,y)。

  5. 在你的情况下,我会尝试一个三维单面噪声函数(simplex来自perlin噪声的作者,推荐为更好)。

    每个星系坐标 - 三元组然后给出一个结果编号。接下来的决定是:数字代表什么?为了充分利用单纯噪声的平滑特征,我将较低的数字映射到更多的太阳系,将更高的数字映射到质量更大的系统。 或者,更好的是,对于每个系统,使用子坐标多次调用单纯形噪声。中等大小的结果数字则是行星,小数字是真空或小行星。大数星等等。

    这个主题不活跃,而且已经过时了,但搜索结果可能就像我的一样。

答案 5 :(得分:5)

你不能只是SHA1星系ID,EG:

Galaxy 1

Sha1(1) = 356a192b7913b04c54574d18c28d46e6395428ab

Galaxy 2

Sha1(2) = da4b9237bacccdf19c0760cab7aec4a8359010b0

Galaxy 3

Sha1(3) = 77de68daecd823babbb58edb1c8e14d7106e83bb

然后您可以对代码进行细分,IE:

前4个Chars =行星数

356a
da4b
77de

你需要某种字符串编号算法,一个简单的算法是获取每个非数字字符的ASCII码,然后将它们全部加在一起或其他东西。

所以现在我们知道星系中有多少行星,星系x,y,z尺寸怎么样?

接下来9个字符=星系尺寸(x,y,z)

与上述原理相同,将代码转换为大数。进行一些敏感性检查,你不需要一个10英里×10英里×10英里的星系,其中有20万个行星。有一些加权算法,比如最小尺寸是行星数×10000。您需要使用数字来确保范围全部兼容,并且哈希中选定的字符实际上为您提供了合理的范围。

或者,您可以使用随机数在星系的最小和最大尺寸之间选择一个数字,但使用恒定的RNG种子,例如星系ID!这样,对于观察者来说,星系大小基本上是“随机的”,但它们每次都是相同的。

等等!

这是获取宇宙属性的一种方法,但行星属性呢?像人口和其他东西一样?

如果你有拥有20,000个行星的Galaxy 1,你可以这样做:

Sha1('1:340') = bc02ab36f163baee2a04cebaed8b141505cc26b5

也就是说,星系一,行星340.然后你可以随心所欲地拼接那段代码。使用哈希的好处是每个星球都应该有一个完全唯一的代码。

答案 6 :(得分:3)

我认为在“银河系”中确实没有那么多信息,你无法将它存储在今天的计算机上。让我们假设一个星系有100颗恒星,每颗恒星有10颗行星,每颗行星有3颗卫星。那是100颗恒星+ 1000颗行星+ 3000颗卫星你必须跟踪,这是4,100个物体。

以下是我们可能想要跟踪行星的事情。

质谱 X,Y,Z位置 一天的长度(在它自己的轴上旋转的时间) 一年的长度 人口 50种不同资源的资源量

假设每个值都需要一个double来存储它,并且我们有57个值要存储(让它向上舍入并说100),那么我们有100个值* 8个字节* 4100个body = 3,280,000个字节。现在,这是3兆的数据。这可能看起来很多,但实际上并没有那么多。而且,我不认为你真的想在一个星系中拥有这么多星星。游戏真的太大了,无法探索,并且可能会变得难以控制,以试图模拟在给定星系中发生的所有事情。

以这种方式看待它。如果您使用像SimCity这样的游戏,并将城市网格上的每个方块视为潜在的行星,然后您就会意识到可以将多少信息存储在一个小文件中,这样您就不必随意生成任何内容。

答案 7 :(得分:3)

每个太阳系的随机种子是一个可行的解决方案,但我感觉你在这里咆哮错误的树。

玩家能做些什么来改变那里的东西吗? (说,建立一些东西,挖掘可耗尽的资源等等?)如果是这样,你还是要保存状态。

玩家可以查看这个地方的样子而不必回到那里吗? (如果他不能,为什么不呢?!)你是要查找它还是要重建整个太阳系只是为了找到一条关于它的信息? (PRNG解决方案不允许您只获得太阳系的一部分,您必须完成所有工作。)

无论如何你需要保存多少细节?

答案 8 :(得分:2)

假设你从星系的种子开始,即1234,取这个种子,产生10000个随机数,每个数字代表一个星系。当你接近恒星时,你取星的随机数,然后它作为新随机函数的种子。为围绕恒星运行的天体数量生成一个随机数,并为每个物体生成一个数字(始终使用第二个随机函数),依此类推。 我不知道这是否对你有所帮助,但是你需要记住随机函数,内部是混乱的,对于初始条件,整个函数都会发生变化。

星系中恒星的种子必须产生相同的恒星,恒星的种子必须产生相同的恒星等。

您可以使用统计数据,密度计算,改善结果,使事情变得更有趣。始终检查函数是否会为同一输入产生相同的结果。

对不起,如果我的英语很糟糕,我来自阿根廷,英语不是我培养的品质之一:p

PD:我正在做同样类型的游戏;)

答案 9 :(得分:1)

我使用Mersenne Twister。 PRNG接受任何长度的种子数组 例如,我想在坐标x = 25,y = 72上生成星系。我用种子重新加捻[25,72] 如果我想在这个星系中产生1138个行星,我会使用[25,72,1138] 国家? [25,72,1138,10]
市? [25,72,1138,10,32]
等等。
使用这种方法,您可以使用一个数字(在x坐标之前,在25之前的情况下)之前生成数十亿数万亿个对象。
现在有一些项目使用它 Noctis:anynowhere.com/
Infiniverse:http://www.infiniverse-game.com/

答案 10 :(得分:0)

在数学上,您希望随机/伪随机生成未定向的连通图。在该图中,每个节点都是太阳系,每个边都是跳闸门。

1)创建N个节点并随机分配每个空间坐标。这些节点最终将成为您的太阳系。

2)使用Deluanay三角剖分算法生成边缘。我建议Deluanay三角测量,因为它会创建一个相当漂亮的地图,没有任何相互交叉的门,但你实际上可以使用你想要的任何算法。我真的不知道你在找什么。

3)如果您使用Deluanay三角测量,我建议您消除一定数量的边缘以创建“稀疏性”。这将使地图更有趣,因为某些地点将成为交通枢纽,而其他地方只是进站。

4)保存此图表。这是你的宇宙。不要错位或抛弃你的宇宙。可以根据需要有效地存储它,但不要删除任何信息。

5)为每个节点分配种子,并使用此种子生成每个太阳系。

6)恭喜,您现在拥有一个拥有任意数量的太阳系和跳闸的宇宙。

答案 11 :(得分:0)

我怀疑你要面对的最大问题是有一个命名系统,以一种对玩家一致和有意义的方式命名所有这些对象 - 尽管我们确实有naming real objects systematically.的方案我忘记了Elite的命名惯例在某一点之后崩溃了......

答案 12 :(得分:0)

这是我的第二个改进的解决方案。玩家将从随机生成的太阳系开始。每个系统连接到1到4个其他系统。将它们视为北,南,东和西系统。如果玩家要穿过北跳门,他将被带到一个系统,其种子比以前的系统多一个。如果他向南走,该系统的种子将少一个。东西两个分别为2+和2-。通过系统的种子和到达的方向计算到这些系统的距离(以秒差或光年或其他)。这样,星系的大小仅受用于保持种子的数量的最大值和最小值的限制。

进入其他星系的经线孔将与起动系统保持一定距离。下一个星系就像是这个星系的延续,因为种子数将以相同的方式递增,而银河系经孔另一端的系统将只是一个“东”或“北” “从起动系统连接。

顺便说一下,与上述解决方案不同,这种递增种子的使用导致了网络。此外,您可以看到此方法使用四边形,而上述解决方案使用六边形,这使得无法创建Web。

当然,所有这些都是基于这样的假设,即所有种子都会生成与任何其他序列不同的随机数字序列。这使得每个系统都是独一无二的。

答案 13 :(得分:0)

只要您使用相同的种子调用srandom(),您就可以从random()中获取相同的值。因此,只需将一个星系统中的所有内容从一个调用srandom()开始...然后,您只需要为整个星系统存储1个整数(种子)。那就是压缩!

答案 14 :(得分:0)

如果使用伪随机数生成器,则可以保证生成的每个随机数将以给定种子的相同顺序出现。 生成由给定数字播种的系统的代码每次生成时都会显示相同的内容。

使用伪随机数流中的第一个数字来生成“门”的数量。 遍历每个门,从数字流中获取一个值,为每个目标系统分配和播种。

根据种子生成每个系统的特征。

有几种已知的生成随机种子的算法。

Mersenne twister一个破解

答案 15 :(得分:0)

这是我想出的。 Dunno,如果它将是最终版本。

想象一个六边形网格,并在每个顶点,一个太阳系。因为,我们在六边形网格上,从任何顶点只有三条线。一个是水平的,另外两个是对角线。如果我们给起始种子赋值n,我们可以给出起始点水平连接的太阳系n + 1的值,其他的得到n + 2和n-2的值。

哦,废话。我们不一定得到网格。该死的。让我们再试一次。

答案 16 :(得分:0)

如果你真的想回到固定状态,我认为单一价值的程序生成是不正确的。

我们假设,每个平面中有一个256x256系统的固定网格,宇宙中有16个平面。每架飞机最多有512个交易站,最多8个链接到其他飞机。所有交易站和链接都处于固定位置。 您的初始种子值必须至少为2 ^ 76才能编码所有可能的Universe。 添加更多对象(行星,船只......),数量呈指数增长。

编辑: 如果您不允许在每个系统中使用多个交易站或链接,则会少一些。 我会使用一些永久存储,也许是像Firebird或sqlite这样的嵌入式数据库。顺便说一下,我正在开发这样的游戏。

答案 17 :(得分:0)

您可以从某个种子(“母亲号码”)构建一个伪随机数的 N 数字。然后,您将数字分成小组并用它们来回答您的问题。

示例: N = 20

- >一位数:多少额外的跳闸?
- >三位数:用于生成每个可用跳跃的相应长度的种子
- >六位数:用于产生太阳系的种子
- >十位数:用于为每个链接太阳系生成新的20位数种子的种子

然后递归。每个系统(具有稳定的轨道等)都会在时间0生成,您必须计算它的外观现在

当然,从母系统开始,这种方法意味着当前系统离母系统越远,生成数据所需的时间就越长。此外,这种方式使树,而不是网(我期望)。

我认为生成坐标会更好 - 在平面中使用极坐标,也许是三维椭球。

答案 18 :(得分:0)

我可以模糊地回忆起以前做过的事情。在90年代早期,分形很流行,我记得有一家公司向游戏程序员提供世界。它创造了一个完整的无限宇宙,充满了太阳和行星的星系,事件可以追溯到行星上的山谷和纹理。他们提议为游戏开发者寻找合适的虚拟房地产。游戏开发人员会得到软件来渲染和使用它,以及它在这个分形世界中的精确坐标。

我用Google搜索了“分形游戏世界行星宇宙”等几分钟,但还没有找到它们。可能是Pandromeda,但我不太记得。

你应该研究这个想法的分形。您所需要的只是一个连续的数字域,您可以从种子中重新创建,然后将这些数字显示为具有不同属性的恒星,行星和卫星。

相关问题