Skip to content

Instantly share code, notes, and snippets.

@FreedomGrenade
Created April 13, 2015 05:17
Show Gist options
  • Save FreedomGrenade/5deb01c1a957e3005a73 to your computer and use it in GitHub Desktop.
Save FreedomGrenade/5deb01c1a957e3005a73 to your computer and use it in GitHub Desktop.
Each pixel represents the starting point of two particles, one particle is attracted to all the Orange dots at the beginning, the other is attracted to the centre of mass of the dots. Colour is based on the distance between the two particles over time.
public float G = 0.02;
int[] colMap;
Puller pullThing;
Cell[][] cells;
int hCells, wCells;
float cellWidth, cellHeight;
public void setup() {
size(500, 500);
pullThing = new Puller();
wCells = 250;
hCells = 250;
cellWidth = (float)width/wCells;
cellHeight = (float)height/hCells;
colorMode(HSB, 1.0, 1.0, 1.0, 1.0);
colMap = new int[1000]; // better than plain greyscale
for (int i = 0; i < 1000; i++) {
float i0 = sqrt((float)i/1000);
float h = ((constrain(i0, 0.0, 5.0/6.0)+1.0/3.0)%1.0);
float s = constrain(map(i0, 5.0/6.0, 1.0, 1.0, 0.0), 0.0, 1.0);
float b = constrain(map((i0), 1.0/3.0, 2.0/3.0, 0, 1), 0, 1);
colMap[i] = color(h, s, b);
}
int maxP = 20;
for (int i = 0; i <= maxP; i++) { // set the pullers (x pos, y pos, mass)
float iFloat = (float)i/maxP;
//pullThing.addMass(cos(iFloat*TWO_PI)*300 + width*0.5, sin(iFloat*TWO_PI)*200+height*0.5, 10);
pullThing.addMass(random(width), random(height), random(100));
//pullThing.addMass(iFloat*width, sin(iFloat*TWO_PI)*200+height*0.5, 10);
}
cells = new Cell[wCells][hCells];
for (int y = 0; y < hCells; y++) {
for (int x = 0; x < wCells; x++) { // (x pos (centered), y pos (centered), initial velocity x, iv y, mass)
cells[x][y] = new Cell((x+0.5)*cellWidth, (y+0.5)*cellHeight, 0, 0, 1);
}
}
}
public void mousePressed() {
println(frameCount);
}
public void draw() {
background(0);
noStroke();
for (int y = 0; y < hCells; y++) {
for (int x = 0; x < wCells; x++) {
Cell curCell = cells[x][y];
curCell.update(pullThing);
int i = (int)constrain(curCell.getDist()*5, 0, colMap.length-1);
fill(colMap[i]);
rect(x*cellWidth, y*cellHeight, cellWidth+1, cellHeight+1);
}
}
}
public class Cell { // particle group
XY one, multi;
public Cell (float x, float y, float xv, float yv, float m) {
one = new XY(x, y, xv, yv, m);
multi = new XY(x, y, xv, yv, m);
}
public void update(Puller p) {
p.forceFromCentre(one);
one.update();
p.forceFromAll(multi);
multi.update();
}
public void display() {
stroke(255, 0, 0);
line(one.pos.x, one.pos.y, multi.pos.x, multi.pos.y);
}
public float getDist() {
return one.distance(multi);
}
}
public class XY { // single 'particle'
PVector pos;
PVector vel;
PVector acc;
float invmass;
public XY(float x, float y, float xv, float yv, float m) {
pos = new PVector(x, y);
vel = new PVector(xv, yv);
acc = new PVector();
invmass = 1.0/m;
}
public void update() {
vel.add(acc);
vel.limit(1);
pos.add(vel);
acc.set(0, 0);
}
public float distance(XY other) {
return dist(pos.x, pos.y, other.pos.x, other.pos.y);
}
}
public class Puller {
ArrayList<PVector> masses; // Using x,y as normal, z as the mass
PVector centre;
PVector fCalc;
public Puller() {
masses = new ArrayList<PVector>();
fCalc = new PVector();
}
public void addMass(float x, float y, float m) {
PVector mass = new PVector(x, y, m);
addMass(mass);
}
public void addMass(PVector mass) {
masses.add(mass);
if (centre == null) {
centre = mass.get();
return;
}
float newPosMult = 1.0 / (centre.z / mass.z + 1); // distance that the CM moves to the new mass
centre.x+= (mass.x - centre.x) * newPosMult;
centre.y+= (mass.y - centre.y) * newPosMult;
centre.z+=mass.z;
}
public void recalc() {
centre = null;
if (masses.size() != 0) {
for (PVector m : masses) addMass(m);
}
}
public void display() {
if (masses.size() != 0) {
noStroke();
fill(#FF7F00);
for (PVector m : masses) {
ellipse(m.x, m.y, 10, 10);
}
strokeWeight(2);
stroke(#CCCCEE);
ellipse(centre.x, centre.y, 10, 10);
}
}
public void addXYacc(PVector pullMass, XY xy) { //
fCalc.set(pullMass.x - xy.pos.x, pullMass.y - xy.pos.y);
float dSq = fCalc.magSq();
fCalc.normalize();
fCalc.mult(G*pullMass.z/max(dSq, 1)); // F = Gm1m2/rr
xy.acc.add(fCalc);
}
public void forceFromCentre(XY point) {
if (centre != null) addXYacc(centre, point);
}
public void forceFromAll(XY point) {
if (masses.size() > 0)
for (PVector m : masses) addXYacc(m, point);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment