Skip to content

Instantly share code, notes, and snippets.

@veltman
Last active November 22, 2020 03:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save veltman/ffce0162d5f55eafb9866a1b588831e8 to your computer and use it in GitHub Desktop.
Save veltman/ffce0162d5f55eafb9866a1b588831e8 to your computer and use it in GitHub Desktop.
Particle tentacles

This got a little weird.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<canvas width="960" height="500"></canvas>
<canvas width="960" height="500" class="offscreen" style="display: none;"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var width = 960,
height = 500;
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
offscreen = document.querySelector(".offscreen"),
offscreenContext = offscreen.getContext("2d");
offscreenContext.globalAlpha = 0.8;
var numDots = 1200;
var points = d3.range(numDots).map(function(d, i){
return {
position: new Vec2(Math.random() * width, Math.random() * height),
velocity: new Vec2(Math.random() * 3, Math.random() * 3)
};
});
d3.shuffle(points);
points.forEach(function(p, i){
p.target = points[i + 1] || points[0];
p.color = d3.interpolateRainbow(i / numDots);
});
var maxVelocity = 3,
maxForce = 0.4;
d3.timer(function(t){
points.forEach(function(p){
var destination = p.target.position.clone(),
desiredVelocity = destination.subtract(p.position).normalize().scale(maxVelocity),
steering = desiredVelocity.subtract(p.velocity).truncate(maxForce);
p.velocity.add(steering).truncate(maxVelocity);
});
offscreenContext.clearRect(0, 0, width, height);
offscreenContext.drawImage(canvas, 0, 0, width, height);
context.clearRect(0, 0, width, height);
context.drawImage(offscreen, 0, 0, width, height);
points.forEach(function(p, i){
// Wall bounces
if (p.position.x + p.velocity.x < 0 || p.position.x + p.velocity.x >= width) {
p.velocity.x = -p.velocity.x;
}
if (p.position.y + p.velocity.y < 0 || p.position.y + p.velocity.y >= height) {
p.velocity.y = -p.velocity.y;
}
p.position.add(p.velocity);
context.beginPath();
context.fillStyle = p.color;
context.arc(p.position.x, p.position.y, 2, 0, 2 * Math.PI);
context.fill();
});
});
function Vec2(x, y) {
this.x = x || 0;
this.y = y || 0;
return this;
};
Vec2.prototype.add = function(v) {
this.x += v.x;
this.y += v.y;
return this;
};
Vec2.prototype.clone = function() {
return new Vec2(this.x, this.y);
};
Vec2.prototype.subtract = function(v) {
this.x -= v.x;
this.y -= v.y;
return this;
};
Vec2.prototype.scale = function(s) {
this.x = this.x * s;
this.y = this.y * s;
return this;
};
Vec2.prototype.normalize = function() {
var length = this.length();
this.x = this.x / length;
this.y = this.y / length;
return this;
};
Vec2.prototype.length = function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
};
Vec2.prototype.truncate = function(max) {
var length = this.length();
if (length > max) {
this.x = this.x * max / length;
this.y = this.y * max / length;
}
return this;
};
Vec2.prototype.dot = function(v) {
return this.x * v.x + this.y * v.y;
};
</script>
@JerryLeeCS
Copy link

Is truncate making the dots going faster when it's farther away from the 0,0 point?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment