xxxxxxxxxx
260
class Particle
{
constructor(x, y, r, c)
{
this.X = x;
this.Y = y;
this.Radius = r;
this.Color = c;
this.StartX = x;
this.StartY = y;
this.HandleX = undefined;
this.HandleY = undefined;
this.TargetX = undefined;
this.TargetY = undefined;
this.Timer = undefined;
this.Duration = undefined;
this.PickNewHandle();
this.PickNewTarget();
this.PickNewDuration();
this.Timer = random(0, this.Duration);
}
Update(dt)
{
this.Timer += dt;
if (this.Timer >= this.Duration / 2)
this.ResetLerp();
let mx = mouseX;
let my = mouseY;
let sx = this.StartX;
let sy = this.StartY;
let hx = this.HandleX + mx;
let hy = this.HandleY + my;
let tx = this.TargetX + mx;
let ty = this.TargetY + my;
let t = this.Timer / this.Duration;
let ax = lerp(sx, hx, t);
let ay = lerp(sy, hy, t);
let bx = lerp(hx, tx, t);
let by = lerp(hy, ty, t);
this.X = lerp(ax, bx, t);
this.Y = lerp(ay, by, t);
}
Render()
{
fill(this.Color);
circle(this.X, this.Y, this.Radius * 2);
if (debug)
{
let mx = mouseX;
let my = mouseY;
let sx = this.StartX;
let sy = this.StartY;
let hx = this.HandleX + mx;
let hy = this.HandleY + my;
let tx = this.TargetX + mx;
let ty = this.TargetY + my;
fill(350, 250, 250);
circle(this.StartX, this.StartY, this.Radius * 2);
fill(150, 200, 200);
circle(this.HandleX + mouseX, this.HandleY + mouseY, this.Radius * 2);
fill(230, 150, 250);
circle(this.TargetX + mouseX, this.TargetY + mouseY, this.Radius * 2);
stroke(255, 100);
strokeWeight(3);
line(sx, sy, hx, hy);
line(hx, hy, tx, ty);
noStroke();
fill(255);
textSize(12);
textAlign(LEFT, BOTTOM);
textStyle(BOLD);
text("Current T:", 4, height - 4);
textStyle(NORMAL);
let t = this.Timer / this.Duration;
text(`${t}`, 64, height - 4);
}
}
PickNewDuration()
{
this.Duration = random(minDuration, maxDuration);
}
PickNewHandle()
{
let angle = random(0, 360);
this.HandleX = radius * cos(angle);
this.HandleY = radius * sin(angle);
}
PickNewTarget()
{
let angle = random(0, 360);
this.TargetX = radius * cos(angle);
this.TargetY = radius * sin(angle);
}
ResetLerp()
{
this.StartX = this.X;
this.StartY = this.Y;
this.HandleX = this.TargetX;
this.HandleY = this.TargetY;
this.PickNewTarget();
this.PickNewDuration();
this.Timer = 0;
}
}
let particles = [];
let particleCount = 200;
let minR = 2;
let maxR = 8;
let minB = 40;
let maxB = 120;
let minDuration = 1.0;
let maxDuration = 1.0;
let radius = 80;
let debug = false;
let beginPaused = true;
let stepping = false;
function setup()
{
createCanvas(600, 600);
background(0);
blendMode(ADD);
colorMode(HSB);
noStroke();
angleMode(DEGREES);
CreateInitialParticles();
}
function draw()
{
clear();
background(20);
if (debug)
DrawCircle();
let dt = 1 / 60;
UpdateAndRenderParticles(dt);
if (beginPaused)
{
beginPaused = false;
Pause();
}
if (stepping)
{
stepping = false;
Pause();
}
}
function keyPressed()
{
if (keyCode === 32) // Spacebar
TogglePause();
else if (keyCode === 68) // D for debug
debug = !debug;
else if (keyCode === RIGHT_ARROW)
Step();
}
function CreateInitialParticles()
{
for (let i = 0; i < particleCount; ++i)
{
let x = random(0, width);
let y = random(0, height);
let r = random(minR, maxR);
let c = color(35, 80, random(minB, maxB));
CreateParticle(x, y, r, c);
}
}
function CreateParticle(x, y, r, c)
{
particles.push(new Particle(x, y, r, c));
}
function UpdateAndRenderParticles(dt)
{
for (const particle of particles)
{
particle.Update(dt);
particle.Render();
}
}
function DrawCircle()
{
noFill();
stroke(35, 150, 120);
strokeWeight(3);
circle(mouseX, mouseY, radius * 2);
noStroke();
}
function TogglePause()
{
if (isLooping())
Pause();
else
Unpause();
}
function Pause()
{
noLoop();
}
function Unpause()
{
loop();
}
function Step()
{
stepping = true;
Unpause();
}
function Dt() { return deltaTime / 1000; }