A fork with extra config options.
I lied in a sunbeam, feeling the Sun's hot kiss when, through my closed eyelids, I read its name.
Log in to post a comment.
// Forked from "way wavy way" by ge1doot
// https://turtletoy.net/turtle/65cb465053
// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(0.33);
const ySpacing = 1.6; //min=0 max=3 step=.1
const octaves = 3; //min=1 max=10 step=1
const seed = 257; //min=1 max=1000 step=1
const xScale = 1; //min=.1 max=5 step=0.1
const yScale = 0.5; //min=.1 max=5 step=0.1
const xOffset = 0; //min=-1000 max=1000 step=1
const yOffset = -54; //min=-1000 max=1000 step=1
const lineCount = 282; //min=1 max=1000 step=1
/*
Seedrandom function from
https://github.com/davidbau/seedrandom/blob/released/seedrandom.js
Copyright 2019 David Bau.
See source for complete copyright information.
The source has been modified slightly from the original to make it shorter.
*/
(function (global, pool, math) {
var width = 256, // each RC4 output is 0 <= x < 256
chunks = 6, // at least six RC4 outputs for each double
digits = 52, // there are 52 significant digits in a double
rngname = 'random', // rngname: name for Math.random and Math.seedrandom
startdenom = math.pow(width, chunks),
significance = math.pow(2, digits),
overflow = significance * 2,
mask = width - 1
function seedrandom(seed, options, callback) {
var key = [];
options = (options == true) ? { entropy: true } : (options || {});
var shortseed = mixkey(flatten(
options.entropy ? [seed, tostring(pool)] :
(seed == null) ? autoseed() : seed, 3), key);
var arc4 = new ARC4(key);
var prng = function() {
var n = arc4.g(chunks), d = startdenom, x = 0;
while (n < significance) {
n = (n + x) * width;
d *= width;
x = arc4.g(1);
}
while (n >= overflow) {
n /= 2;
d /= 2;
x >>>= 1;
}
return (n + x) / d;
};
prng.int32 = function() { return arc4.g(4) | 0; }
prng.quick = function() { return arc4.g(4) / 0x100000000; }
prng.double = prng;
mixkey(tostring(arc4.S), pool);
return (options.pass || callback ||
function(prng, seed, is_math_call, state) {
if (state) {
if (state.S) { copy(state, arc4); }
prng.state = function() { return copy(arc4, {}); }
}
if (is_math_call) { math[rngname] = prng; return seed; }
else return prng;
})(
prng,
shortseed,
'global' in options ? options.global : (this == math),
options.state);
}
function ARC4(key) {
var t, keylen = key.length,
me = this, i = 0, j = me.i = me.j = 0, s = me.S = [];
if (!keylen) { key = [keylen++]; }
while (i < width) {
s[i] = i++;
}
for (i = 0; i < width; i++) {
s[i] = s[j = mask & (j + key[i % keylen] + (t = s[i]))];
s[j] = t;
}
(me.g = function(count) {
var t, r = 0,
i = me.i, j = me.j, s = me.S;
while (count--) {
t = s[i = mask & (i + 1)];
r = r * width + s[mask & ((s[i] = s[j = mask & (j + t)]) + (s[j] = t))];
}
me.i = i; me.j = j;
return r;
})(width);
}
function copy(f, t) {
t.i = f.i;
t.j = f.j;
t.S = f.S.slice();
return t;
};
function flatten(obj, depth) {
var result = [], typ = (typeof obj), prop;
if (depth && typ == 'object') {
for (prop in obj) {
try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {}
}
}
return (result.length ? result : typ == 'string' ? obj : obj + '\0');
}
function mixkey(seed, key) {
var stringseed = seed + '', smear, j = 0;
while (j < stringseed.length) {
key[mask & j] =
mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++));
}
return tostring(key);
}
function autoseed() {
try {
var out;
out = new Uint8Array(width);
(global.crypto || global.msCrypto).getRandomValues(out);
return tostring(out);
} catch (e) {
var browser = global.navigator,
plugins = browser && browser.plugins;
return [+new Date, global, plugins, global.screen, tostring(pool)];
}
}
function tostring(a) {return String.fromCharCode.apply(0, a);}
mixkey(math.random(), pool);
math['seed' + rngname] = seedrandom;
})((typeof self !== 'undefined') ? self : this,[],Math);
const turtle = new Turtle();
class Noise {
// http://mrl.nyu.edu/~perlin/noise/
constructor(octaves = 1) {
this.p = new Uint8Array(512);
this.octaves = octaves;
var rng = new Math.seedrandom(seed)
for (let i = 0; i < 512; ++i) {
this.p[i] = rng() * 256;
}
}
lerp(t, a, b) {
return a + t * (b - a);
}
grad2d(i, x, y) {
const v = (i & 1) === 0 ? x : y;
return (i & 2) === 0 ? -v : v;
}
noise2d(x2d, y2d) {
const X = Math.floor(x2d) & 255;
const Y = Math.floor(y2d) & 255;
const x = x2d - Math.floor(x2d);
const y = y2d - Math.floor(y2d);
const fx = (3 - 2 * x) * x * x;
const fy = (3 - 2 * y) * y * y;
const p0 = this.p[X] + Y;
const p1 = this.p[X + 1] + Y;
return this.lerp(
fy,
this.lerp(
fx,
this.grad2d(this.p[p0], x, y),
this.grad2d(this.p[p1], x - 1, y)
),
this.lerp(
fx,
this.grad2d(this.p[p0 + 1], x, y - 1),
this.grad2d(this.p[p1 + 1], x - 1, y - 1)
)
);
}
noise(x, y) {
let e = 1,
k = 1,
s = 0;
for (let i = 0; i < this.octaves; ++i) {
e *= 0.5;
s += e * (1 + this.noise2d(k * x, k * y)) / 2;
k *= 2;
}
return s;
}
}
const perlin = new Noise(octaves);
turtle.up();
function walk(i) {
for (let j = -100; j < 101; j++) {
const h = perlin.noise(100 + j * 0.01, 100 + i * 0.01);
turtle.goto(xOffset + j * xScale, yOffset + yScale * ySpacing * i + yScale * h * 200 - 100);
turtle.down();
}
turtle.up();
return i < lineCount;
}