Particles, thanks to Daniel Shiffman of Processing fame, aren’t so scary after all. I adapted one of the sketches from his Nature of Code book and applied it to my existing framework. That’s jumping ahead of myself slightly, firstly I created small particle clouds in the general locations of the taste bud locations in my earlier sketch.

IMG_8024

Apologies for the horrendous quality, I didn’t expect to move on from this sketch as quickly as I did, so did not make a screen recording to do it justice. This is the main particle class –

class Particle{
/*
PVector is a class in Processing that makes it easier to store
values, and make calculations based on these values. It can make
applying forces to objects much easier and more efficient!
*/
PVector loc; //location vector
PVector vel; //velocity vector
PVector acc; //acceleration vector
float sz; //size of particle
float gravity; //gravity variable
float mass; //mass variable
int velocityLimit = 5; //the maximum velocity a particle can travel at
float d; //distance variable between particle and the target co-ordinates
float x;
float y;
color colour;

//CONSTRUCTOR
Particle(PVector _loc, float _sz, float _gravity, float _mass, float _x, float _y){
loc = _loc.get(); //when calling loc, return current location of the selected particle
vel = new PVector(0, 0); //set vel and acc vectors to 0 as default
acc = new PVector(0, 0);
sz = _sz;
gravity = _gravity;
mass = _mass;
x = _x;
y = _y;
}

//method to render the particle. control how it looks here!
void display(){
float theta = vel.heading2D() + radians(90);
fill(255);
stroke(colour);
pushMatrix();
translate(loc.x, loc.y);
rotate(theta);
beginShape(TRIANGLES);
vertex(0, -sz*2);
vertex(-sz, sz*2);
vertex(sz, sz*2);
endShape();
popMatrix();

// ellipseMode(CENTER);
// fill(colour);
// ellipse(loc.x, loc.y, sz, sz);
}

//math for attraction and repulsion forces
//tx and ty are the co-ordinates attraction/repulsion will be applied to
void forces(float tx, float ty){
PVector targetLoc = new PVector(tx, ty); //creating new vector for attractive/repulsive x and y values
PVector dir = PVector.sub(loc, targetLoc); //calculate the direction between a particle and targetLoc
d = dir.mag(); //calculate how far away the particle is from targetLoc
dir.normalize(); //convert the measurement to a unit vector

//calculate the strength of the force by factoring in a gravitational constant and the mass of a particle
//multiply by distance^2
float force = (gravity*mass) / (d*d);

//if the mouse is pressed, turn on repulsion by multiplying direction by 1
if(keyPressed){
dir.mult(1);
}
//else multiply the direction by -1 to switch the direction the particle travels in (attraction)
else{
dir.mult(-1);
}

//apply directional vector
applyForce(dir);
}

//method to apply a force vector to the particle
void applyForce(PVector force){
force.div(mass);
acc.add(force);
}

//method to update the location of the particle, and keep its velocity within a set limit
void update(){
vel.add(acc);
vel.limit(velocityLimit);
loc.add(vel);
acc.mult(0);
}

//method to bounce particles of canvas edges
void bounds(){
if(loc.y > height || loc.y < 0){ vel.y *= -1; } if(loc.x > width || loc.x < 0){ vel.x *= -1; } } //main method that combines all previous methods, and takes two arguments //tx and ty are inherited from forces(), and set the attractive/repulsive co-ords void run(float tx, float ty){ forces(tx, ty); display(); bounds(); update(); } }

Here, we declare the location, velocity and acceleration for each single particle, as well as its velocity, acceleration, size and position. I've worked through this example code to at least completely comprehend some of the mathematics involved, but it's been difficult - i'm very glad i'm not creating my own physics engine, but I did create the particle shape as a triangle. For now, this seems like a good particle shape. Within the forces() method, there's a means to change the direction of gravity upon keypress, meaning we could repel the particles too - this will be very useful.

For each flavour (sweet, salty etc) i've defined a location on the screen and a colour, as well as how many particles are to be initiated within a function that returns an ArrayList of the generated particles;

ArrayList flavourFlockInit(float d, ArrayList flav, float prevalence, float left, float top, float w, float h, color colour) {

flav = new ArrayList();

for (int i = 0; i < prevalence; i++) { flav.add(new Vehicle(d, left, top, w, h, colour)); } return flav; }

The function is initiated in void setup();

bitter = flavourFlockInit(0.6, width/2, height/6);

And deployed in the draw() function;

for (Particle b : bitter) {
b.colour = bitterColour;
b.run(b.x, b.y);
}

As above, you can see it works quite well. I'm going to implement this with my database data shortly, ee!