A simple rendering for demonstration of design intent
forked from Kcnarf's block: Simplex Worms + Explanations
xxxxxxxxxx
<meta charset="utf-8">
<style>
canvas {
margin: 10px;
border: solid lightgrey 1px;
}
</style>
<body>
<div id="worms" class="step">
<canvas></canvas>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="simplex-noise.min.js"></script>
<script>
var _2PI = 2*Math.PI;
var simplex = new SimplexNoise(),
timeBasedLength = 20000, //lower values make the noise evolving faster
coordBasedLength = 80; //lower values make close particles behave more differently
var particleCount = 30,
particleRadius = 2,
particles = new Array(particleCount),
particleSpeed = 0.75;
var interval = 10, //a direction/noise every interval
midInterval = interval/2,
fieldValues = [];
var cbw = 1, //canvas border width
cm = 10, //canvas margin
width = 800,
height = 400;
initLayout();
initParticles();
var wormsContext = document.querySelector("#worms canvas").getContext("2d");
d3.interval(function(elapsed) {
updateSimplexField(elapsed);
updateParticles(elapsed);
redrawWorms();
// redrawParticles();
// redrawDirections();
// redrawNoises();
});
function initLayout() {
d3.selectAll("canvas")
.attr("width", width)
.attr("height", height);
}
function initParticles() {
for (var i = 0; i < particleCount; ++i) {
particles[i] = {
x: width*Math.random(),
y: height*Math.random(),
noise: 0,
direction: 0
};
}
}
function updateSimplexField (elapsed) {
var timeBasedChange = elapsed/timeBasedLength;
//begin: compute a value every 10-x and 10-y
fieldValues = [];
for (var x = interval; x < width-midInterval; x+=interval) {
for (var y = interval; y < height-interval; y+=interval) {
var noise = simplex.noise3D(x/coordBasedLength, y/coordBasedLength, timeBasedChange);
var noiseBasedAngle = _2PI*noise;
fieldValues.push({
x: x,
y: y,
noise: noise,
direction: noiseBasedAngle
})
}
}
//end: compute a value every 10-x and 10-y
}
function updateParticles(elapsed) {
var timeBasedChange = elapsed/timeBasedLength;
//begin: update each particle's coord. using SimplexNoise
for (var i = 0; i < particleCount; ++i) {
var p = particles[i];
var noise = simplex.noise3D(p.x/coordBasedLength, p.y/coordBasedLength, timeBasedChange);
var noiseBasedAngle = _2PI*noise;
var change = {vx: particleSpeed*Math.cos(noiseBasedAngle),
vy: particleSpeed*Math.sin(noiseBasedAngle)}
p.x += change.vx;
p.y += change.vy;
p.noise = noise;
p.direction = noiseBasedAngle;
if (p.x < -particleRadius || p.x > width+particleRadius ||
p.y < -particleRadius || p.y > height+particleRadius) {
p.x = (i===0)? width/2 : width*Math.random();
p.y = (i===0)? height/2 : height*Math.random();
p.noise = 0;
p.direction = 0;
}
}
//end: update each particle's coord. using SimplexNoise
}
function redrawWorms() {
//begin: fade existing image
wormsContext.globalCompositeOperation = 'source-over';
wormsContext.fillStyle = 'rgba(1, 1, 1, .04)';
wormsContext.fillRect(0, 0, width, height);
wormsContext.globalCompositeOperation = 'source-over';
//end: fade existing image
//begin: insert particles
wormsContext.fillStyle = 'rgba(255, 255, 255, .5)'
for (var i = 0; i < particleCount; ++i) {
wormsContext.beginPath();
wormsContext.arc(particles[i].x, particles[i].y, particleRadius, 0, _2PI);
wormsContext.fill();
}
//end: insert other particles (black, small)
}
</script>
</body>
Modified http://d3js.org/d3.v4.min.js to a secure url
https://d3js.org/d3.v4.min.js