Quite often when developing a game I need “random” numbers, that I can reproduce or that I can steer. Why? – For example when setting up a level or when resetting a level you might want to have it look random, but still the same every time you load it. – So how do we do that? There are tons of ways of achieving a so called “seeded random generated number” – if you want any details on the algorithms you can for example check out this link. But basically they all work the same: You initialize the algorithm with a “seed” (a number, that you choose to steer the algorithm). And every seed will return its own unique set of “random” numbers, so e.g.: Every time I seed the Number 6, I get the same set of generated “random” numbers. Every time I seed the Number 10, I get the same set of “random” number, that is different from the set ‘6’ and so on…
Because of this fact: seeded random numbers are predictable, which is not bad, but just don’t use it for encryption purposes ect…
The algorithm
So the algorithm I’m using is the following, it’s really very simple:
(this is nothing new and also nothing I invented, but I think this might help quite a few people)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// the initial seed Math.seed = 6; // in order to work 'Math.seed' must NOT be undefined, // so in any case, you HAVE to provide a Math.seed Math.seededRandom = function(max, min) { max = max || 1; min = min || 0; Math.seed = (Math.seed * 9301 + 49297) % 233280; var rnd = Math.seed / 233280; return min + rnd * (max - min); } |
You may ask: Why ‘(seed * 9301 + 49297) % 233280‘ ?!
The answer is both simple&complicated: The combination of 9301, 49297 and 233280 provide a very even distributed set of “random” numbers. Please don’t ask WHY – that’s the complicated part, some very smart people figured out those numbers quite some time ago, and I also cannot tell you how they did it. But as allways: Google is your friend
Benchmark
I set up a small benchmark on jsfiddle, to test the performance of that algorithm and also how the distribution of the generated sets are: Just hit then Run-button and see the results, for me Math.random() is usually 3-4x faster than Math.seededRandom(), which is for 100.000 numbers still within the range of 10-15ms and therefor pretty fast. Also the distribution of the numbers is very equal as you can see.
See it in ‘action’
I quickly implemented this in my Runner Game Prototype, so no matter how often you reload the page, the level is allways going to look the same and all I did was replacing the “Math.random()” with “Math.seededRandom()” and of course I added the algorithmto the utilities-file.
If you want to try out other seeds, just go to: http://demos.indiegamr.com/jumpy/seededRandomLevel/?seed=1.57 and change the “seed” in the query string.
Pingback: 随机数生成算法 | 鹏博无际