Procedural Generation: Programming The Universe

javidx9
24 Jan 202041:57

Summary

TLDR在这个视频中,我们跟随孤独的编码者一起探索如何通过程序生成一个宇宙。视频展示了如何使用伪随机数生成器来创建一个持续且一致的宇宙,其中包含了恒星、行星和卫星。通过控制随机性,我们可以在不需要存储整个宇宙的情况下,即时生成和互动。视频还讨论了随机数生成器的选择,以及如何通过设置种子来保持宇宙的一致性。最后,通过一个简单的星系类和一些用户输入处理,我们能够在屏幕上可视化这个宇宙,并与之互动。

Takeaways

  • 🌌 视频介绍了如何通过程序化生成技术创建一个虚拟宇宙。
  • 🎮 灵感来源于经典游戏《精英》系列,展示了如何在有限的内存中呈现一个广阔的宇宙。
  • 🔄 宇宙的生成是持久的,无论从哪个方向浏览,宇宙的星系都会保持一致。
  • 🧮 使用了伪随机数生成器来控制宇宙的生成过程,确保每次生成的结果都是一致的。
  • 📊 通过屏幕坐标作为随机数生成器的种子,实现了基于位置的随机数序列。
  • 🚀 视频讨论了随机数生成器的质量,以及如何通过数学方法控制随机性以创建有意义的资源。
  • 📚 介绍了C++标准库中的随机数生成器,以及如何使用它们来生成高质量的随机数。
  • 🔧 使用了Lemaire随机数生成器,因为它既快速又能够产生高质量的随机数。
  • 🌠 创建了一个星系类来表示宇宙中的星系,并在构造函数中完成所有生成工作。
  • 🪐 展示了如何通过随机数生成星系的属性,如星的大小、颜色、行星数量和特性。
  • 🖼️ 通过用户输入和鼠标位置,可以在宇宙中导航并选择特定的星系进行查看。
  • 🔄 视频强调了程序化生成的关键在于能够一致地生成随机数序列,从而实现宇宙的一致性和可预测性。

Q & A

  • 视频开头提到的Elite系列游戏是什么?

    -Elite系列游戏是一系列太空飞行模拟游戏,最早在1980年代推出,以其在内存有限的小型机器上呈现整个宇宙而著称。

  • 为什么视频作者决定创建一个模拟Elite Dangerous效果的小型应用程序?

    -视频作者决定创建这个应用程序是因为他被Elite Dangerous游戏中庞大的宇宙所吸引,该游戏的宇宙如此之大,以至于无法完全存储在计算机上。

  • 视频中提到的“程序生成”(procedural generation)是什么?

    -程序生成是一种技术,它使用一系列复杂的方程式根据输入参数(如鼠标坐标)动态生成内容,而不是预先存储所有内容。这允许在有限的内存中创建看似无限的宇宙。

  • 视频中提到的“伪随机数生成”(pseudo-random number generation)有什么特点?

    -伪随机数生成器不能真正生成随机数,但可以生成看似随机的数列。这些数列可以通过设置种子(seed)来重复生成,这对于保持程序生成内容的一致性至关重要。

  • 视频中为什么作者对“roguelikes”和“Minecraft”等游戏的随机内容生成持有异议?

    -作者认为这些游戏生成的随机内容实际上是预先存储并需要时召回的,这与他心中的程序生成定义不同。他更倾向于“自动生成”(automated generation),即根据需要即时生成资源和资产。

  • 视频中提到的“Lemé随机数生成器”(Lemé random number generator)有什么优势?

    -Lemé随机数生成器被认为是相当健壮且计算速度非常快的随机数生成算法,适合用于需要快速生成随机数的程序生成应用。

  • 视频中如何实现星系的程序生成?

    -视频通过创建一个星系类,使用Lemé随机数生成器根据星系在宇宙中的位置(X和Y坐标)作为种子来生成星系。这包括决定星系是否存在、大小、颜色以及围绕它的行星数量等属性。

  • 视频中如何处理用户在宇宙中的移动和探索?

    -视频通过创建一个“星系偏移量”(galaxy offset)向量来模拟用户的视角在宇宙中的位置。用户可以通过键盘输入(如W、A、S、D键)来移动这个偏移量,从而在宇宙中探索。

  • 视频最后提到的“改变宇宙状态”的问题是什么?

    -这个问题涉及到如何在程序生成的宇宙中实现持久性变化,例如玩家在Minecraft中改变方块状态。这在视频中没有详细解释,但作者提到这将是未来视频的主题。

Outlines

00:00

🌌 开始探索程序化生成的宇宙

视频介绍了一个孤独的编码者如何在新年开始时,通过一个简单的视频教程来程序化生成宇宙。他提到了对Elite系列游戏的喜爱,尤其是Elite Dangerous,这款游戏有一个庞大的宇宙,无法完全存储在计算机上。因此,他决定创建一个小应用程序来模拟这种效果。他展示了一个简单的宇宙,其中包含不同的星系,每个圆圈代表一个星星。他强调宇宙的持久性,并解释了如何通过鼠标移动来探索宇宙。

05:02

🎲 探索伪随机数生成的选项

视频继续讨论如何控制随机性,以创建一个有趣的宇宙。作者通过C++语言探索了可用的伪随机数生成选项,并决定通过可视化这些随机数来评估它们的质量。他提到了随机数生成器的两个重要特性:随机性和速度。通过在屏幕上绘制随机数,他展示了如何评估随机数生成器的质量。他还讨论了如何使用种子来确保随机数生成器的一致性。

10:03

🔄 利用Lemaire随机数生成器

作者介绍了Lemaire随机数生成器,这是一个快速且健壮的随机数生成算法。他解释了如何创建一个简单的实用函数来生成32位的Lemaire随机数,并讨论了如何使用这些随机数来构建宇宙。他强调了使用随机数生成器的一致性,以及如何通过设置阈值来模拟现实世界中的分布,例如树木的分布。

15:05

🌠 创建星系类和宇宙探索

视频展示了如何创建一个星系类来代表宇宙中的星系,并在构造函数中完成所有生成工作。作者解释了如何基于星系的位置生成种子,以及如何使用这个种子来确定星系是否存在。他还讨论了如何为星系生成大小、颜色和其他属性,并展示了如何在屏幕上绘制星系。

20:08

🚀 在宇宙中移动和交互

作者介绍了如何在宇宙中移动,通过处理用户输入来改变观察宇宙的位置。他展示了如何使用鼠标输入来选择星系,并在屏幕上显示星系的详细信息。他还讨论了如何生成星系中的行星和卫星,并展示了如何在屏幕上绘制这些天体。

25:09

🌍 完善星系的生成和可视化

视频最后,作者展示了如何完善星系的生成过程,包括行星的属性和卫星的生成。他强调了随机数生成器在保持宇宙一致性方面的重要性,并讨论了如何通过随机数来模拟现实世界中的分布。他还展示了如何通过鼠标点击来选择星系,并在屏幕上显示星系的详细信息。

Mindmap

Keywords

💡程序生成

程序生成(Procedural Generation)是一种在游戏和模拟中创建内容的技术,它通过算法和数学模型动态生成游戏世界或宇宙。在视频中,程序生成用于创建一个庞大的宇宙,其中包含恒星、行星和卫星等元素。这种方法使得宇宙的内容不是预先存储的,而是根据需要即时生成,从而节省了大量存储空间。

💡Elite系列游戏

Elite系列游戏是一系列太空模拟游戏,以其开放世界和复杂的交易系统而闻名。视频中提到,Elite Dangerous是该系列的最新作品,它拥有一个庞大的宇宙,但并非所有内容都存储在玩家的计算机上,而是通过程序生成技术实现。

💡伪随机数

伪随机数(Pseudorandom Number)是由计算机算法生成的一系列数字,它们看起来像是随机的,但实际上是由确定性的算法产生的。在程序生成中,伪随机数用于模拟真实世界的随机性,以创造出多样化和不可预测的内容。

💡梅森旋转器

梅森旋转器(Mersenne Twister)是一种广泛使用的伪随机数生成器,以其高质量和速度而著称。它能够产生高质量的随机数序列,适用于需要随机性的复杂应用。

💡Lemire随机数生成器

Lemire随机数生成器是一种快速且相对健壮的伪随机数生成算法,它通过简单的数学运算来产生随机数。Lemire算法在性能和随机性之间取得了良好的平衡,适合于需要快速随机数生成的应用。

💡宇宙

在视频中,宇宙指的是程序生成的虚拟空间,包含了无数的恒星、行星和卫星。这个宇宙是持久的,意味着无论何时访问,相同的位置都会生成相同的星系。

💡星系

星系是由恒星、行星和其他天体组成的天文系统。在视频中,每个星系都是通过程序生成技术创建的,具有独特的特征,如大小、颜色和行星数量。

💡内存消耗

内存消耗(Memory Consumption)指的是程序运行时占用的内存空间。在视频中,尽管宇宙非常庞大,但由于采用了程序生成技术,实际的内存消耗非常小。

💡随机性控制

随机性控制(Control of Randomness)是指在程序生成过程中,如何管理和操纵随机性以产生有意义的结果。这通常涉及到设置随机数生成器的种子,以及如何根据随机数的结果做出决策。

💡交互性

交互性(Interactivity)是指用户与程序或系统之间的互动能力。在视频中,用户可以通过鼠标移动和点击来探索宇宙,程序会根据用户的操作动态生成相应的内容。

Highlights

介绍了如何通过程序生成一个宇宙,灵感来源于Elite系列游戏。

展示了一个简单的宇宙视图,其中每个圆圈代表一个恒星系统。

强调了宇宙的持久性,即无论何时查看,宇宙的状态都是一致的。

讨论了如何在有限的内存中存储和访问庞大的宇宙数据。

提出了程序生成(procedural generation)的概念,并与随机内容生成进行了区分。

解释了伪随机数生成器的重要性以及如何控制随机性。

展示了如何使用C++语言中的随机数生成选项。

通过可视化方法评估随机数生成器的质量。

讨论了Mersenne Twister算法的优缺点。

介绍了Lemaire随机数生成器,它既快速又健壮。

解释了如何使用空间位置作为随机数生成器的种子。

展示了如何通过随机数生成器来决定恒星系统的存在和特性。

讨论了如何通过随机数生成器来控制星系的详细程度。

展示了如何通过用户输入来探索宇宙,并实时生成星系。

介绍了如何通过鼠标位置来选择和显示星系的详细信息。

讨论了如何在程序生成的宇宙中实现交互性。

展示了如何为星系添加行星和卫星,并为它们生成不同的属性。

强调了程序生成宇宙的一致性和可重复性。

提出了关于如何在程序生成的宇宙中改变状态的问题,这将作为未来视频的主题。

Transcripts

play00:00

hello it's a new year for one lone coder

play00:02

so let's have a nice simple video to get

play00:04

started let's procedurally generate the

play00:07

universe now to those of you that

play00:09

frequent the discord server you will

play00:11

know that I'm a big fan of the elite

play00:13

series of games going way back to the

play00:15

early 80s where the elite games

play00:17

presented an entire universe on a very

play00:20

small machine ie machine with not very

play00:22

much memory and over the Christmas

play00:24

period I've been playing elite dangerous

play00:26

and loving every minute of it and it has

play00:28

a vast universe in fact it has a

play00:30

universe so large it can't all possibly

play00:32

be stored on the computer and so I've

play00:35

decided to create a small application

play00:37

here which tries to emulate that effect

play00:39

and as you can see I'm panning around

play00:40

well a very simplistic looking universe

play00:43

of different star systems so each of

play00:45

these circles represents a star the

play00:48

first thing to note is that the universe

play00:49

is actually persistence if I scroll this

play00:51

way it will look the same as I scroll

play00:53

this way admittedly it's easy to get

play00:55

lost in my universe because I've not put

play00:57

any coordinates on the screen I shall

play00:59

add that to the to-do list but please

play01:00

don't misunderstand this universe is

play01:02

vast it's huge it will go on for

play01:05

billions and billions of stars and they

play01:08

will all exist in exactly the same place

play01:10

as I move the mouse cursor around I can

play01:12

highlight specific stars so let's click

play01:15

on this one so we can click on this one

play01:16

when we see around the stars that

play01:18

several planets and the planets have

play01:20

several moons let's try a different one

play01:24

let's try a few so some don't have any

play01:27

but they all have something different

play01:29

and again these are persistent so I

play01:32

could go to one side of the universe and

play01:34

come back these will still be here we

play01:36

can test this let's try and find some

play01:38

features I can recognize so here we've

play01:39

got a small cluster of planets let's

play01:41

pick that one in the middle and I'm

play01:43

going to pan all the way this way for a

play01:45

few seconds and then I'm going to pan

play01:47

all the way back and try and find that

play01:49

cluster there it is

play01:51

and click on the same one we see we get

play01:53

the same results and it doesn't matter

play01:55

how big this universe is there's no

play01:57

search time required it will always

play01:59

generate the same persistent star

play02:02

systems for a given star the size of

play02:06

this universe is limited only by the

play02:08

precision of the integer types I'm using

play02:10

to store the position of the mouse

play02:12

ordinate it is vast and yet can be

play02:15

rendered and interacted with in no time

play02:19

at all you can also see on the

play02:21

right-hand side of the screen here that

play02:23

the universe consumes very little memory

play02:26

as I'm moving around we're not

play02:27

generating more and more planets and

play02:30

stars and so there's no more memory

play02:31

created and nothing is cashed out to

play02:34

disk that would be far too slow and

play02:35

you'll just have to take my word for it

play02:37

but the size of the executable on disk

play02:40

is about 30 kilobytes so how do we store

play02:44

an entire persistent universe and access

play02:48

it so quickly on my computer well

play02:52

hopefully it's obvious that we can't

play02:53

store the entire universe on my computer

play02:55

instead we're going to use an elaborate

play02:58

series of equations to generate the

play03:00

universe as we knew it and we'll use our

play03:02

mouse coordinates x and y as the input

play03:05

parameters to this equation this

play03:07

technique is called procedural

play03:09

generation we see it quite a lot in

play03:12

games like minecraft or roguelikes now

play03:15

I'm going to take a little bit of an

play03:16

issue with that and I'm expecting some

play03:18

debate in the comments about this I

play03:19

think games like roguelikes

play03:21

net hacks and minecraft and all of those

play03:24

games that generate random content I

play03:26

don't necessarily consider those to be

play03:28

procedural generation I think about

play03:30

moore's automated generation because in

play03:33

take minecraft for example it generates

play03:35

the world in these chunks and what it

play03:38

generated them they mean to be stored

play03:40

they need to be fixed somewhere and

play03:42

recalled when they're required in my

play03:44

mind procedural generation is something

play03:46

a bit different it is generating the

play03:48

resources as a required on-the-fly and

play03:51

consistently each time I don't think

play03:53

either term is incorrect but in my mind

play03:56

it makes sense to make a distinction

play03:57

between the two that games that

play03:59

automatically generate resources and

play04:01

assets are not quite the same as games

play04:04

that procedurally generate resources and

play04:06

assets at the heart of all procedurally

play04:09

generated applications lies randomness

play04:12

or in the case of a computer pseudo

play04:14

randomness because we can't

play04:15

realistically generate true random

play04:17

numbers but randomness on its own is not

play04:20

enough to create compelling resources we

play04:23

need to control that randomness

play04:25

in such a way that makes our application

play04:27

sensible and in this video I hope to

play04:30

show just that so let's get started as

play04:35

usual I'm going to start with a skeleton

play04:37

pixel game engine project so it's got

play04:39

nothing in the on user-created on user

play04:41

update functions and I'm constructing

play04:43

the pixel game engine to be 512 by 480

play04:46

and each game pixel is 2 by 2 screen

play04:50

pixels now I've also moved over to

play04:52

Visual Studio 2019 and I'm still

play04:54

learning what it's going to be doing

play04:56

with tooltips and things popping up all

play04:57

over the video so I apologize if they

play04:59

get in the way

play05:01

fundamentally procedural generation is

play05:04

about controlling randomness and so I

play05:06

think it's worth spending a few minutes

play05:07

just exploring the available options of

play05:10

pseudo random number generation that are

play05:12

available to us via the C++ language and

play05:15

rather than just look at the statistics

play05:17

of the generated numbers I'm going to

play05:19

visualize them instead and I'm going to

play05:21

do that whenever the space key is

play05:23

pressed if you've seen my videos before

play05:24

and we've looked at things like noisy

play05:26

images on the screen it's always caused

play05:28

the YouTube algorithm to completely

play05:30

collapse when it's displaying the video

play05:32

so by making it sensitive to the space

play05:34

bar being released

play05:35

I should hopefully be able to retain the

play05:38

integrity of the image which is going to

play05:40

be necessary to understand whether a

play05:42

random number generator is good for us

play05:44

or not there are two qualities of the

play05:46

random number generator I want to look

play05:48

at the first is how good is the

play05:51

randomness and the second is how fast

play05:53

can it generate the random number so I'm

play05:56

putting in too little time points so I

play05:58

can measure the duration of the

play06:00

generation I'm going to draw that to the

play06:02

top left of the screen using the pixel

play06:04

game engine to draw string function my

play06:07

intention here is to go through every

play06:09

pixel on the screen and for each pixel

play06:13

we're going to draw a random number and

play06:15

depending upon value of that random

play06:17

number I'm going to set a flag B is star

play06:20

to true or false and I'll just simply

play06:23

for now use a single pixel as the star

play06:25

it's either white or black and the only

play06:28

reason I'm drawing the black stars even

play06:31

though I've previously cleared the

play06:32

screen appear to all black is to just

play06:35

make sure that the timing is consistent

play06:37

for example if the random number

play06:38

generator generated a few white stars

play06:41

it's going to give the appearance that

play06:42

it's performing better so I need to make

play06:44

sure that the drawing of the star is not

play06:46

factoring into the timing of the

play06:48

randomness functions so let's start with

play06:51

the random function everybody knows Rand

play06:55

and everybody also knows well at least

play06:57

have been told that round is not a very

play06:59

good random number generator well let's

play07:02

take a look so I'm going to draw a

play07:04

random number between 0 and 255

play07:07

inclusive and I'm going to check is that

play07:09

value less than 32 so in principle were

play07:11

looking at 1/8 of the screen being stars

play07:15

or white in this case let's run the

play07:18

application now to get any stars to

play07:21

appear I need to press the spacebar so

play07:23

there we go

play07:24

and on average this told us to generate

play07:26

this field of stars took about 6

play07:28

milliseconds and the randomness doesn't

play07:31

look too bad

play07:32

at first glance anyway I'll keep

play07:36

pressing space I can regenerate more and

play07:38

more stars and the time to do so is well

play07:43

it's roughly always the same

play07:44

a handful of milliseconds the problem is

play07:47

I want to control the randomness it's no

play07:49

good to me to just have genuine

play07:51

randomness here I need some way of

play07:53

shaping that randomness into a universe

play07:55

if I always wanted to generate the same

play07:58

universe each time I would need to seed

play08:00

the random number generator with some

play08:03

sort of key I'm going to pick a value at

play08:05

random here a thousand so now when I run

play08:10

the application even though I'm pressing

play08:17

the spacebar and we can see it's

play08:18

generating it the universe is the same

play08:21

each time so knowing that we can set the

play08:23

seed of a pseudo-random number generator

play08:25

is going to be really important for

play08:27

maintaining persistence across the

play08:29

assets were procedurally generating but

play08:32

there's a problem here in order to know

play08:36

whether a pixel is black or white I need

play08:39

to have generated them in this specific

play08:41

sequence from the top left all the way

play08:44

to wherever my cursor is so yes I can

play08:47

always check what color the pixel is

play08:49

under the cursor but if I wanted to

play08:51

derive that based on our

play08:52

under Miss equations how do I do it

play08:55

right now I have to start at the top

play08:57

left and generate the sequence precisely

play08:59

because of the set seed all the way

play09:02

until the point that I need it this

play09:04

could be very slow particularly if I've

play09:06

got an entire universe to procedurally

play09:08

generate I would have to generate the

play09:10

universe up until the point that it is

play09:12

under my mouse cursor and this is

play09:15

exactly what I'm not trying to do I

play09:18

don't want to have to generate the

play09:20

universe in advance and storage

play09:21

somewhere in order to interrogate it or

play09:24

assess various components of it what if

play09:27

instead we used a seed that was based on

play09:30

the spatial location within the universe

play09:32

so instead of setting the seed once at

play09:35

the start I'm going to set it for every

play09:37

single star that we generate but there's

play09:40

no point in me using a fixed number all

play09:41

the time because then the entire

play09:43

universe would be the same instead I'm

play09:45

going to take the x and y position of

play09:47

the screen and sort of squash that

play09:50

together into a seed value and use that

play09:53

as my seed

play09:55

this approach guarantees that the seed

play09:58

is different for every pixel on the

play10:00

screen yet in regardless of the location

play10:02

it should consistently generate the same

play10:05

sequence of random numbers for that

play10:07

location let's take a look it's best to

play10:14

spacebar hmm well it's certainly

play10:18

generating numbers and it's plotting

play10:21

stars and it's taking a little bit more

play10:22

time now that we're setting the seed but

play10:25

something tells me that's not quite

play10:28

random perhaps I'm just getting very

play10:31

very unlucky with the distribution so

play10:33

let's change that to a 50-50

play10:35

distribution well that's not changed

play10:41

very much and in fact this highlights

play10:43

the limitations of using R and given

play10:46

that we're choosing to plot a pixel as

play10:47

white or black based on the first random

play10:50

number generated after setting a seed

play10:52

these patterns suggest that the random

play10:55

number is highly correlated to the seed

play10:58

therefore its burly random at all in

play11:01

fact it's utterly predictable in this

play11:03

instance

play11:04

surrend is rubbish we're going to need

play11:07

something better than round modern C++

play11:10

actually provides a good random library

play11:13

as part of its standard library

play11:15

generating high-quality and robust

play11:18

random numbers is well beyond the scope

play11:20

of this video and it's a complete

play11:22

computer science and mathematics field

play11:24

in its own right there's a lot of

play11:26

research and dedicated effort going into

play11:28

generating high-quality random numbers

play11:30

simply because they'll underpin all of

play11:33

our digital communications and

play11:34

cryptography services and as I've just

play11:37

demonstrated even though we've used Rand

play11:39

plenty of times in previous videos it's

play11:41

great for little bits of randomness in

play11:43

games if you are really relying on its

play11:45

integrity to generate random numbers it

play11:48

could probably very easily be hacked

play11:50

I think generating random numbers on

play11:53

computers is a fascinating topic I don't

play11:55

know if it will ever be solved until we

play11:57

get dedicated hardware which can somehow

play11:59

exploit the environment in order to

play12:02

generate some random numbers but until

play12:04

then we've got what we've got in good

play12:07

old modern C++ fashioned using the

play12:10

random library is a little bit wordy

play12:11

first we have to choose some sort of

play12:13

random device this is meant to be the

play12:16

seed that will be generated randomly

play12:18

from my machine then we need to choose

play12:20

what kind of random number generation

play12:22

engine do we want to use and in this

play12:25

case I'm going for the mesentery stirrer

play12:27

it's reasonably accepted as being one of

play12:30

the most robust random number generators

play12:32

out there at least a lot of research has

play12:34

gone into it I can't just draw a random

play12:36

number like before I need to specify a

play12:38

distribution and in this case I'm

play12:40

transferring a uniform distribution so

play12:42

all numbers should have an even

play12:43

probability of being drawn so this time

play12:46

let's include the standard random part

play12:48

and just as we did before we'll do the

play12:50

same test I'm going to draw a random

play12:52

number between 0 and 255 inclusive and

play12:55

plot the pixel you'll note that I've not

play12:57

included this set up within my time

play13:00

period ideally you'd only need to do

play13:02

this once one final thing just because I

play13:04

forgot where we need some parentheses

play13:06

after the Rd and the construction of the

play13:09

Mersenne twister object so let's take a

play13:11

look so as before I'm going to press the

play13:14

spacebar and well it looks pretty much

play13:16

the same if

play13:17

thing I would say it's a little more

play13:19

evenly distributed than it was using

play13:22

Graham not seeing quite as many clusters

play13:25

or line artifacts you might just be my

play13:28

eyes playing tricks on me but it does

play13:30

seem to look better and it's taking

play13:32

approximately the same time about 3.8

play13:35

milliseconds for milliseconds there

play13:37

generate a few more so that's fine but

play13:40

again we've got this problem of we've

play13:42

just set the seed once for the entire

play13:44

universe now we need to set it per star

play13:46

well using the same seed generator as

play13:49

before I'm just going to see the missing

play13:51

twister and let's try that space and Wow

play13:59

oh dear I mean it looks great it's

play14:01

perfect what we want but it's taking

play14:03

about 400 milliseconds 395 400

play14:08

milliseconds to generate the screen it

play14:10

looks like seeding the Mersenne twister

play14:12

algorithm is quite slow and probably far

play14:15

too slow for our needs however it has

play14:17

generated a very nice random universe so

play14:21

I could place my mouse cursor anywhere

play14:23

in this scene and converting its

play14:26

coordinates to use as a seed for the

play14:28

random number generator will tell me

play14:30

whether the star exists or not is the

play14:32

pixel white or black and so the quality

play14:35

of the random number is brilliant here

play14:38

in this case but the performance of it

play14:39

sucks we need something that's a good in

play14:42

between so C++ random library Mersenne

play14:45

twister you're out it takes far smarter

play14:49

people and more dedicated people than me

play14:51

to generate a high-quality random number

play14:53

generator so I would suggest to go on

play14:56

finding one and one that's been around

play14:57

for quite some time is the lemma or

play15:00

lemma random number generator I was

play15:02

using this back in the early 2000s as

play15:05

part of a research project I was doing

play15:07

for the University this was before the

play15:09

introduction of the random library where

play15:11

you had easy access to algorithms such

play15:13

as Mersenne twister this algorithm is

play15:16

known as being reasonably robust but the

play15:19

beauty of it and what's going to appeal

play15:20

to us is that it's actually very very

play15:23

quick we're going to need to create a

play15:25

little utility function to generate

play15:27

these lemo random numbers now if it's

play15:29

not pronounced lamb

play15:30

then I apologize to dr. lemma so I'm

play15:33

going to create a small function called

play15:34

lemma 32 because it's going to generate

play15:37

32-bit numbers most of the algorithms

play15:40

shown for this generate 64-bit numbers

play15:43

and by converting it to 32-bit I've

play15:45

probably completely compromised its

play15:46

integrity as a robust random number

play15:48

generator I'm aware of that

play15:50

it works by maintaining a state variable

play15:53

and each time we draw a random number

play15:55

we're going to change that state in fact

play15:57

that state isn't a random number and

play15:59

even though this will look like

play16:01

gobbledygook that's all there is to it

play16:03

and we can see computationally there's

play16:05

not a great deal going on here we've got

play16:07

some additions where we've got an

play16:09

integer multiplication but then all

play16:11

we've got are shifts and zorse these are

play16:13

all very cheap computational

play16:15

instructions to use and the maths behind

play16:18

this is mostly beyond me but I'm on the

play16:20

understanding that these are some type

play16:22

of specialist prime number and by xoring

play16:24

with these prime numbers and shifting

play16:26

the register we can change the state of

play16:29

our lemma variable in many ways this is

play16:31

very similar to a linear feedback shift

play16:33

register so let's just get stuck in and

play16:36

use it straight away instead of looking

play16:39

at the whole screen this time we're

play16:40

going to look that's just setting the

play16:42

seed value directly to be the lemma

play16:44

States and that's sort of priming the

play16:46

shift register and as we have done

play16:48

exactly before I'm going to draw a

play16:50

random number between 0 and 255

play16:52

inclusive so let's take a look first

play17:00

space and what we see now is a

play17:03

persistent universe being generated per

play17:06

pixel on the screen with the same

play17:09

performance as Rand and so this is

play17:12

perfect for what we need

play17:14

procedural generation is fundamentally

play17:17

harnessing the properties of probability

play17:18

to generate interesting things so let's

play17:22

just take a very simple one-dimensional

play17:24

example assume I've got a plane of land

play17:28

and I wanted to populate this land with

play17:31

trees in the universe example we're

play17:33

using the location in space as the seed

play17:36

for a random number generator so I'm

play17:38

going to do the same sort of thing here

play17:39

and I'm breaking space up into discrete

play17:42

zones

play17:43

for each zone I'm effectively rolling a

play17:46

die and making a decision based on the

play17:49

output so i can assume with my die

play17:52

example that's a tree exists if my

play17:55

random number is less than 2 in this

play17:58

case there's a 33% chance of a tree

play18:01

existing so we might see one here and

play18:04

one here and one here

play18:06

etc etc if I made this threshold larger

play18:09

let's say if it's less than or equal to

play18:12

5 so there's only a 1 in 6 chance of it

play18:14

not being a tree we would certainly

play18:16

expect to see a lot more trees in each

play18:19

section to the point where they're all

play18:21

uniformly distributed across the land in

play18:24

order to bias procedural generation to

play18:26

give us plausible results we can't just

play18:30

rely on the probability and harsh

play18:32

thresholds alone in this tree example we

play18:35

may see that if we did have the

play18:37

probability of it being a tree set too

play18:39

high all of our trees would be uniformly

play18:41

spaced it wouldn't look particularly

play18:43

realistic perhaps we want clumps of

play18:46

trees to exist instead well this is just

play18:49

a case of biasing our threshold values

play18:52

on some of the parameters perhaps the

play18:55

threshold value could be based on

play18:57

location so as the location number

play19:01

increases it's going across the screen

play19:03

the probability of it being a tree also

play19:06

increases at which point it's unlikely

play19:08

we'd see a tree here at the start but as

play19:10

we're moving along the screen we may

play19:12

start to see them and we'll start to see

play19:15

them with more frequency so you could

play19:17

use this approach to have sort of a

play19:19

boundary going into a forest for example

play19:21

we can also use lots of other

play19:24

interesting functions to access this

play19:26

threshold perhaps we wanted a clump of

play19:28

trees to appear somewhere in the middle

play19:30

of this land well if we used a threshold

play19:32

value that was biased by some of the

play19:35

function for example a Gaussian curve

play19:38

then in this region it's far more likely

play19:41

we'll see trees than in these extreme

play19:45

regions the beauty of this approach is

play19:47

that our random number has never changed

play19:50

but our understanding of how we want to

play19:52

construct the world as forces to think

play19:55

about how to manipulate there is

play19:57

of that drawn random number and this is

play20:00

really down to us as engineers to devise

play20:02

an appropriate solution set of rules to

play20:05

construct compelling worlds and I'm not

play20:08

arguing that that in itself is easy it's

play20:10

far from it depending on the level of

play20:12

detail you want to go to but

play20:15

fundamentally the random component is at

play20:18

least guaranteed to be consistent and so

play20:21

irrespective of how complicated your

play20:24

generation routine is it will always be

play20:27

the same each time so given that we know

play20:31

we're going to get the exact same

play20:33

sequence for a given seed and that

play20:35

sequence is going to be random I'm going

play20:38

to construct my universe by first

play20:40

checking for that location does a star

play20:44

exist and so that becomes my first

play20:47

random number draw I'm going to draw a

play20:50

maximum up to 20 and I'm going to test

play20:52

is that equal to 1 that will tell me

play20:55

does a star exist so one in every 20

play20:57

locations will contain a star now it's

play21:00

important I don't reset the seat because

play21:03

I want the sequence of random numbers

play21:05

that are generated to be the same every

play21:07

single time so the seed has been set

play21:10

once and we've generated does a star

play21:12

exist if it does then I'm going to

play21:14

determine the size of the star and again

play21:17

that's going to be some random number

play21:19

generated in this case between 10 and 40

play21:23

these units are meaningless and they

play21:25

will need to be chosen to suit the

play21:27

application that you're trying to

play21:28

procedurally generate then I'm going to

play21:30

draw another random number for the color

play21:32

of the star and I've got eight possible

play21:35

colors to choose from and then I want to

play21:37

generate how many planets surround the

play21:40

star and then for each planet in order I

play21:42

want to determine some properties of the

play21:45

planet

play21:46

what is its size what is its temperature

play21:49

what is its makeup a what percentage is

play21:53

perhaps covered in foliage what

play21:56

percentage is covered in water how much

play21:58

of it is minerals you can make up all

play22:01

sorts of different parameters

play22:02

what is its population each time we

play22:06

start to create a statistic we always

play22:09

draw some random

play22:10

number from our pseudo random number

play22:13

sequence the sequence is always going to

play22:15

be the same each time that's the real

play22:17

take-home message and what the

play22:19

interesting thing is we can start to not

play22:21

only just use the sequence but we can

play22:23

use the values of parameters we've

play22:25

already chosen so let's say we are also

play22:28

maintaining the distance away from the

play22:30

star or we could use that distance

play22:32

function as part of the temperature

play22:34

calculations we can use the temperature

play22:37

calculations to tell us is it likely

play22:39

there's going to be water on the surface

play22:41

and if there's no water on the surface

play22:43

what's the probability of there being

play22:45

foliage so this is really up to the

play22:47

designer now to start thinking how are

play22:49

all of these things connected but the

play22:52

beauty of this is it's generated when

play22:54

it's needed each time because even

play22:57

though randomness is involved in the

play22:59

definition of the planets and the stars

play23:01

and the system's the randomness is under

play23:04

our control and it's guaranteed to be

play23:06

consistent but the key principle here is

play23:09

we have to generate these random numbers

play23:11

in the same order each time now we've

play23:14

explored the randomness I'm going to

play23:16

remove this code from the application

play23:18

and I'm going to add to the application

play23:21

a new class which represents a star

play23:23

system and the constructor of this class

play23:26

is going to be the thing that does all

play23:28

of the work so a ladder constructor

play23:31

which takes in an x and y coordinate

play23:33

which is the location of this star

play23:35

system in the universe I'm going to take

play23:38

our little random number generator from

play23:40

before and move that over to the class

play23:45

we'll keep those private the first thing

play23:49

this star system needs to do is generate

play23:51

its seed based on its location which as

play23:54

we've just seen before is merging

play23:56

together the X and y coordinates now I'm

play23:59

using a 32-bit system here but I'm only

play24:02

looking at the least-significant 16 bits

play24:04

of the X&Y coordinate that will of

play24:06

course put some boundaries on the

play24:08

universe they will only have a 16-bit

play24:11

the coordinate resolution in each axes

play24:14

so it's not going on forever and

play24:16

hopefully when it does get to one end of

play24:18

the universe it should just wrap round

play24:20

to the other quite nicely of course if

play24:23

we needed larger you

play24:24

versus we would use more bits as we

play24:27

start to procedurally generate the star

play24:29

system we're going to need to store some

play24:32

of its states so here I've added a

play24:34

boolean for whether it exists something

play24:36

that represents the size of the star and

play24:38

the stars color and I'll draw the Stars

play24:40

color from an array of colors which I've

play24:43

defined as a constant expression at the

play24:45

start of the program so these are alpha

play24:48

blue green red in hex I don't always

play24:53

want to draw random numbers of the type

play24:55

unsigned integer 32 now instead I'd

play24:58

rather work with doubles and regular in

play25:00

SATs a bit more convenient and also I

play25:01

want to work with numbers that are

play25:03

within boundaries that are sensible for

play25:05

the things I'm trying to define so I

play25:07

want to create some utility functions

play25:09

where I supply a minimum and a maximum

play25:10

each time so this one will generate a

play25:13

random integer between this minimum and

play25:15

that maximum and this function will

play25:18

return a random double with the same

play25:20

constraints note that they both call the

play25:23

lemma 32 function so going back to our

play25:25

constructor we can start to generate

play25:27

this system firstly does it exist and

play25:31

that's quite important and quite an odd

play25:33

concept because you might think well of

play25:35

course the system must exist we're

play25:37

constructing a class that represents

play25:39

that system well that's not quite true

play25:41

we're actually creating a definition of

play25:43

what exists at that location within the

play25:46

universe so our boolean star exists will

play25:49

be set to true one in 20 times on

play25:52

average if the star doesn't exist I'm

play25:55

just going to abort the construction

play25:57

there's literally no point in doing

play25:58

anything else so very cheaply we have

play26:01

set the seed determined whether the star

play26:03

exists or not and if it does then we go

play26:06

on to create more interesting features

play26:07

if it doesn't then who cares assuming

play26:10

the star does exist then I'm going to

play26:12

generate something that represents its

play26:14

diameter and choose its color from the

play26:16

array above instead of working with the

play26:19

screen in a per pixel basis I'm going to

play26:23

break the screen into sectors which is

play26:25

easily done by taking any location on

play26:28

the screen and integer dividing it by

play26:30

the dimensions of our sector which I'm

play26:32

going to set to 16 by 16 pixels this

play26:35

allows me to then take

play26:37

the size of the star that we've just

play26:40

generated and in some cases we'll have

play26:41

small stars and in some cases we'll have

play26:43

big stars and then we'll have some

play26:45

medium stars but it gives me space to

play26:47

plot them in this little simple

play26:49

demonstration I'm just going to draw a

play26:51

circle of the appropriate color but you

play26:53

could of course

play26:54

procedurally generate images you could

play26:56

create animated graphics the

play26:58

possibilities are literally limitless it

play27:01

just depends how much effort you are

play27:02

prepared to put into generating the

play27:04

detail required for your application in

play27:07

the on user update function I'm going to

play27:09

start drawing our world so now we will

play27:12

clear the screen to black and I'll

play27:14

create two variables and set as X and n

play27:16

sectors Y which tells us how many

play27:18

sectors we've got across and down the

play27:20

screen because you might choose a

play27:22

different resolution and sector size

play27:24

this year I'm going to get into the

play27:26

habit of using the built in vector types

play27:28

in the pixel game engine so here I'm

play27:30

creating a two-dimensional integer

play27:32

vector called screen setter which is

play27:35

going to hold the coordinate of a

play27:37

particular sector on the screen I want

play27:39

to iterate through all of the sectors

play27:42

that are visible on the screen to have

play27:45

two nested for-loops

play27:46

that are just scanning through all of

play27:48

the X&Y coordinates and because our

play27:50

sectors are quite large there aren't

play27:51

that many sectors to process for a given

play27:54

sector location we need to determine

play27:56

what is the star system in that sector

play27:59

so I'll construct a star system object

play28:01

but I'll need to pass in the location

play28:11

which will be used to seed the Lema

play28:14

generator later on at this point I'm

play28:17

only interested if the star actually

play28:20

exists now that will have been set by

play28:22

the procedural generation routine in the

play28:24

constructor of C star system and as

play28:27

you'll see with the rest of this video

play28:28

I'm really just going to hack in the

play28:30

graphics appropriately so here I'm going

play28:32

to draw a circle in the middle of our

play28:34

sector and I've got some hard-coded

play28:35

numbers in here I know I shouldn't but

play28:37

the point of this video is not about the

play28:39

visualization it's about the generation

play28:41

so this will just draw a fill circle

play28:43

based upon the size of the star which

play28:46

already we now know because we have a

play28:48

star system object and

play28:50

the color so let's just take a quick

play28:51

look that's very nice we can see we've

play28:56

got a variety of different size stars

play28:58

not every single sector is populated

play29:01

with a snap and the stars are different

play29:04

colors but right now our universe is

play29:06

very very small because we can't move

play29:08

around in it if we want to move around

play29:11

the universe we need to know where we

play29:13

are within the universe so I'm going to

play29:15

create a 2d vector called galaxy offset

play29:18

this effectively represents the camera

play29:21

location inside our universe and in on

play29:24

user update before we draw anything

play29:27

we're going to handle some user input

play29:29

I'm going to be sensitive to the WUSA

play29:33

and D Keys being pressed to change the

play29:35

value of our galaxy offset vector bias

play29:38

fixed constant speed don't forget in the

play29:41

pixel game engine if we want movement we

play29:43

need to modulate by F elapsed time to

play29:45

make the movement smooth because the

play29:47

frame rate will vary depending on the

play29:49

load of your computer but you want it to

play29:51

move at a consistent visible rate we've

play29:54

done that many times before this galaxy

play29:57

offset vector effectively represents the

play29:59

top left of the screen and are nested

play30:02

for-loops going through all of the

play30:03

visible set is on the screen should be

play30:05

added to that offset to give us the real

play30:09

location in space so to our screen

play30:12

sector variables I'm going to add in our

play30:15

galaxy offset there's x and y now we

play30:23

should be able to move around the

play30:24

universe smoothly so if I move this way

play30:29

and we can see the stars are consistent

play30:31

going back it's actually it's a bit of a

play30:34

bold statement for me to say we can see

play30:35

the stars are consistent because none of

play30:38

us have memories that are that good

play30:40

let's just test the theory so here I've

play30:43

got a big cluster of planets hopefully

play30:45

that should be recognizable in the

play30:47

future let's mentally clock that one in

play30:48

and I'm going to scroll down for quite a

play30:51

while

play30:56

there we go and I'm going to scroll back

play30:59

up and hopefully we should find that

play31:02

cluster of planets again maybe that will

play31:04

demonstrate that it's consistent there

play31:07

it is

play31:07

now we've not stored that anywhere we've

play31:10

generated that cluster dynamically

play31:13

on-demand when we need it but because

play31:15

we've got complete control of our

play31:17

sequence of random numbers it is the

play31:19

same as having generated it previously

play31:22

and stored it because we don't actually

play31:24

care about the numeric value of our

play31:26

seeds the fact that our galaxy offset

play31:28

vector is going negative and positive

play31:30

depending on where we are in the

play31:32

universe doesn't matter it will always

play31:34

generate the same sequence of random

play31:36

numbers now that we've got this vast

play31:39

universe it would be useful to be able

play31:40

to interact with it sensibly we've got

play31:43

billions of planets we don't want to

play31:45

have to search through all of the

play31:47

planets to find which one have we

play31:48

selected what's its location and of

play31:50

course now we don't need to we know

play31:52

where our mouse cursor is going to be

play31:54

within the universe's space so we can

play31:56

just interrogate that sector location

play31:58

and get all of the information

play31:59

procedurally generated immediately for

play32:02

us to use as we see fit so I'm going to

play32:05

add in some mouse user input to going to

play32:08

get the screen space mount's coordinate

play32:10

and divide it by our number of sectors

play32:12

so again now we know which sector across

play32:15

the screen our mouse is in but because

play32:17

we can offset the galaxy we also need to

play32:20

know offset our Galactic mouse cursor so

play32:23

this vector represents the mouse on the

play32:25

screen but this vector represents our

play32:28

mouse within the universe as we're

play32:31

drawing the Stars out on the screen we

play32:33

can highlight which star might be

play32:35

underneath our mouse cursor of course it

play32:37

can only be underneath the mouse cursor

play32:38

if it exists so all I'm going to do is

play32:41

check whether the screens Mouse sector

play32:43

coordinates is the same as the sector

play32:45

coordinate we're currently drawing to

play32:47

and if it is I'm going to draw a circle

play32:49

around that sector let's take a look

play32:57

and though we can see a nice yellow

play32:59

circle around starts and it only appears

play33:02

where they exist so I've not had to do

play33:04

any searching in this instance and I say

play33:06

pound the screen across we can see

play33:08

occasionally we get that the circle

play33:11

popping up has accidentally put the

play33:12

cursor over a star system but it doesn't

play33:15

matter where we are in our universe it

play33:17

can immediately determine whether a star

play33:20

exists there universe is with just stars

play33:23

in are all well and good but not very

play33:25

realistic star systems need to contain

play33:28

other bodies so I'm going to create a

play33:30

structure called s planet and this is

play33:33

going to contain all sorts of different

play33:35

information about the planets and I'm

play33:37

not interested and I'm not even going to

play33:38

implement most of it I'm just leaving it

play33:40

here is an example that actually you can

play33:42

create this as detailed as you like

play33:44

you've just got to follow this process

play33:45

of always generating your random numbers

play33:47

in the same order and each planets not

play33:50

only is it going to have a bunch of

play33:52

material properties it may have a ring

play33:54

and it's going to have a selection of

play33:56

moons in our star system constructor

play33:59

there is no need to keep generating

play34:01

things if we know that we don't need

play34:03

them for example when we determine that

play34:05

a star didn't exist we immediately

play34:07

aborted the construction this means we

play34:10

could easily put gates within our system

play34:12

that will generate only up to the level

play34:15

of detail that we require so I'm going

play34:17

to add a boolean as a simple example up

play34:20

here

play34:20

generate full system when we're in the

play34:23

galaxy map view which we've just been

play34:25

scrolling around I don't care whether

play34:27

the stars have planets or not all I care

play34:29

about is whether the star exists it's

play34:31

only when I select one of the stars do I

play34:34

then need to go and generate a star with

play34:36

all of the planets and so if I don't

play34:38

care about generating the full system

play34:40

I'm just going to return immediately all

play34:42

I cared about was generating what does

play34:44

the star look like but now I do care

play34:47

what the planets look like and we'll get

play34:50

through this pretty quickly because I

play34:51

think we're getting to the point where

play34:52

I'm just repeating the same point over

play34:54

and over but to generate a planet I'm

play34:57

going to choose a random distance from

play34:59

the star because they don't all exist at

play35:02

the uniform distances from stars and I'm

play35:04

going to generate how many planets there

play35:06

might be okay it's a for loop to then go

play35:09

who all of these planets worn by one and

play35:11

for each planet I'll create my planet

play35:13

structure and I'll start to populate it

play35:15

with some of the information so each

play35:16

time I'm drawing more and more

play35:18

randomness from our sequence of

play35:20

pseudo-random numbers none of these

play35:22

numbers really are going to make any

play35:24

difference to this demonstration

play35:26

although it did occur to me that if you

play35:28

wanted to describe the makeup of a

play35:30

planet like this as percentages then you

play35:33

can't go over 100 percent so we probably

play35:35

want to normalize those numbers all of

play35:37

this is utterly irrelevant to procedural

play35:39

generation but I wanted to sort of

play35:41

demonstrate that once you start

play35:42

generating these very random bases you

play35:45

can manipulate this randomness as you

play35:47

see fit based on real-world equations

play35:50

based on previously drawn random numbers

play35:52

you could even go as far as to generate

play35:55

modifications to these random numbers

play35:57

based on the neighboring stars in the

play35:59

system if they exist or not you can also

play36:02

do interesting things with the

play36:03

probability distribution so here I've

play36:05

chosen a population value and it's

play36:07

choosing a random integer between oddly

play36:10

- five million and 20 million now you

play36:13

can't have a negative population but by

play36:15

using the max function in conjunction

play36:17

with this some planets just will have no

play36:20

population so sort of doing a two-in-one

play36:22

calculation with the probability here if

play36:25

we wanted to look at percentages like we

play36:28

did with these whether the star system

play36:29

exists or not does this planet have a

play36:31

ring well will draw a random integer and

play36:33

see if the value is equal to one so

play36:35

there's a 10% chance in this case of the

play36:37

planet having a ring perhaps the planet

play36:40

has been moons well in the same way as

play36:42

we've done the population by taking the

play36:45

maximum of a range which can go negative

play36:47

and take making sure that the maximum is

play36:49

always greater than zero we can generate

play36:51

a proportion of planets that have moons

play36:53

and a proportion that don't so in this

play36:55

case it's approximately 50/50 whether

play36:58

the planet will have at least one moon

play37:01

and therefore if it does have moons

play37:02

we'll create a loop that goes through

play37:04

all of the moons and all I'm interested

play37:06

in is the size of the moon nothing

play37:08

stopping you then going creating more

play37:09

and more planet bodies to the moons have

play37:11

their own unique mineral systems and

play37:14

properties that you want to try and

play37:15

generate once we've fully populated a

play37:17

planet I'll add it to the star systems

play37:20

vector of planets

play37:22

which we'll need to add as one of its

play37:23

variables back in the on user update

play37:26

function let's display the star system

play37:28

for a selected star to handle mouse

play37:31

clicking I'm going to be sensitive to

play37:32

the left mouse button being clicked if

play37:35

it is I'm going to generate the star

play37:37

system object based at the location of

play37:40

the mouse coordinate in the galaxy and

play37:42

if it exists I'm going to record the

play37:44

fact that it has exists by setting a

play37:46

flag to true I also want to cache that

play37:49

particular location at the moment I

play37:52

don't care about the planets and the

play37:53

moons so I've not instructed the star to

play37:56

be constructed with all of its planetary

play37:59

detail if the star at that location

play38:01

didn't exist I'll set my selected flag

play38:04

to false I'll just add these variables

play38:06

into the class as my star selected and

play38:09

my star selected vector now that we know

play38:13

we've got the system selected and we

play38:15

know its coordinates we can go about

play38:17

drawing it on the screen and I'll

play38:19

quickly go through this but I'm not

play38:20

interested in demonstrating the actual

play38:22

drawing routines want to display on the

play38:25

screen the entire system now and we know

play38:28

that we only need to do that if our star

play38:29

selected value is true but now I am

play38:32

interested in generating the full system

play38:42

you'll see a lot of magic numbers creep

play38:45

in now these are just to position things

play38:46

on the screen nicely they're actually

play38:48

unimportant to any of this algorithm but

play38:51

firstly I want to draw a window the blue

play38:54

window that's going to hold the

play38:55

information for our star and I also want

play38:58

to draw the star on the left hand side

play39:01

of the window so all of these

play39:02

coordinates and scaling factors are just

play39:04

to make it appear on the screen in a

play39:06

pleasing way let's take a quick look to

play39:08

see if things are working so far so I

play39:14

can select a star and then we've got our

play39:16

blue window and we see the star is the

play39:18

same color as the star chosen in the

play39:20

universe and if we choose a bigger star

play39:22

it's a bigger rendered star in our blue

play39:25

window let's choose this little tiny

play39:27

star over here and as before we can move

play39:31

to anywhere in the universe and continue

play39:33

doing the same thing

play39:35

if we select somewhere where a star

play39:37

doesn't exist the window disappears once

play39:40

we've drawn the star we want to draw the

play39:42

planets that orbit the star and so here

play39:45

I've got a little Auto for loop that's

play39:47

going through the vector of planets

play39:48

associated with the star system and

play39:50

again things are scaled and positioned

play39:53

accordingly the planet may have some

play39:55

moons in which case we need to then have

play39:58

another for loop that goes through the

play40:00

vector of moons for that particular

play40:02

planet all of my planets are just drawn

play40:04

as filled circles and so let's take one

play40:06

final look there's a universe to choose

play40:14

a system we can see the planets with

play40:17

associated moons of different sizes

play40:19

around those planets there's all sorts

play40:25

of variety and we know even though I've

play40:27

not visualized that these planets have

play40:29

different properties - about the

play40:31

composition and makeup and because we've

play40:34

used procedural generation with a high

play40:37

quality random number generator that's

play40:39

very fast

play40:40

we're guaranteed that we can always come

play40:43

back to a known position in the universe

play40:45

and it will be generated exactly the

play40:47

same way and so there we have it a

play40:51

persistent and procedurally generated

play40:53

universe all stored within about 200

play40:55

lines of code and some fancy random

play40:57

number generation this has been a very

play41:00

simple demonstration of this concept but

play41:02

I'd like to go back to a point I made at

play41:04

the start that it's not necessarily the

play41:06

same as for example the Minecraft

play41:09

procedural generation routines nothing

play41:12

here is persistently stored it's always

play41:14

generated as in ways needed and this

play41:17

does cause some problems of its own how

play41:19

do we change the state of this universe

play41:21

in Minecraft for example the player will

play41:23

go and change the state of the blocks

play41:25

that are created that's quite tricky

play41:28

here and I think that's definitely going

play41:30

to be the topic for a future video as

play41:33

always the source code for this video is

play41:35

available on github from the link in the

play41:37

description below it's got a few more

play41:38

comments and a bit more material inside

play41:40

it if you've enjoyed this video please

play41:42

give me a big thumbs up have a think

play41:44

about subscribing perhaps come and have

play41:46

a chat with me and many others on the

play41:47

discourse server

play41:49

big thank you to all of my patrons or

play41:51

patreon is depending on where you from

play41:52

and I'll see you next time take care

Rate This

5.0 / 5 (0 votes)

Related Tags
程序生成虚拟宇宙游戏开发精英系列随机数生成星系构建游戏引擎宇宙探索算法实现互动体验
Do you need a summary in English?