
int NUM_PARTICLES = 2000;
int NUM_NEGATTRACTORS = 10;
int NUM_ATTRACTORS = 10;
Particle[] particle = new Particle[NUM_PARTICLES];
Attractor[] attractors = new Attractor[NUM_ATTRACTORS+50];
Attractor[] negattractors = new Attractor[NUM_NEGATTRACTORS];
Forces forcefield;
void setup() {
size(600,240,P3D);
background(0);
forcefield = new Forces(NUM_ATTRACTORS,NUM_NEGATTRACTORS,50 ); //put in numattractors,numnegattractors acceleration
for (int i = 0; i < particle.length; i++) //for loop running through all of the 2000 particles
{
particle[i] = new Particle(0,0,1,1,0); //instantiating each of the 2000 particles
if (i<(particle.length/2)) //if statement that allows me to set a parameter on half of the to one thing and to something else on the other half
{
particle[i].x=width; //if the particle is in the first half of the 2000 (aka 0-999) makes the x position equal to the width of the applet so its all the way to the right
}
}
}
void draw() {
fill(255,0,0);
for (int j = 0; j < particle.length; j++)
{
particle[j].step();
particle[j].checkDistance(j);
}
forcefield.drawAttractorPoints();
}
void mouseClicked()
{
forcefield.addAttractor();
}
void keyPressed() {
if (key == CODED) {
if (keyCode == UP) {
setup();
}
}
}
class Forces {
float accel; //gets its value from forces input (50 in this case gets put in)
int NUM_ATTRACTORS=10;
int NUM_NEGATTRACTORS=10;
Forces (int _NUM_ATTRACTORS,int _NUM_NEGATTRACTORS, float _a) //constructor for forces
{
accel = _a;
NUM_ATTRACTORS = _NUM_ATTRACTORS;
NUM_NEGATTRACTORS = _NUM_NEGATTRACTORS;
negattractors = new Attractor[NUM_NEGATTRACTORS+50];
for (int i = 0; i < NUM_ATTRACTORS; i++)
{
negattractors[i] = new Attractor(int (random(25,600)), int (random(0,250)) );
}
NUM_ATTRACTORS = _NUM_ATTRACTORS;
attractors = new Attractor[100];
for (int i = 0; i < NUM_ATTRACTORS; i++)
{
attractors[i] = new Attractor( int (random(25,600)), int (random(0,250)) );
}
}
void addAttractor()
{
attractors[NUM_ATTRACTORS] = new Attractor(mouseX,mouseY);
count();
}
void count()
{
NUM_ATTRACTORS=NUM_ATTRACTORS+1;
}
void drawAttractorPoints()
{
for (int i = 0; i < NUM_ATTRACTORS; i++)
{
if (mousePressed == true)
{
stroke(0,50);
}else{
stroke(255,50);
}
if (mouseX>(attractors[i].x-10) && mouseX<(attractors[i].x+10) && mouseY>(attractors[i].y-10) && mouseY<(attractors[i].y+10))
{
stroke(255,0,0);
}
attractors[i].spot();
}
for (int i = 0; i < NUM_NEGATTRACTORS; i++)
{
if (mousePressed == true)
{
stroke(255,50);
}else{
stroke(0,50);
}
if (mouseX>(negattractors[i].x-10) && mouseX<(negattractors[i].x+10) && mouseY>(negattractors[i].y-10) && mouseY<(negattractors[i].y+10))
{
stroke(255,0,0);
}
negattractors[i].spot();
}
}
Vector3D getAccel(float _x, float _y) //method of forces class to calculate the particles acceleration
{ //returns a vectors called pos
float d2 = 0;
float ax = 0;
float ay = 0;
for (int i = 0; i < NUM_ATTRACTORS; i++) //do these calcs for every attractor
{
d2 = sq(attractors[i].x-_x) + sq(attractors[i].y-_y); //calculates the distance between the given vector and the attractor/////this is wrong and way way higher than dist actually is
if (d2 > 0.1) //if that distance is greater than .1
{
if (mouseX>(attractors[i].x-10) && mouseX<(attractors[i].x+10) && mouseY>(attractors[i].y-10) && mouseY<(attractors[i].y+10))
{
}else{
if (mousePressed == true)
{
ax = ax - accel/2 * (attractors[i].x-_x) / d2;
ay = ay - accel/2 * (attractors[i].y-_y) / d2;
} else {
ax = ax + accel * (attractors[i].x-_x) / d2; //new vector is multiplied by //not 2
ay = ay + accel * (attractors[i].y-_y) / d2;
}
}
}
}
for (int i = 0; i < NUM_NEGATTRACTORS; i++) //do these calcs for every detractor
{
d2 = sq(negattractors[i].x-_x) + sq(negattractors[i].y-_y);
if (d2 > 0.1)
{
if (mouseX>(negattractors[i].x-10) && mouseX<(negattractors[i].x+10) && mouseY>(negattractors[i].y-10) && mouseY<(negattractors[i].y+10))
{
}else{
if (mousePressed == true)
{
ax = ax + accel * (negattractors[i].x-_x) / d2; //new vector is multiplied by //not 2
ay = ay + accel * (negattractors[i].y-_y) / d2;
} else {
ax = ax - accel/2 * (negattractors[i].x-_x) / d2;
ay = ay - accel/2 * (negattractors[i].y-_y) / d2;
}
}
}
}
Vector3D pos = new Vector3D(ax,ay); //new vector of acceleration
return pos;
}
}
class Attractor { //attractor is a class that holds a position and draws itself and thats all?
float x,y; //local variables are the x and y position
Attractor(float _x, float _y )
{
x = _x;
y = _y;
}
void spot() //method to draw itself
{
line(x-4, y, x+4, y);
line(x, y-4, x, y+4);
}
}
class Vector3D
{
float x; //global variable x position
float y; //global variable y position
float z; //global variable y position
Vector3D (float x_, float y_, float z_) //constructor for a 3D vector
{
x=x_; //sets x to input number x_
y=y_; //sets y to input number y_
z=z_; //sets y to input number z_
}
//constructor for a 2D vector
Vector3D (float x_, float y_) //if vector called with 2 inputs sets it to a vector
{
x=x_; //sets x to 0
y=y_; //sets y to 0
z=0; //sets z to 0
}
//constructor for an empty vector
Vector3D () //if vector called with no inputs sets it to a vector
{
x=0; //sets x to 0
y=0; //sets y to 0
z=0; //sets z to 0
}
//methods of vector class
//addition function
void add (Vector3D v) //this is a function that returns nothing (Void = no function return type)
{
x =v.x+x;
y =v.y+y;
z =v.z+z;
}
//subract function
void subtract(Vector3D v)
{
x =v.x-x;
y =v.y-y;
z =v.z-z;
}
//multiplication function //to divide just multiple with a number below one
void mult (float n)
{
x=x*n;
y=y*n;
z=z*n;
}
//distance funciton //calc distance between two vectors
float distance (Vector3D v)
{
float distance= sqrt (pow(v.x-x,2) + pow(v.y-y,2) + pow(v.z-z,2) );
return distance;
}
//magnitude function //calculating the length of the vector
float magnitude()
{
return (float) sqrt (pow(x,2) + pow(y,2) + pow(z,2) );//Calculate the magnitude (length) of the vector and return the magnitude of the vector
}
//set function values //change vector parameters without using another function //manual input
void set (float xx, float yy, float zz)
{
x=xx;
y=yy;
z=zz;
}
//set function values //change vector parameters without using another function // set with vectors values
void set (Vector3D v)
{
x=v.x;
y=v.y;
z=v.z;
}
}
class Particle {
float x,y; //declating global variables for the x and y position of the center of the particle
float r; //declaring global variable for the angle of rotation of the ellipse
float t=0; //declaringglobal variable t set to start at 0 for every particle
float xp; //declares a global variable xp set to start at 100 for every particle
float yp; //declares a global variable xp set to start at 100 for every particle
float sinTranslateCount=0; //creates global variable for every particle starting count at zero
float curveTranslateCount = 0; //creates global variable for every particle starting count at zero
color c=color(73,175,159,5); //colors original color
float colorT=0; //color t value starts at zero
color c1=color (73,175,159,5);
color c2=color (255,255,0,5);
color c3=color (255,5);
float w=1; //declaring global variable w for the width //our particle has a size
float h=1; //declaring global variable w for the width //our particle has a size
float accel;
float distance;
boolean d=false;
float startxx;
float startyy;
float endxx;
float endyy;
Vector3D pos =new Vector3D(0,0,0); /////////////////////////particles vector (used to be a)
Vector3D v =new Vector3D(0,0,0);//particles current vector
Particle(float X, float Y, float W, float H, float R) {//class constructor
x = 0;
y = random(height);
pos.x=X;
pos.y=Y;
w=W; //translating global values in local variables
h=H; //translating global values in local variables
r=R; //translating global values in local variables
}
//check to see if particle is w/in certain dist of attractors
void checkDistance(int count)
{
stroke(c1); //sets the stroke to white green
if (mousePressed == true)
{
for (int j = 0; j < NUM_NEGATTRACTORS; j++) //do these calcs for every attractor
{
distance = sqrt( sq(negattractors[j].x-x) + sq(negattractors[j].y-y));
if (distance<50)
{
stroke(lerpColor(c1,c3,distance/50)); //sets the stroke to white green
}
}
}else{
for (int i = 0; i < NUM_ATTRACTORS; i++) //do these calcs for every attractor
{
distance = sqrt( sq(attractors[i].x-x) + sq(attractors[i].y-y));
if (distance<100)
{
stroke(lerpColor(c1,c2,distance/100)); //sets the stroke to white green
}
}
}
if (key == CODED) {
if (keyCode == DOWN) {
//if (keyPressed == true)
{
if (distance>50)
{
w=distance*2;
h=distance*2;
//inflate(1.1,1.1);
drawEllipse();
}
}
}
}
line(startxx, startyy, endxx, endyy);
}
void step() /////this is where it moves a certain amount based on the acceleration from forcefield.getAccel
{
pos = forcefield.getAccel(x,y); //gets the acceleration vector from forcefield
float xstart = x; //position first
float ystart = y;
x += pos.x; //adding acceleration vector
y += pos.y;
float xend = x; //new position
float yend = y;
endxx=xend;
endyy=yend;
startxx=xstart;
startyy=ystart;
stroke(0,0,200,1);//really light black
point (x,y);
}
void inflate(float rateX, float rateY) //creates a function called inflate that takes two parameters
{
w=w*rateX; //resets the width of a particle to the previous width multiplied by a given rate
h=h*rateY; //resets the height of a particle to the previous width multiplied by a given rate
}
void drawEllipse()
{
float s=100.0/((w+h)/4);
for (float t=0; t<=360; t=t+s) //sets a loop that calculates every third x and y positions of an ellipse all the way around
{
float a=endxx+(w/5)*cos(radians(t))* cos(radians(r))-h/2*sin(radians(t))*sin(radians(r)); //figures out the position of the x coord on at ellipse at a gven location with a given height width and rotation
float b=endyy+(h/5)*sin(radians(t))* cos(radians(r))+w/2*cos(radians(t))*sin(radians(r)); //figures out the position of the y coord on at ellipse at a gven location with a given height width and rotation
stroke(50 ,255/(distance/2));
point(a,b); //draws a point at location a,b
}
}
}
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.
