Keine Ergebnisse gefunden
Today, I want to talk to you about random number generation (RNG). Or, more accurately, pseudo-random number generation (PRNG). Technically speaking, computer software is really only capable of PRNG, as computers are mostly incapable of generating a truly random number. This is because computers are deterministic. So, when generating random numbers, the computer is following the same algorithm to generate the numbers. Generally, this means that the computer is using a “seed” and generating numbers based on that seed. If the seed never changes, the result of generation never changes. Considering that the data required to generate the random numbers is predefined, this means the generation is “pseudo random."
Pseudo random is extremely useful because it can be controlled. You can use the same seed every time to help track down bugs, and to easily replicate generation outcomes over and over for testing.
In this blog, we will go over a couple of different examples of how to use PRNG, and how to control the seed. As usual, I will be using GameMaker Studio as my dev environment, but pretty much every programming language has similar functions built in. Rarely would you ever need to write your own random generation functions. However, if you are interested in doing so, I will link to some documentation at the end of the blog.
We are going to start simple by generating a series of numbers that range from 0 - 9, and printing them to the screen. Since I am using GameMaker Studio as my dev environment, it is important to note that by default, GameMaker Studio will always use the same seed unless specifically told otherwise. So if you are using Game Maker Studio as well, and you do NOT want to use the same seed (which for this section we don’t), you will need to make sure you call the randomize() function before you do your RNG code.
The randomize() function in GameMaker Studio randomizes the seed every time you run your game. If you didn’t call this function, everyone who plays your game could end up with the same seed and as such, have the same outcomes for all randomly generated content! This actually happened fairly recently with a port of a very famous AAA RPG series. When the game was originally released on the PS2, the seed used for RNG was based on the system's internal clock. So, when the game was ported to other platforms, there was no PS2 system clock to check! This resulted in every player having the same exact seed.
The first thing you should do is familiarize yourself with the random functions provided in your language of choice. For me the big ones are random(), irandom(), random_range(), and irandom_range(). These functions are nearly identical except irandom only returns whole numbers. Most of the time, I use irandom over random for that exact reason, but it really depends on what you are trying to accomplish.
In the example code below, I am generating a list of 10 random numbers that range from 0-9. After that, I simply draw the numbers to the screen that are in the list. A note about irandom is that it returns a random value between 0 and the number in the brackets. So this this case, it returns any number between and including 0-9.
Create event
number_list = ds_list_create();
for(i = 0; i < 10; i++){
n = irandom(9);
ds_list_add(number_list,n);
}
In the draw event, we read the numbers from the list using another for loop, and draw them to the center of the screen.
Draw event
for(i = 0; i < ds_list_size(number_list); i ++){
n = ds_list_find_value(number_list,i);
draw_text(room_width / 2 + (i - 5)* 32, room_height / 2, n);
}
I know this isn’t terribly exciting, but understanding the basics is key. I often create a handful of RNG functions for things like dice rolls, determining a percent chance, or a coin flip. Here are some examples of those.
Dice roll function
i = irandom_range(1,6);
return i
This is about as basic as a dice roll gets. We simply return a random number between 1 and 6. You can use this function for all kinds of things. Consider a tabletop game like Warhammer, where you may need to roll a die and get a value that is equal to or greater than a certain value to damage your opponent.
Here is what that might look like using the above function.
n = number to beat
if (dice() >= n ) {
//deal some damage
}{
A similar check based on percentage is very very similar. Say you have an RPG and your character has a 45% chance to hit the target. Your check may look something like this.
//my percentChance function
if (irandom_range(1, 100) <= argument[0]) {
return true;
} else {
return false;
}
//when you are checking to see if your character hits
if(percentChance(45)){
hit = true;
}else{
hit = false;
}{
When doing a coin flip, you are essentially doing the same thing as a percent chance check, except its always going to be 50/50.
//my coin function
if(irandom_range(1,100) <= 50){
return true;
}else{
return false;
}
//calling the coin function in code
if(coin()){
//do something if true
}{
You can use this to randomly generate pretty much anything in your game. In the example below, I am using RNG to set a random horizontal speed, vertical speed, spawn position, random ranges for each RGB value, sprite, the number of little guys that are spawned, and sprite direction!
And here I am using RNG to generate caves for a top down game. I will show you all how to do this in the next blog entry by using Cellular Automata (it's not as complicated as it sounds).
I hope this blog entry helped open your eyes a bit to how RNG can be used and that it's not quite as intimidating as it sounds. I mean, most of the work is done for you with built in random functions!
Next time, we will learn to wrangle RNG a little more and create some cool environments.
Nathan Ranney is the founder of game development studio Gutter Arcade. He's best known for the creation and development of Knight Club, an online indie fighting game.