Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Procedural Content Generation for C++ Game Development

You're reading from   Procedural Content Generation for C++ Game Development Get to know techniques and approaches to procedurally generate game content in C++ using Simple and Fast Multimedia Library

Arrow left icon
Product type Paperback
Published in Jan 2016
Publisher
ISBN-13 9781785886713
Length 304 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Dale Green Dale Green
Author Profile Icon Dale Green
Dale Green
Arrow right icon
View More author details
Toc

Table of Contents (13) Chapters Close

Preface 1. An Introduction to Procedural Generation FREE CHAPTER 2. Project Setup and Breakdown 3. Using RNG with C++ Data Types 4. Procedurally Populating Game Environments 5. Creating Unique and Randomized Game Objects 6. Procedurally Generating Art 7. Procedurally Modifying Audio 8. Procedural Behavior and Mechanics 9. Procedural Dungeon Generation 10. Component-Based Architecture 11. Epilogue Index

Seeds

We just created a program to generate pseudorandom numbers, but every time we run it we get the same results. We know that these numbers are the results of complex equations and algorithms, so why are they the same? It's because each time we run the program, we're starting with the same seed.

Defining seeds

A seed provides a starting point for an algorithm. So, in the previous example, yes we're using complex algorithms to generate numbers, but we're kicking off the algorithm at the same point each time. No matter how complex the algorithm is, if you start at the same point, and perform the same operations, you're going to get the same results.

Imagine that we have three people, and each person is about to walk the same path by 5 steps. If they all start from the same square, they will end at the same square:

Defining seeds

Now, in the next diagram, we give these three people unique starting positions. Even though they are doing the same actions as before, and are on the same path, their results are different because they started from different locations:

Defining seeds

In this analogy, the path is the algorithm, and the starting square is the seed. By changing the seed we can get different results from the same actions.

You will have most likely used seeds before and not even known it. Games that procedurally generate worlds, such as Minecraft and Lego Worlds, give you the option to set a seed manually before generating a world. If your friend generates a world that looks great, they can grab their seed and give it to you. When you input that seed yourself, you kick off the algorithm at the same place that your friends did and you end up with the same worlds.

Using seeds

Now that we know what seeds are, let's fix the previous example so that we don't keep generating the same numbers. To do this, we will use the std::srand() function. It's similar to std::rand(), but it takes an argument. This argument is used to set the seed for an algorithm. We'll add the call to std::srand() before we enter the while loop.

Tip

You only need to set the seed once per run of the application. Once std::srand() has been called, all the subsequent calls to std::rand() will be based upon the updated initial seed.

The updated code should look like this:

// Random number generation
// This program will generate a random number each time we press enter.

#include <iostream>

using namespace std;

int main()
{
  // Here we will call srand() to set the seed for future rand() calls.
  srand(100);

  while (true)
  {
    cout << "Press enter to generate a random number:";
    cin.get();

    // Generate a random integer.
    int randomInteger = rand() % 201 + 50;

    cout << randomInteger << endl << endl;
  }

  return 0;
}

Now when we run this code we get different results! I got 214, 60, 239, 71, and 233. Don't worry if your numbers don't match mine exactly; they are both CPU- and vendor-specific. So, what will happen if we run the program again? We changed the seed. So we should get different numbers again, right?

Not quite. We called std::srand() and set a new seed, but each time we run the program we're setting the same seed again. We're kicking the algorithm off at the same position each time, so we're seeing the same results. What we really want to do is randomly generate a seed during runtime so that the algorithm always starts at a new position.

Generating random seeds during the runtime

There are many ways to achieve this, and your use case will determine which method is suitable. For us, as game developers, something relatively trivial such as the current system time will usually suffice.

This does mean that if you run the program at the exact same time you'll get the same results, but that's almost never going to be a problem for our use. C++ provides us with a nice function to get the current time, time(), which is located in <ctime>.

Let's update the program one last time and pass time() as a parameter in std::srand() so that we generate unique numbers with every run:

// Here we will call srand() to set the seed for future rand() calls.
//srand(100);
srand(time(nullptr));

Now, every time we run the program, we get unique numbers! You may have noticed that if you run the program multiple times in succession, the first number is always very similar to the last run. That's because between the runs time doesn't change a lot. This means that the starting points are close to each other and the results reflect this.

Controlled randomness is the key to generating random numbers

The process of generating random numbers is a huge component in creating systems that procedurally generate game content. There are lots of ways in which random data is generated, such as noise maps and other external systems, but in this book, we'll stick to these simple C++ functions.

We want systems that are predictable enough to give us control over them as developers, but they should be dynamic enough to create variations for the player. This balance can be hard to achieve, and sometimes games get it wrong. Later in this chapter, we'll look at some of the things that you have to watch out for when incorporating procedural generation into a game project to avoid this.

You have been reading a chapter from
Procedural Content Generation for C++ Game Development
Published in: Jan 2016
Publisher:
ISBN-13: 9781785886713
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime