cool!
class Particle
{
color c1,c2;
float w,h; // radii
float x,y; // center point
float r; // rotation
float t=0; //
float xP, yP; // start position
float xS, yS; // splode position
float sinTransCount=0;
float curveTransCount=0;
color c=c2;
int colorCount=0;
float colorT=0; // change in color over time
float strokeSize=1;
float easing=0;
float inflateCount;
boolean toDraw = true;
boolean activated = false;
float accel=1; // acceleration value
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) //constructor
{
x=X;
y=Y;
w=W;
h=H;
r=R;
c1=C1;
c2=C2;
}
////////////////////////////////////////////////////////////
// checkColor ( wanted color , original color)
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; // allows acceleration up to some value
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; // allows acceleration up to some value
else if(accel>maxAccel) accel=maxAccel;
}
////////////////////////////////////////////////////////////
// attract (attractor X/Y)
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;
}
//if(distance(xP,yP,x,y) < homeDist*.5)
else
{
accel*=.95;
if(accel<minAccel) accel=minAccel;
}
}
// hack to stop particle from perpetually vibrating when at start position
else if(distance(xP,yP,x,y)<2)
{
x=xP;
y=yP;
}
}
//////////////////////////////////////////////////////////////
//distance (from one point, to another point)
float distance(float x1, float y1, float x2, float y2)
{
float d= sqrt(pow(x2-x1,2) + pow(y2-y1,2)) ;
return d;
}
////////////////////////////////////////////////////////////
// magnetTrans (mouse x, mouse y, particle x, particle y)
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;
}
////////////////////////////////////////////////////////////
// curveTrans( deviation x, deviation y, radius x, radius y, center x, center y, motion speed)
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; // area of effect of particle
float homeDist=0;
void setup()
{
//smooth();
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));
}
// placing particles on grid
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; // stores start location x
p[q].yP=120+j*40; // stores start location y
p[q].activated=true;
q++;
}
}
}
void draw()
{
//background(0);
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;
// only inflate up until entity is some max value and constrain inflate rate
if(p[i].w<121) p[i].inflate(constrain(1+(1/mouseDist),0,2));
p[i].inflateCount++;
// particles are attracted, checks edge of screen
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);
}
// particles are repulsed, checks edge of screen
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 a particle has been activated for some length of time, destroy it by not drawing it and store position
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;
// only runs once, the moment a particle goes from attracted/detracted to not
if(p[i].activated==true)
{
homeDist = sqrt(pow(p[i].xP-p[i].x,2)+pow(p[i].yP-p[i].y,2));
//line(p[i].xP, p[i].yP, p[i].x, p[i].y);
p[i].activated=false;
}
// particles slowly return to their start location if their current pos != start positions
if(p[i].x != p[i].xP && p[i].y != p[i].yP) p[i].attractHome(homeDist);
// only deflate if entity larger than start size
if(p[i].w>11) p[i].inflate(.97);
if(p[i].inflateCount>=0) p[i].inflateCount--;
}
// connect by lines
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)); // cur_pos to cur_pos
connectLine(p[i].xP, p[i].yP, p[j].xP, p[j].yP, color(255,0,255)); // start_pos to start pos
}
}
}
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);
}
}
OpenProcessing is an online community platform devoted to sharing and discussing Processing sketches in a collaborative, open-source environment.
Download Processing
Terms of Service
To contact, send an email to:

See the feedback forum and vote!
Follow OpenProcessing on Twitter.
All sketches are licensed under Creative Commons Attribution-Share Alike 3.0.
Syntax highlighting and Processing brush under LGPL 3.
All the source code is licensed under Creative Commons GNU GPL.
Comments engine by Scriptsmill Comments Script.


