ArrayList<Body> objects = new ArrayList<Body>(100);
ArrayList<Body> destroy = new ArrayList<Body>();
float m1 = 0.5;
float m2 = 1;
float G = 0.00002;
int maxDist = 1;
float scale = 1;
PVector mouse = new PVector(0, 0);
PVector midPos;
PVector startPos;
boolean hasBeenDragged;
boolean paused;
boolean wasCreated;
boolean C_pressed;
PVector ObjectDir = new PVector(0, 0);
ArrayList<PVector> points = new ArrayList<PVector>();
ArrayList<Body> Copy;
void setup() {
size(1000, 1000);
midPos = new PVector(0, 0);
startPos = new PVector(width / 2, height / 2);
//fullScreen();
/*for (int i = 0; i < 10; i++) {
objects.add(new Body(new PVector(random(-width / 2, width / 2), random(-height / 2, height / 2)), random(50, 80)));
objects.get(i).applyForce(PVector.random2D().setMag(random(10)));
}
for (int i = 0; i < 10; i++) {
objects.add(new Body(new PVector(random(-width / 2, width / 2), random(-height / 2, height / 2)), random(10)));
objects.get(i).applyForce(PVector.random2D().setMag(random(0.8)));
}*/
frameRate(80);
}
void draw() {
background(0);
stroke(255, 50);
points = new ArrayList<PVector>();
Copy = CopyArray(objects);
if (keyPressed && key == 'c') {
strokeWeight(7);
line(ObjectDir.x, ObjectDir.y, mouseX, mouseY);
/*PVector ObjectDirCopy = ObjectDir.copy();
ObjectDirCopy = ObjectDirCopy.sub(mouseX, mouseY);
ObjectDirCopy = ObjectDirCopy.div(80 * scale);
Copy.add(new Body(new PVector((mouseX - width / 2) / scale - midPos.x, (mouseY - height / 2) / scale - midPos.y), m2));
Copy.get(Copy.size() - 1).applyForce(ObjectDirCopy);
Copy.get(Copy.size() - 1).createPreview = true;
for (int i = 0; i < 1; i++) {
for (Body b : Copy) {
b.update(); This update() is updating the original body in objects array
if (b.createPreview) {
points.add(new PVector(b.pos.x, b.pos.y));
}
}
}*/
}
translate(width / 2, height / 2);
scale(scale);
translate(mouse.x + midPos.x, mouse.y + midPos.y);
destroy = new ArrayList<Body>();
for (PVector p : points) {
strokeWeight(1 / scale);
stroke(255);
point(p.x, p.y);
//println(p);
}
for (Body b : objects) {
b.show();
}
if (!paused) {
for (Body b : objects) {
b.update();
}
}
if (!paused) {
for (Body b1 : objects) {
for (Body b2 : objects) {
if (b1 != b2) {
float r = dist(b1.pos.x, b1.pos.y, b2.pos.x, b2.pos.y);
if (r < (b1.radius + b2.radius)) {
destroy.add(b1);
destroy.add(b2);
}
PVector p1 = new PVector(b2.pos.x, b2.pos.y);
PVector p2 = new PVector(b1.pos.x, b1.pos.y);
p1 = p1.sub(b1.pos);
p2 = p2.sub(b2.pos);
float a = G * ((b1.m * b2.m) / (r * r));
b1.applyForce(p1.mult(a).mult(1));
b2.applyForce(p2.mult(a).mult(1));
//stroke(map(r, 0, 500, 255, 0));
stroke(255, 50);
//line(b1.pos.x, b1.pos.y, b2.pos.x, b2.pos.y);
}
}
}
}
for (Body b1 : destroy) {
for (Body b2 : destroy) {
float dist = dist(b1.pos.x, b1.pos.y, b2.pos.x, b2.pos.y);
if (dist < b1.radius + b2.radius && dist > 0) {
if (b1.m >= b2.m) {
objects.remove(b2);
b1.m += b2.m;
b1.vel = b1.vel.mult(0.8);
} else {
objects.remove(b1);
b2.m += b1.m;
b2.vel = b2.vel.mult(0.8);
}
}
}
}
}
void mousePressed() {
startPos = new PVector(mouseX, mouseY);
}
void mouseWheel(MouseEvent e) {
float mv = e.getCount();
if (scale > 0.5) {
if (mv < 0) {
scale -= scale / 2;
}
}
if (mv > 0) {
scale += scale / 2;
}
}
void mouseDragged() {
if (mouseButton == LEFT) {
mouse = new PVector((mouseX - startPos.x) / scale, (mouseY - startPos.y) / scale);
hasBeenDragged = true;
}
}
void mouseReleased() {
midPos = midPos.add(mouse.copy());
mouse = new PVector(0, 0);
if (mouseButton == LEFT && !hasBeenDragged) {
objects.add(new Body(new PVector((mouseX - width / 2) / scale - midPos.x, (mouseY - height / 2) / scale - midPos.y), m1));
} else if (!hasBeenDragged) {
objects.add(new Body(new PVector((mouseX - width / 2) / scale - midPos.x, (mouseY - height / 2) / scale - midPos.y), m2));
}
hasBeenDragged = false;
}
void keyPressed() {
if (key == 'd') {
objects = new ArrayList<Body>();
} else if (key == 'p') {
paused = paused? false : true;
} else if (key == 'c' && !C_pressed) {
C_pressed = true;
ObjectDir = new PVector(mouseX, mouseY);
}
}
void mouseMoved() {
}
void keyReleased() {
if (C_pressed) {
if (key == 'c' && !wasCreated) {
wasCreated = true;
ObjectDir = ObjectDir.sub(mouseX, mouseY);
ObjectDir = ObjectDir.div(80 * scale);
objects.add(new Body(new PVector((mouseX - width / 2) / scale - midPos.x, (mouseY - height / 2) / scale - midPos.y), m2));
objects.get(objects.size() - 1).applyForce(ObjectDir);
}
for(Body b : objects){
b.createPreview = false;
}
}
wasCreated = false;
C_pressed = false;
}
ArrayList<Body> DoGravity(ArrayList<Body> b_in) {
ArrayList<Body> result = new ArrayList<Body>();
for (Body b1 : b_in) {
for (Body b2 : b_in) {
if (b1 != b2) {
float r = dist(b1.pos.x, b1.pos.y, b2.pos.x, b2.pos.y);
if (r < (b1.radius + b2.radius)) {
destroy.add(b1);
destroy.add(b2);
}
PVector p1 = new PVector(b2.pos.x, b2.pos.y);
PVector p2 = new PVector(b1.pos.x, b1.pos.y);
p1 = p1.sub(b1.pos);
p2 = p2.sub(b2.pos);
float a = G * ((b1.m * b2.m) / (r * r));
b1.applyForce(p1.mult(a).mult(1));
b2.applyForce(p2.mult(a).mult(1));
}
}
}
result = b_in;
return result;
}
ArrayList<Body> CopyArray(ArrayList<Body> b){
ArrayList<Body> result = new ArrayList<Body>();
for(Body b1 : b){
Body o = b1.copy();
result.add(o);
}
return result;
}
class Body {
PVector pos;
PVector vel = new PVector(0, 0);
PVector acc = new PVector(0, 0);
float m;
float radius = 0;
boolean createPreview;
Body(PVector pos_, float m_) {
pos = pos_;
m = m_;
}
void update() {
vel = vel.add(acc.div(m));
vel.limit(5);
acc = new PVector(0, 0);
pos = pos.add(vel);
vel.mult(1);
if (m > 300) {
m -= map(m, 0, 300, 0, 0.1);
}
}
void applyForce(PVector acc_) {
acc.add(acc_);
}
void show() {
radius = min(m / 20, 30);
stroke(255);
noFill();
strokeWeight(radius * 2);
point(pos.x, pos.y);
//line(pos.x, pos.y, vel.x * 20 + pos.x, vel.y * 20 + pos.y);
}
Body copy() {
Body b = new Body(this.pos, this.m);
b.vel = this.vel;
b.acc = this.acc;
return b;
}
}