Placeholder Image

字幕列表 影片播放

  • Hello.

  • It's a new year for one lone Koda.

  • So let's have a nice simple video to get started.

  • Let's procedurally generate the universe.

  • Now, To those of you that frequent the discord server, you will know that I'm a big fan of the elite Siri's of games going way back to the early eighties, where the elite games presented an entire universe on a very small machine.

  • I am machine with not very much memory, Andi.

  • Over the Christmas period, I've been playing elite, dangerous and loving every minute of it, and it has a vast universe.

  • In fact, it has a universe so large it can't all possibly be stored on the computer.

  • And so I've decided to create a small application here, which tries to emulate that effect on As you can see, I'm panning around well, a very simplistic looking universe of different star systems.

  • So each of these circles represents a star.

  • The first thing to note is that the universe is actually persistence.

  • If I scroll this way, it will look the same as I school this way.

  • Admittedly, it's easy to get lost in my universe because I'm not put any coordinates on the screen natural at that, too.

  • Their to do list.

  • But please don't misunderstand.

  • This universe is vast.

  • It's huge.

  • It will go on for billions and billions of stars.

  • And they were all exist in exactly the same place as I move the mouse cursor around, I can highlight specific stars.

  • So let's that cook on this one.

  • You can click on this one, and we see around the stars that several planets and the planets have several moons.

  • Let's try a different one.

  • Try a few so some don't have any.

  • But they all have something different on again.

  • These are persistent, so I could go to one side of the universe and come back.

  • These will still be here.

  • We contest this.

  • Let's try and find some features I can recognize.

  • So here we've got a small cluster of planets that's pick that one in the middle on.

  • I'm going to panel the way this way for a few seconds, and then I'm going to pan all the way back and try and find that cluster.

  • There it is and click on the same one we see.

  • We get the same results on it doesn't matter how big this universe is.

  • There's no search time required.

  • It will always generate the same persistent star systems forgiven star.

  • The size of this universe is limited only by the precision of the interview types I'm using to store the position of the mouse coordinate.

  • It is vast and yet can be rendered on dhe interacted with in no time at all.

  • You can also see on the right hand side of the screen here that the universe conceals very little memory.

  • As I'm moving around, we're not generating more and more planets and stars that so there's no more memory created on.

  • Nothing is cashed out to disk that would be far too slow, and you'll just have to take my word for it.

  • But the size of the executed well on disk is about 30 kilobytes.

  • So how do we store on entire persistent universe and access it so quickly on my computer?

  • Well, hopefully, it's obvious that we can't store the entire universe on my computer.

  • Instead, we're going to use an elaborate series of equations to generate the universe as we need it on.

  • We'll use our mouths coordinates X and Y as the input parameters to this equation.

  • This technique is called procedural generation.

  • We see it quite a lot in games like Minecraft or Road likes.

  • Now I'm going to take a little bit of an issue with that, and I'm expecting some debate in the comments about this.

  • I think games like Road likes net tax and Minecraft and all of those games that generate random content.

  • I don't necessarily consider those to be procedural generation.

  • I think about Moore's automated generation because take my craft, for example.

  • It generates the world in these chunks on.

  • Once it generated them, they need to be stored.

  • They need to be fixed somewhere on recalled when they're required.

  • In my mind, procedural generation is something a bit different.

  • It is generating the resources as required on the fly on consistently each time.

  • I don't think either term is incorrect, but in my mind it makes sense to make a distinction between the two.

  • That gangs that automatically generate resources and assets are not quite the same as games that procedurally generate resources and assets At the heart of all procedurally generated applications lies, randomness or, in the case of a computer, pseudo randomness.

  • Because we can't realistically generate true random numbers.

  • But randomness on its own is not enough to create compelling resources.

  • We need to control that randomness in such a way that makes our applications sensible.

  • In this video, I hope to show us that.

  • So let's get stuff as usual.

  • I'm going to start with a skeleton pixel game engine project, so it's got nothing in the on user created on user update functions on I'm Constructing the Pixel game engine to be 5 12 by 4 80 onder each game pixel is to my to screen pixels.

  • Now.

  • I've also moved over to Visual Studio 2019 and I'm still learning what it's going to be doing with tool tips and things popping up all over the video.

  • So I apologize if they get in the way.

  • Fundamentally, Procedural Generation is about controlling randomness, and so I think it's worth spending a few minutes just exploring the available options off pseudo random number generation that's available to us with c++ language.

  • And rather than just look at the statistics of the generated numbers, I'm going to visualize them instead on I'm going to do that whenever the space key is pressed if you've seen my videos before him, we've looked at things like noisy images on the screen.

  • It's always caused the YouTube algorithm to completely collapse when it's displaying the video.

  • So by making its sensitive to the space bar being released, I should hopefully be able to retain the integrity of the image, which is going to be necessary to understand whether a random number generator is good for us or not.

  • The two qualities of the random number generator I want to look at the first is how good is the randomness on the second is how fast can it generate the random number?

  • So I'm putting in too little time points so I can measure the duration off the generation.

  • I'm going to draw that to the top left of the screen, using the pixel game engines drawstring function.

  • My intention here is to go through every pixel on the screen and for each pixel we're going to draw a random number, and depending upon value of that random number, I'm going to set a flag B s star to true or false, and I'll just simply for now use a single pixel is the star.

  • It's either white or black.

  • And the only reason I'm drawing the Black Stars, even though I've previously cleared the screen appear to all black is to just make sure that the timing is consistent.

  • For example, if the random number generator generated a few white stars, it's going to give the appearance that is performing better.

  • So I need to make sure that the drawing of the star is not factoring into the timing of the randomness functions.

  • So let's start with the random function everybody knows round.

  • And everybody also knows well least have been told that Rand is not a very good random number generator.

  • Well, let's take a look.

  • So I'm going to draw a random number between zero and 255 inclusive on I'm going to check.

  • Is that value less than 32?

  • So, in principle, we're looking at an eighth of the screen being stars or white.

  • In this case, let's run the application now to get any stars to appear.

  • I need to press the space bar, so there we go on.

  • On average, this told us to generate This field of stars took about six milliseconds on dhe.

  • The randomness doesn't look too bad at first glance anyway.

  • Keep pressing space.

  • I can regenerate more and more stars, and the time to do so is well.

  • It's roughly always the same.

  • A handful of milliseconds.

  • The problem is, I want to control the randomness.

  • It's no good to me to just have genuine randomness here.

  • I need some way of shaping that randomness into a universe.

  • If I always wanted to generate the same universe each time, I would need to see to the random number generator with some sort of key.

  • I'm going to pick a value at random here, 1000.

  • So now when I run the application, even though impressing the space bar on, we can see it's generating it.

  • The universe is the same each time, so knowing that we can set the seed of a pseudo random number generator is going to be really important for maintaining persistence.

  • Across the assets were procedurally generating, but there's a problem here in order to know whether a pixel is black or white.

  • I need to have generated them in this specific sequence from the top left all the way to wherever my cursor is.

  • So yes, I can always check what color the pixel is under the cursor.

  • But if I wanted to derive that based on our randomness equations, how do I do it right now?

  • I have to start at the top left on Generate the sequence precisely because of the set seed all the way until the point that I need it.

  • This could be very slow, particularly if I've got an entire universe to procedure, regenerate out, have to generate the universe up until the point that it is under my mouse cursor.

  • And this is exactly what I'm not trying to do.

  • I don't want have to generate the universe in advance and store it somewhere in order to interrogate it or cess various components of it.

  • What if instead, we used to seed that was based on the spatial location within the universe.

  • So instead of setting the seed once at the start, I'm going to set it for every single star that we generate.

  • But there's no point in using a fixed number all the time, because then the entire universe would be the same.

  • Instead, I'm going to take the X and Y position of the screen and sort of squash that together into a seed value and use that as my seed.

  • This approach guarantees that the seed is different for every pixel on the screen.

  • Yet regardless of the location, it should consistently generate the same sequence of random numbers for that location.

  • Let's take a look.

  • It's best this baseball well, it's certainly generating numbers, and it's plotting stars, and it's taking a little bit more time now that we're setting the seed.

  • But something tells me that's not quite random.

  • Perhaps I'm just getting very, very unlucky with the distribution.

  • So let's change that to a 50 50 distribution.

  • Well, that's not changed very much on.

  • In fact, this highlights the limitations of using Rand.

  • Given that we're choosing to plot a pixel as white or black, based on the first random number generated after setting a seed, thes patterns suggest that the random number is highly correlated to the seed.

  • Therefore, it's burly, random at all.

  • In fact, it's utterly predictable.

  • In this instance, it's around his rubbish.

  • We're going to need something better than round.

  • Modern C++ actually provides a good random library as part of its standard library, generating high quality and robust random numbers is well beyond the scope of this video.

  • It's a complete computer science and mathematics field in its own right.

  • There's a lot of research and dedicated effort going into generating high quality random numbers simply because they underpin all of our digital communications and cryptography.

  • Service's as I just demonstrated, even though we've used round plenty of times in previous videos, it's great for little bits of randomness in games.

  • If you're really relying on its integrity to generate random numbers, it could probably very easily be hacked.

  • I think generating random numbers on computers is a fascinating topic.

  • I don't know if it will ever be solved until we get dedicated hardware which concerned how exploit the environment in order to generate some random numbers.

  • But until then, we've got what we've got in good old modern c++ fashion.

  • Using the random library is a little bit wordy.

  • First, we have to choose some sort of random device.

  • This is meant to be the seed that will be generated randomly from my machine.

  • Then we need to choose what kind of random number generation engine do we want to use, and in this case, I'm going for the mise en Twister.

  • It's reasonably accepted as being one of the most robust random number generators out there.

  • At least a lot of research has gone into it.

  • I can't just draw a random number like before.

  • I need to specify a distribution on in this case.

  • I'm testifying a uniform distribution so all numbers should haven't even probability of being drawn.

  • So this time, let's include the standard random part.

  • And just as we did before, we'll do the same test.

  • I'm going to draw a random number between zero and 255 inclusive and plot the pixel.

  • You'll know that I've not included this setup within my time period.

  • Ideally, you don't you need to do this once.

  • One final thing just because I forgot where we need some parentheses after the RD in the construction off the mise en twister object.

  • So let's take a look.

  • So as before this press the space bar and, well, it looks pretty much the same.

  • If anything, I would say it's a little more evenly distributed than it was using Rand Not seeing quite a cz many clusters or line artifacts, you might just be my eyes playing tricks on me.

  • But it does seem to look better, and it's taking approximately the same time.

  • At 3.8 milliseconds, Formula seconds there generate a few more, so that's fine.

  • But again, we've got this problem of We've just set the seed once for the entire universe.

  • Now we need to set it per star.

  • Well, using the same scene generators before I'm just going to see the mise en twister.

  • Let's try that space And while oh dear, I mean, it looks great.

  • It's perfect what we want, but it's taking about 400 milliseconds.

  • 395 400 milliseconds to generate the screen.

  • It looks like seeding.

  • The mise en twister algorithm is quite slow and probably far too slow for our needs.

  • However, it has generated a very nice random universe, so I could place my mouse cursor anywhere in this scene on converting its coordinates to use as a seed for the random number generator will tell me whether the star exists or not is the pixel white or black.

  • And so the quality of the random number is brilliant here in this case, but the performance of its sucks we need something that's a good in between.

  • So C++ random library mise en twister, you're out.

  • It takes far smarter people on more dedicated people than me to generate a high quality random number generator.

  • So I would suggest Go on.

  • Finding one on one that's been around for quite some time is the lemma or Lima random number generator.

  • I was using this back in the early two thousands as part of a research project I was doing for the university.

  • This was before the introduction of the Random Library.

  • We had easy access to algorithms such as Miss a Twister.

  • This algorithm is known as being reasonably robust, but the beauty of it and what's going to appeal to us, is that it's actually very, very quick.

  • We're going to need to create a little utility function to generate these lemma random numbers.

  • Now, if it's not pronounced lemma, then I apologize to Dr Lemma.

  • So I'm going to create a small function called Lam a 32 because it's going to generate 32 bit numbers.

  • Most of the algorithm shown for this generates 64 bit numbers on By converting it to 32 bit, I've probably completely compromised.

  • Its integrity is a robust a random number generator.

  • I'm aware of that.

  • It works by maintaining a state variable on each time we draw a random number, we're going to change that state.

  • In fact, that state is in a random number on even though this will look like gobbledygook, that's all there is to it, and we can see Computational e.

  • There's not a great deal going on here.

  • We've got some additions.

  • What?

  • We've got an Inter Jim multiplication.

  • Then all we've got our shifts and source.

  • These are all very cheap computational instructions to use on the maths.

  • Behind this is mostly beyond me, but I'm on the understanding that these are some type of specialist prime number and buys a roaring with these prime numbers and shifting the register.

  • We can change the state of al M a variable.

  • In many ways, this is very similar to a linear feedback shift register, so let's just get stuck in and use it straightaway instead of looking at the whole screen.

  • This time, we're going to look at just setting the seed value directly to be the lemma states and that sort of prime ing the shift register on.

  • As we have done exactly before, I'm going to draw a random number between zero and 255 inclusive.

  • So let's take a look space.

  • And what we see now is a persistent universe being generated per pixel on the screen, with same performance as Rand.

  • And so this is perfect for what we need.

  • Procedural generation is fundamentally harnessing the properties of probability to generate interesting things.

  • Let's just take a very simple, one dimensional example to assume I've got a plane of land, and I wanted to populate this land with trees in the universe.

  • Example.

  • We're using the location in space as the seed for a random number generator, So I'm going to do the same sort of thing here on I'm breaking space up into discrete sons.

  • For each zone, I'm effectively rolling a dye and making a decision based on the output so I can assume with my Di example that's a tree exists If my random number is less than two.

  • In this case, there's a 33% chance of a tree existing, so we might see one here and one here, one here, et cetera, et cetera.

  • If I made this threshold larger, let's say if it's less than or equal to five, so there's only a one in six chance of it not being a tree.

  • We would certainly expect to see a lot more trees in each section to the point, whether all uniformly distributed across the land in order to bias procedural generation to give us plausible results.

  • We can't just rely on the probability and harsh thresholds alone in this tree example.

  • We may see that if we did have the probability of it being a tree set too high, all of our trees would be uniformly spaced.

  • It wouldn't look particularly realistic.

  • Perhaps we want clumps of trees to exist instead.

  • Well, this is just a case of biasing.

  • Our threshold values on some of the parameters.

  • Perhaps the special value could be based on location.

  • So as the location number increases is going across the screen, the probability of it being a tree also increases, at which point it's unlikely would see a tree here at the start.

  • But as we're moving along the screen, we may start to see them on.

  • We'll start to see them with more frequency so you could use this approach toe have sort of a boundary going into a forest, for example, we can also use lots of other interesting functions to access this threshold.

  • Perhaps we wanted a clump of trees to appear somewhere in the middle of this land.

  • Well, if we used a threshold value that was biased by some of the function, for example, Gaussian curve, then in this region it's far more likely we'll see trees than in these extreme regions.

  • The beauty of this approach is that our random number has never changed, but our understanding of how we want to construct the world as forces to think about how to manipulate the results of that drawn random number.

  • And this is really down to earth as engineers to devise an appropriate solution set of rules to construct compelling worlds.

  • And I'm not arguing that that in itself is easy.

  • It's far from it, depending on the level of detail you want to go to.

  • But fundamentally, the random component is at least guaranteed to be consistent, and so, irrespective of how complicated your generation routine is, it will always be the same each time.

  • So, given that we know we're going to get the exact same sequence Forgiven Seed, and that sequence is going to be random.

  • I'm going to construct my universe by first checking for that location.

  • Does a star exist?

  • That's that becomes my first random number.

  • Draw.

  • I'm going to draw a maximum 20 and I'm going to test.

  • Is that equal toe?

  • One that will tell me, Does the star exit So one in every 20 locations will contain a star.

  • Now it's important I don't reset the seed because I want the sequence of random numbers that are generated to be the same every single time.

  • So the seed has been set.

  • Once on we've generated.

  • Does a star exist?

  • If it does, then I'm going to determine the size of the star.

  • And again, that's going to be some random number generated in this case.

  • Between 10 and 40 thes units are meaningless, and they will need to be chosen to suit the application that you're trying to procedurally generate.

  • Then I'm going to draw another random number for the color of the star, and I've got eight possible colors to choose from, and then I want to generate how many planets surround the star and then for each planet in order.

  • I want to determine some properties off the planet.

  • What is its size?

  • What is its temperature?

  • What is its makeup?

  • A.

  • What percentage is perhaps covered in foliage?

  • What percentage is covered in water?

  • How much of it is minerals?

  • You can make up all sorts of different parameters.

  • What is its population?

  • Each time we start to create a statistic, we always draw some random number from our pseudo random number sequence.

  • The sequence is always going to be the same each time.

  • That's the real take home message on what the interesting thing is.

  • We can start to not only just use the sequence, but we can use the values off parameters we've already chosen.

  • So let's say we're also maintaining the distance away from the start.

  • Well, we could use that distance function as part of the temperature calculations.

  • We can use the temperature calculations to tell us.

  • Is it likely there's going to be water on the surface on if there's no water on the surface?

  • What's the probability of there being foliage?

  • So this is really up to the designer now to start thinking, How are all of these things connected?

  • But the beauty of this is it's generated when it's needed each time.

  • Because even though randomness is involved in the definition off the planets and the stars and the systems, the randomness is under our control, and it's guaranteed to be consistent.

  • But the key principle here is we have to generate these random numbers in the same order each time.

  • Now we've explored the randomness.

  • I'm going to remove this code from the application I'm going to add to the application.

  • A new class which represents a star system on the constructor of this class, is going to be the thing that does all of the work.

  • So a lot of constructor, which takes in an X and Y coordinate, which is the location of this star system in the universe.

  • I'm going to take our little random number generator from before and move that over to the class.

  • Well, keep those private.

  • The first thing that star system needs to do is generated seed based on its location, which, as we've just seen before, is merging together the X and Y coordinates.

  • Now I'm using a 32 bit system here, but I'm only looking at the least significant 16 bits off the X and Y corner that will, of course, put some boundaries on the universe.

  • They will only have 16 bit coordinate resolution, any taxis.

  • So it's not going on forever, Aunt.

  • Hopefully, when it does get to one end of the universe, it should just wrapped around to the other quite nicely.

  • Of course, if we needed larger universes, we would use more bit.

  • As we start to procedurally generate this star system, we're going to need to store some of its states to hear about it.

  • A Boolean, whether it exists, something that represents the size of this star on the stars color.

  • And I'll draw the stars color from an array of colors, which I've defined as a constant expression at the start of the program.

  • So these are Alfa blue, green, red in hex.

  • I don't always want to draw a random numbers of the typed, unsigned interview 32.

  • Instead of rather work with doubles and regular EMTs, that's a bit more convenient, and also I want to work with numbers that are within boundaries that is sensible for the things I'm trying to define.

  • So I want to create some utility functions where I supply a minimum and maximum each time.

  • So this one will generate a random interview between this minimum on that maximum on this function will return a random double with same constraints.

  • Note that they both call Dilemma 30 to function.

  • So going back to our constructor, we can start to generate this system.

  • Firstly, does it exist?

  • And that's quite important and quite an odd concept because you might think well, of course the system must exist.

  • Were constructing a class that represents that sister.

  • Well, that's not quite true.

  • We're actually creating a definition of what exists at that location within the universe.

  • So our Boolean star exists will be set to true one in 20 times on average.

  • If the star doesn't exist, I'm just going to abort the construction.

  • There's literally no point in doing anything else so very cheaply we have set the seed, determined whether the star exists or not.

  • And if it does, then we go on to create more interesting features.

  • If it doesn't, then who cares?

  • Assuming the start does exist, then I'm going to generate something that represents its diameter and choose its color from the array above.

  • Instead of working with screen in a per pixel basis, I'm going to break the screen into sectors which is easily done by taking any location on the screen on interview, dividing it by the dimensions of our sector, which I'm going to set to 16 by 16 pixels.

  • This allows me to then take wth the size of the star that we've just generated and in some cases will have small stars and in some cases will have big stars.

  • And then we'll have some medium stars, but it gives me space to plot them.

  • In this little simple demonstration.

  • I'm just going to draw a circle of the appropriate color, but you could have cost procedurally generate images.

  • You could create animated graphics.

  • The possibilities are literally limitless.

  • It just depends how much effort you're prepared to put into generating the detail required for your application in the autumn User update function.

  • I'm going to stop drawing out world, so now we will clear the screen to black and I'll create two variables in sectors X and in sectors.

  • Why, which tells us how many sex is we've got across and down the screen because you might choose a different resolution and sector size.

  • This year, I'm going to get into the habit off using the built in vector types in the pixel game engine.

  • So here I am creating a two dimensional interview vector called Screen Sector, which is going to hold the coordinates of a particular sector on the screen.

  • I want to reiterate through all of the sectors that's a visible on the screen to have two nested four loops that are just scanning through all of the accident.

  • Why coordinates on?

  • Because our sectors are quite large, there aren't that many sectors to process for a given sector location.

  • We need to determine what is the star system in that sector.

  • So I construct a star system object, but only to pass in the location, which will be used to cede the lemma generator later on.

  • At this point, I'm only interested if this star actually exists now that will have been set by the procedural generation routine in the constructor of Sea Star system.

  • Unless you'll see with the best of this video, I'm really just goingto hack in the graphics appropriately, So here I'm going to draw a circle in the middle of our sector, and I've got some hard coded numbers in here.

  • I know I shouldn't, but the point of this video is not about the visual ization.

  • It's about the generation.

  • So this will just draw Phil Circle based upon the size of the star, which already we now know because we have a star system object onto the color.

  • So let's just take a quick look.

  • That's very nice.

  • We can see we've got a variety of different size stars.

  • Not every single sector is populated with a snap on the stars of different colors, but right now our universe is very, very small because we can't move around in it.

  • If we want to move around the universe, we need to know where we are within the universe.

  • So I'm going to create a to D vector called Galaxy offset.

  • This effectively represents the camera location inside our universe and in on user update.

  • Before we draw anything, we're going to handle some user input.

  • We're going to be sensitive to the W S.

  • A and D keys being pressed to change the value of our galaxy offset vector bias Fixed constant speed.

  • Don't forget in the pixel game engine.

  • If we want movement, we need to modulate by f elapsed time to make the movement smooth because the frame weight will very depending on the load of your computer.

  • But you wanted to move.

  • That's a consistent, visible rate.

  • We've done that many times before This galaxy offset.

  • Vector effectively represents the top left of the screen.

  • Onda nested four loops going through all of the visible sectors on the screen should be added to that offset to give us the real location in space.

  • So to our screen sector variables, I'm going to add in galaxy offset his ex.

  • Then why now?

  • We should be able to move around the universe smoothly.

  • If I move this way and we can see the stars are consistent going back, it is actually a bit of a bold statement for me to say We can see the stars a consistent because none of us have memories that are that good.

  • Let's just test the theory.

  • So here I've got a big cluster off planets.

  • Hopefully that should be recognizable in the future.

  • Let's mentally clock that one in.

  • I'm going to scroll down for quite a while.

  • There we go.

  • I'm going to scroll back up and hopefully we should find that cluster of planets again.

  • Maybe that will demonstrate that it's consistent.

  • There it is.

  • Now we've not stored that anywhere.

  • We've generated that cluster dynamically on demand when we need it.

  • But because we've got complete control of our sequence of random numbers, it is the same as having generated it previously on stored it because we don't actually care about the numeric value of our seeds.

  • The fact that our galaxy offset vectors going negative and positive depending on where we are in the universe, it doesn't matter.

  • It will always generate the same sequence of random numbers.

  • Now that we've got this vast universe, it would be useful to be able to interact with it sensibly.

  • We've got billions of planets.

  • We don't want to have to search through all of the planets to find which one we selected.

  • What's its location?

  • And of course, now we don't need thio.

  • We know where our mouse cursor is going to be within the university space, so we can just interrogate that sector location, get all of the information procedurally generated immediately for us to use as we see fit.

  • So I'm going to add in some mouse user input.

  • Two.

  • I'm going to get the screen space mounts, coordinate on, divided by a number of sectors.

  • So again, now we know which sector across the screen are.

  • Mouse is in.

  • But because we can offset the galaxy, we also need to know offset our galactic milks cursor.

  • So this factor represents the Maris on the screen.

  • But this rector represents our mouths within the universe.

  • As we're drawing the stars out on the screen, we can highlight which star might be underneath our mouse cursor.

  • Of course, it can only be underneath the mouse cosa if it exists.

  • So all I'm going to do is check whether the screens mouse sector coordinates is the same as the sector Cornet were currently drawing, too.

  • And if it is, I'm going to draw a circle around that sector.

  • Let's take a look.

  • You know, we could see a nice yellow circle around starts and it only appears where they exist.

  • So I've not had to do any searching in this instance, and ice I pound the screen across.

  • We can see occasionally we get a little circle popping up has accidentally put the cursor over a star system.

  • But it doesn't matter where we are in our universe.

  • It can immediately determine whether a star exists.

  • The universities would just stars in are all well and good, but not very realistic.

  • Star systems need to contain other bodies, so I'm going to create a structure called S Planet.

  • This is going to contain all sorts of different information about the planet.

  • And I'm not interested, and I'm not even going to implement most of it.

  • I'm just leaving it here is an example that actually you can create this as detailed as you like.

  • You've just got to follow this process of always generating random numbers in the same order on each planet's.

  • Not only is it going to have a bunch of material properties it may have a ring on, it's going to have a selection of moons in our star system constructor.

  • There is no need to keep generating things if we know that we don't need them.

  • For example, when we determined that a star didn't exist, we immediately aborted the construction.

  • This means we could easily put Gates within our system that will generate only up to the level of detail that we require.

  • So I'm going to add a Boolean as a simple example appear of generate full system when we're in the Galaxy map view, which we've just been schooling around.

  • I don't care whether the stars have planets or not.

  • All I care about is whether the star exists.

  • It's only when I select one of the stars.

  • Do I then need to go on, generate a star with all of the planet.

  • And so if I don't care about generating the full system, I'm just going to return immediately.

  • All I cared about was generating what does the star look like?

  • But now I do care what the planets look like, and we'll get through this pretty quickly because I think we're getting to the point where I'm just repeating the same point over and over.

  • But to generate a planet, I'm going to choose a random distance from the star because they don't all exist of the uniformed distances from stars on, I'm going to generate how many planets that might be.

  • Our creates a four loop to then go through all of these planets one by one, and for each planet are creates my planet structure, and I'll start to populate it with some of the information.

  • So each time on drawing more and more randomness from our sequence of pseudo random numbers, none of these numbers really are going to make any difference to this demonstration.

  • Although it did occur to me that if you wanted to describe the makeup of a planet like this as percentages, then you can't go over 100% so you probably want to normalize those numbers.

  • All of this is earthly relevance to procedural generation.

  • But I wanted to sort of demonstrate that once you start generating these very random basis, you can manipulate this randomness as you see fit.

  • Based on real world equations based on previously drawn random numbers, you could even go as far as to generate modifications to these random numbers based on the neighboring stars in the system.

  • If they exist or not, you can also do interesting things with the probability distribution.

  • So here are chosen population value, and it's choosing a random interview between oddly minus five million on 20 million now you can't have a negative population.

  • But by using the max function in conjunction with this, some planets just will have no population.

  • So sort of doing a two in one calculation with the probability here if we wanted to look at the percentage is like we did with these, whether the star system exists or not that does.

  • This planet's have a ring will wield your random interview and see if the values equal toe want.

  • So there's a 10% chance, in this case of the planet having a ring.

  • Perhaps the planet has moons well in the same ways we've done the population.

  • By taking the maximum of a range, which can go negative and take making sure that that maximum is always greater than zero.

  • We can generate a proportion of planets that have moons and a proportion that don't.

  • So in this case it's approximately 50 50 whether the planet will have at least one moon, and therefore, if it does have moons will create a loop that goes through all of the moons, and all I'm interested in is the size of the moon's.

  • Nothing stopping you then going, creating more and more planet bodies to the moon's have their own unique mineral systems and properties that you want to try and generate.

  • Once we fully populated a planet, I'll add it to this star systems.

  • Vector Off planets, which will need to add, is one of its variables back in the all news update function.

  • Let's display the star system.

  • First selected star toe handle, mouse clicking.

  • I'm going to be sensitive to the left mouse button being clicked.

  • If it is, I'm going to generate the star system object based at the location off the mouse cornet in the galaxy.

  • And if it exists, I'm going to record the fact that it has exist by setting a flag.

  • Too.

  • True.

  • I also want to cash that particular location.

  • At the moment.

  • I don't care about the planets and the moons, so I've not instructed this star to be constructed with all of its planetary detail.

  • If the star of that location didn't exist, I'll set my selected flag to false.

  • I'll just have these variables into the class that my star selected on my star selected vector.

  • Now that we know we've got a system selected on, we know its coordinates we can go about drawing it on the screen on.

  • I'll quickly go for this, but I'm not interested in demonstrating natural drawing routines.

  • Want to display on the screen the entire system now, and we know that we only need to do that if our star selected value is true.

  • But now I am interested in generating the full system.

  • You'll see a lot of magic numbers creep in now.

  • These are just two position things on the screen, nicely actually unimportant to any of this algorithm.

  • Firstly, I want to draw a window, the blue window that's going to hold the information for our star.

  • And I also want to draw the star on the left hand side of the window.

  • So all of these coordinates and scaling factors are just to make it appear on the screen in a pleasing way.

  • Just take a quick look to see if things are working so far.

  • I can select a star on that.

  • We've got our blue window and we still the star is the same color as the star chosen in the universe.

  • And if we choose a biggest star, it's a bigger rendered star in our blue window.

  • Let's choose this little tiny star over here on.

  • As before, we could move to anywhere in the universe and continue doing the same thing.

  • If we select somewhere where a star doesn't exist, the window disappears.

  • Once we've drawn the star, we want to draw the planets that orbit the star.

  • And so here I've got a little auto four loop that's going through the vector of planets associated with the star system.

  • And again things are scaled and positioned accordingly.

  • The planet may have some moons, in which case we need to then have another four loop that goes through the vector of moons for that particular planet.

  • All of my planets are just drawn us filled circles.

  • And so let's take one final look.

  • There's our universe to choose a system.

  • We could see the planets with associative moons of different sizes around those planets.

  • There's all sorts of variety, and we know, even though I've not visualize them, that these planets have different properties.

  • Two about the composition and makeup on.

  • Because we've used procedural generation with a high quality random number generator, that's very fast.

  • We're guaranteed that we can always come back to a known position in the universe, and it will be generated exactly the same way.

  • And so there we have a persistent and procedurally generated universe, all stored within about 200 lines of code on some fancy random number generation.

  • This has been a very simple demonstration of this concept, but I'd like to go back to a point I made of that start that it's not necessarily the same as, for example, the Minecraft procedural generation routines.

  • Nothing here is persistently stored.

  • It's always generated, as in ways needed on.

  • This does cause some problems of its own.

  • How do we change the state of this universe?

  • In Minecraft, for example, the player will go and change the state of the blocks that they created.

  • That's quite tricky here on.

  • I think that's definitely going to be the topic for a future video.

  • As always, the source code for this video is available on Get Hope from the link.

  • In the description below, it's got a few more comments and a bit more material inside it.

  • If you've enjoyed this video, please give me a big thumbs up.

  • Have a think about subscribing, perhaps come and have a chat with me and many others on the discourse ever big.

  • Thank you to all of my patrons or patrons depending on away from I'll see you next time.

  • Take it.

Hello.

字幕與單字

單字即點即查 點擊單字可以查詢單字解釋

B1 中級

程序化生成。程序生成: 宇宙編程 (Procedural Generation: Programming The Universe)

  • 1 1
    林宜悉 發佈於 2021 年 01 月 14 日
影片單字