I'm wrapping my head around procedural generation, and the difference between it and random generation. I get that the difference is that it's deterministic, which is based off a specific seed value, like all random engines are.
So in C++11, I understand that to get the 'best' random sequences, an std::seed_seq
should be used, and it doesn't need to be cryptographically secure, so an std::mt19937
is fine.
In this scenario, I want a bunch of positions for objects in the world so I can generate a level, and then I want to text my friend the seed of this brand new level because it was really cool. But as it is, typing 189151022 140947902 1454660100 853918093 3243866855
is really annoying. So what can I do as a dev to make sure the randomness is preserved with a bit more type-ability?
I thought hash the values as a string and then reverse it, (but then I remembered the point of hashes) or just use the hash itself, but would that be worse as a seed? Or does it even matter, and can I just use "lol" as my seed and have that be just as good as a megabyte-long perfectly random number?
Here's the quick example I made to help me understand it a bit better.
#include <iostream>
#include <random>
#include <array>
using std::cout;
using std::endl;
using std::array;
struct pos
{
float x, y;
pos(float x, float y) : x(x), y(y) {}
void print()
{
cout << "(" << x << " " << y << ")" << endl;
}
};
int main()
{
//Get seed
std::random_device rd;
array<unsigned long, 5> seed = { rd(), rd(), rd(), rd(), rd() };
//Seed generator
std::mt19937 generator;
generator.seed(std::seed_seq(seed.begin(), seed.end()));
//Setup distribution
std::uniform_real_distribution<float> distribution(0, 100);
//Generate the world (or whatever)
pos a = pos(distribution(generator), distribution(generator));
pos b = pos(distribution(generator), distribution(generator));
pos c = pos(distribution(generator), distribution(generator));
//And many, many more calls to get values from the generator
a.print();
b.print();
c.print();
//For when I want the same world back
cout << "Seed: ";
for (unsigned long s : seed)
{
cout << s << " ";
}
cout << endl;
}
To be clear, the question I'm asking is:
What should I use for a seed in a procedural generator in a game context, and what are the upsides and downsides of doing it in that fashion?
Aucun commentaire:
Enregistrer un commentaire