Sunday, December 9, 2018

repeatable random colors in javascript

Indiegamer olsn provides a nice function making a repeatable series of "random" numbers:

// 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);
}

(Of course to quote John von Neumann: "Anyone who attempts to generate random numbers by deterministic means is, of course, living in a state of sin.")

olsn goes on to say
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 ;-)

That bit reminds me John Carmack's Fast inverse square root where a little bit shifting and then subtracting from the magic number 0x5F3759DF gives surprisingly good results for an otherwise very expensive math calculation. 

My favorite use of finding a great random seed is in classic video games - both Pitfall! and River Raid on the Atari 2600 use it to generate huge amounts of content (for River Raid, see this page on an amazing 'bot that was taught to play it amazing well and explore The River of No Return) but I thought I might use something similar to generate a series of colors for a project I'm on - I wanted to make a series of colors that kind of harmonized but were still distinct - one trick I learned is to constrain each r g and b value to a medium-size range (or if you alternate between #ff and #cc you get some nice pastels, which is how my loveblender site got its look in the 90s which given the era, wasn't half bad)

For each part of the rgb I generate a number from 100-200:
Math.round(Math.seededRandom(100,200)).toString(16);
and that makes a series like this:




(If the inline version doesn't work you can see it in action here.)

(Note to self, Indiegamer's book From Zero to the App Store looks interesting)

2 comments:

  1. Ha! I just used that exact same snippet of code very recently!

    I have since swapped it for p5's random() that already supports setting the seed, but it worked quite well

    ReplyDelete
    Replies
    1. Cool! That reminds me I really should peruse through the p5 docs - every once in a while I run into some tidbit I don't remember from my Processing circa 2004 days :-D

      Delete