public void draw(Graphics g) {
    animate();

    g.setColor(Color.black);
    g.fillRect(0, 0, dim.width, dim.height);
    g.setColor(Color.white);

    numpaint++;
    DebugPrinter dbg = new DebugPrinter(g, 50, 60);
    dbg.print(
        "Spring-mass demo by yigal irani, drag balls or create new ones by clicking inside box");
    dbg.print("frame", numpaint);
    dbg.print("fps", 1 / timer.time_diff);

    Point top_left = point_by_vec(new Vec(-1, 1));
    g.draw3DRect(top_left.x, top_left.y, screen_dist(2), screen_dist(2), true);
    for (int i = 0; i < springs.size(); i++) {
      Spring spring = springs.get2(i);
      Point p1 = point_by_vec(balls.get2(spring.start).pos);
      Point p2 = point_by_vec(balls.get2(spring.end).pos);
      g.drawLine(p1.x, p1.y, p2.x, p2.y);
    }
    for (int i = 0; i < balls.size(); i++) {
      Ball ball = balls.get2(i);
      Point p = point_by_vec(ball.pos);
      int screen_radius = screen_dist(RADIUS);
      g.setColor(Color.blue);
      g.fillOval(p.x - screen_radius, p.y - screen_radius, screen_radius * 2, screen_radius * 2);

      g.setColor(Color.white);
      g.drawOval(p.x - screen_radius, p.y - screen_radius, screen_radius * 2, screen_radius * 2);

      g.drawString("" + i, p.x, p.y);
    }
  }
  void the_derive(double time, double y[], double dy[]) {
    int i;
    BallVector balls = decode_balls(y); // new BallVector();//Ball[num_balls];
    BallVector dballs = new BallVector(); // new Ball[num_balls];

    for (i = 0; i < num_balls; i++) {
      Ball p = balls.get2(i);
      Ball d = new Ball();
      d.pos = p.speed;
      d.speed = wall_power(p);
      d.speed.y -= 1; // gravity
      dballs.add(d);
    }

    for (i = 0; i < num_balls; i++)
      for (int j = i + 1; j < num_balls; j++) {
        Ball p1 = balls.get2(i);
        Ball p2 = balls.get2(j);
        if (far_away_fast_calc(p1.pos, p2.pos, radius * 2)) continue;
        double dist = p1.pos.calc_dist(p2.pos);
        // if (dist>radius*2)
        //	continue;

        Vec collide_power = calc_collide_power(p1, p2, dist);
        dballs.get2(i).speed.add_to(collide_power);
        dballs.get2(j).speed.sub_to(collide_power);
      }
    for (i = 0; i < springs.size(); i++) {
      Spring s = springs.get2(i);
      Vec collide_power = calc_spring_power(balls.get2(s.start), balls.get2(s.end));
      dballs.get2(s.start).speed.add_to(collide_power);
      dballs.get2(s.end).speed.sub_to(collide_power);
    }
    encode_balls(dballs, dy);
  };
 void add_spring(int start, int end) {
   Spring s = new Spring();
   s.start = start;
   s.end = end;
   springs.add(s);
 }