# Problems with gravity simulation

**URL:** https://discourse.processing.org/t/problems-with-gravity-simulation/20349
**Category:** Coding Questions
**Created:** [May 1, 2020, 2:40pm UTC](https://discourse.processing.org/t/problems-with-gravity-simulation/20349 "2020-05-01T14:40:43Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Kport1](https://avatars.discourse-cdn.com/v4/letter/k/278dde/32.png) [@Kport1](https://discourse.processing.org/u/Kport1)
#### Post date: [May 1, 2020, 2:40pm UTC](https://discourse.processing.org/t/problems-with-gravity-simulation/20349/1 "2020-05-01T14:40:43Z")

</div>

```auto

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;
} 

```

```auto
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;
  }
}

```

---

<div class="post-metadata">

### Author: ![Kport1](https://avatars.discourse-cdn.com/v4/letter/k/278dde/32.png) [@Kport1](https://discourse.processing.org/u/Kport1)
#### Post date: [May 1, 2020, 2:43pm UTC](https://discourse.processing.org/t/problems-with-gravity-simulation/20349/2 "2020-05-01T14:43:16Z")

</div>

I marked the spot in the code, that creates the problem. There is an update() which not only updates the bodys in the copy, but also the original.

---

<div class="post-metadata">

### Author: ![Schred](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/schred/32/13146_2.png) [@Schred](https://discourse.processing.org/u/Schred)
#### Post date: [May 1, 2020, 4:00pm UTC](https://discourse.processing.org/t/problems-with-gravity-simulation/20349/3 "2020-05-01T16:00:09Z")

</div>

Please consider breaking this code down to a [minimal reproducable example](https://stackoverflow.com/help/minimal-reproducible-example) and explaining what exactly the problem is. That way we will be much more likely to be able to help you out. 😉

---

<div class="post-metadata">

### Author: ![Kport1](https://avatars.discourse-cdn.com/v4/letter/k/278dde/32.png) [@Kport1](https://discourse.processing.org/u/Kport1)
#### Post date: [May 1, 2020, 5:46pm UTC](https://discourse.processing.org/t/problems-with-gravity-simulation/20349/4 "2020-05-01T17:46:22Z")

</div>

Im trying to create a preview of a path a body will take if created with a specific velocity and position.  
So im trying to copy an array of these bodys to do the simulation. but if i do update() on the body in the copied array it updates the one in the original array. If you run the code and uncomment the part at the top, when pressing c the other bodys will speed up

---

<div class="post-metadata">

### Author: ![Schred](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/schred/32/13146_2.png) [@Schred](https://discourse.processing.org/u/Schred)
#### Post date: [May 1, 2020, 5:53pm UTC](https://discourse.processing.org/t/problems-with-gravity-simulation/20349/5 "2020-05-01T17:53:35Z")

</div>

Your `copy` method doesn’t do what you want it to do. It creates a new instance of `Body`, which is good, but it doesn’t copy the fields of the original body, meaning you just pass reference to the same objects.

To fix this, change your `Body#copy` method to:

```auto
Body copy() {
  Body b = new Body(this.pos.copy(), this.m);
  b.vel = this.vel.copy();
  b.acc = this.acc.copy();
  return b;
}

```
