class Particle
{
color c1,c2;
float w,h;
float x,y;
float r;
float t=0;
float xP, yP;
float xS, yS;
float sinTransCount=0;
float curveTransCount=0;
color c=c2;
int colorCount=0;
float colorT=0;
float strokeSize=1;
float easing=0;
float inflateCount;
boolean toDraw = true;
boolean activated = false;
float accel=1;
float maxAccel=6;
float minAccel=.7;
int numSplodes=6;
Splode[] splodes = new Splode[numSplodes];
Particle(float X, float Y, float W, float H, float R, color C1, color C2)
{
x=X;
y=Y;
w=W;
h=H;
r=R;
c1=C1;
c2=C2;
}
void checkColor(color cc1, color cc2)
{
if(colorCount>60)
{
c=c2;
colorCount=0;
}
if(c != c2)
{
colorCount++;
}
if(colorT<0) colorT=0;
if(colorT>1) colorT=1;
}
void fillPart(color cFill, float trans)
{
noStroke();
fill(cFill, trans);
ellipse(x,y,w-2,h-2) ;
}
void inflate(float rate)
{
w *= rate;
h *= rate;
strokeSize*=rate;
}
void attract(float rate)
{
activated=true;
x+=accel*(mouseX-x) / distance(mouseX,mouseY,x,y);
y+=accel*(mouseY-y) / distance(mouseX,mouseY,x,y);
if(accel<maxAccel) accel=1+rate/1.5;
else accel=maxAccel;
}
void detract(float rate)
{
activated=true;
x-=accel*(mouseX-x) / distance(mouseX,mouseY,x,y);
y-=accel*(mouseY-y) / distance(mouseX,mouseY,x,y);
if(accel<maxAccel) accel=1+rate;
else if(accel>maxAccel) accel=maxAccel;
}
void attractHome(float homeDist)
{
if(distance(xP,yP,x,y)>2)
{
x+=accel*(xP-x) / distance(xP,yP,x,y);
y+=accel*(yP-y) / distance(xP,yP,x,y);
if(distance(xP,yP,x,y) > homeDist*.6)
{
accel*=1.1;
if(accel>maxAccel) accel=maxAccel;
}
else
{
accel*=.95;
if(accel<minAccel) accel=minAccel;
}
}
else if(distance(xP,yP,x,y)<2)
{
x=xP;
y=yP;
}
}
float distance(float x1, float y1, float x2, float y2)
{
float d= sqrt(pow(x2-x1,2) + pow(y2-y1,2)) ;
return d;
}
void magnetTrans(float mx, float my, float dis)
{
if(mouseButton==LEFT)
{
easing=1/dis;
x -= (mx-x)*easing;
y -= (my-y)*easing;
}
else if(mouseButton==RIGHT)
{
easing=1/dis;
x += (mx-x)*easing;
y += (my-y)*easing;
}
}
void returnTrans()
{
easing = .03;
x += (xP-x)*easing;
y += (yP-y)*easing;
}
void curveTrans(float sx, float sy, float rx, float ry, float xx, float yy, float speed)
{
curveTransCount+=speed;
x=xx+(cos(curveTransCount*sx)*rx);
y=yy+(sin(curveTransCount*sy)*ry);
}
void transParticle(float xT, float yT)
{
if(t<=1)
{
x = (1-t)*xP+t*xT;
y = (1-t)*yP+t*yT;
t+=.01;
}
}
void sinTrans(float xT, float yT)
{
x = (1-t)*xP+t*xT;
y = (1-t)*yP+t*yT;
t=sin(sinTransCount);
sinTransCount+=.04;
}
void drawParticle()
{
checkColor(c1, c2);
for(float t=0; t<=360; t+=13)
{
float a= x + w/2 * cos(radians(t))*cos(radians(r))-h/2*sin(radians(t))*sin(radians(r));
float b= y + h/2 * sin(radians(t))*cos(radians(r))+w/2*cos(radians(t))*sin(radians(r));
strokeWeight(strokeSize);
stroke(lerpColor(c1,c2,colorT));
point(a,b);
}
}
void prepSplode()
{
xS=x;
yS=y;
for (int i = 0; i < numSplodes; i++)
{
splodes[i] = new Splode(xS+random(-10,10), yS+random(-10,10), 9, i, splodes);
}
}
void drawSplode()
{
for (int i = 0; i < numSplodes; i++)
{
splodes[i].collide(numSplodes);
splodes[i].move();
splodes[i].display();
}
}
}
Particle [] p = new Particle[225];
float aoe=150;
float homeDist=0;
void setup()
{
size(800,800);
int q=0;
for(int i=0; i<225; i++)
{
p[i]= new Particle(250,250,11,11,45,color(255),color(255,255,0));
}
for(int i=0; i<15; i++)
{
for(int j=0; j<15; j++)
{
p[q].x=random(-aoe,aoe)+120+i*40;
p[q].y=random(-aoe,aoe)+120+j*40;
p[q].xP=120+i*40;
p[q].yP=120+j*40;
p[q].activated=true;
q++;
}
}
}
void draw()
{
fill(0,75);
noStroke();
rect(0,0,width,height);
stroke(255);
for(int i=0; i<225; i++)
{
float mouseDist = sqrt(pow(mouseX-p[i].x,2)+pow(mouseY-p[i].y,2));
if(mouseDist<=aoe)
{
if(mousePressed==true)
{
p[i].colorT+=.05;
float normDist = (aoe-mouseDist)/aoe*4;
if(p[i].w<121) p[i].inflate(constrain(1+(1/mouseDist),0,2));
p[i].inflateCount++;
if(mouseButton==LEFT)
{
if(p[i].x >= (0+p[i].w) && p[i].x <= (width-p[i].w) && p[i].y >= (0+p[i].h) && p[i].y <= (height-p[i].h))
p[i].attract(normDist);
}
else if(mouseButton==RIGHT)
{
if(p[i].x >= (0+p[i].w) && p[i].x <= (width-p[i].w) && p[i].y >= (0+p[i].h) && p[i].y <= (height-p[i].h))
p[i].detract(normDist);
}
if(p[i].inflateCount==80)
{
p[i].toDraw=false;
p[i].prepSplode();
}
}
else p[i].accel=1;
if(p[i].toDraw==true) p[i].fillPart(color(255,0,0) , (aoe-mouseDist)/aoe*255);
}
else
{
p[i].colorT-=.01;
if(p[i].activated==true)
{
homeDist = sqrt(pow(p[i].xP-p[i].x,2)+pow(p[i].yP-p[i].y,2));
p[i].activated=false;
}
if(p[i].x != p[i].xP && p[i].y != p[i].yP) p[i].attractHome(homeDist);
if(p[i].w>11) p[i].inflate(.97);
if(p[i].inflateCount>=0) p[i].inflateCount--;
}
for (int j=0; j<p.length; j++)
{
if(i != j)
{
float lineDist= dist(p[i].x, p[i].y, p[j].x, p[j].y);
if(lineDist<38 && p[i].toDraw==true && p[j].toDraw==true)
{
strokeWeight(1);
connectLine(p[i].x, p[i].y, p[j].x, p[j].y, color(255));
connectLine(p[i].xP, p[i].yP, p[j].xP, p[j].yP, color(255,0,255));
}
}
}
if(p[i].toDraw==true)
{
p[i].drawParticle();
connectLine(p[i].xP, p[i].yP, p[i].x, p[i].y, color(150));
}
if(p[i].toDraw==false)
{
noStroke();
p[i].drawSplode();
}
}
}
void connectLine(float x1, float y1, float x2, float y2, color c)
{
stroke(c);
line(x1,y1,x2,y2);
}
class Splode
{
float x, y;
float diameter;
float vx = 0;
float vy = 0;
int id;
Splode[] others;
float spring = 0.5;
Splode(float xin, float yin, float din, int idin, Splode[] oin) {
x = xin;
y = yin;
diameter = din;
id = idin;
others = oin;
}
void collide(int numSplodes) {
for (int i = id + 1; i < numSplodes; i++) {
float dx = others[i].x - x;
float dy = others[i].y - y;
float distance = sqrt(dx*dx + dy*dy);
float minDist = others[i].diameter/2 + diameter/2;
if (distance < minDist) {
float angle = atan2(dy, dx);
float targetX = x + cos(angle) * minDist;
float targetY = y + sin(angle) * minDist;
float ax = (targetX - others[i].x) * spring;
float ay = (targetY - others[i].y) * spring;
vx -= ax;
vy -= ay;
others[i].vx += ax;
others[i].vy += ay;
}
}
}
void move() {
x += vx;
y += vy;
if (x + diameter/2 > width) {
x = width - diameter/2;
vx += -0.9;
}
else if (x - diameter/2 < 0) {
x = diameter/2;
vx *= -0.9;
}
if (y + diameter/2 > height) {
y = height - diameter/2;
vy *= -0.9;
}
else if (y - diameter/2 < 0) {
y = diameter/2;
vy *= -0.9;
}
}
void display() {
fill(255,0,0);
ellipse(x, y, diameter, diameter);
}
}