I am making a circle to circle collision detection program. I can get the balls to move around but when the collision is detected, the balls are quite far overlapped. Any suggestions? Thanks in advance!
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.lang.Math;
public class ShapePanel extends JPanel{
  private JButton button, startButton, stopButton;
  private JTextField textField;
  private JLabel label;
  private Timer timer;
  private final int DELAY = 10;
  ArrayList<Shape> obj = new ArrayList<Shape>();
  public static void main(String[] args){
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new ShapePanel());
    frame.pack();
    frame.setVisible(true);
  }
  public ShapePanel(){
    JPanel controlPanel = new JPanel();
    DrawingPanel dpanel = new DrawingPanel();
    controlPanel.setPreferredSize(new Dimension(100,400));
    button = new JButton("Add Shape");
    startButton = new JButton("Start");
    stopButton = new JButton("Stop");
    textField = new JTextField(2);
    label = new JLabel("Count:");
    controlPanel.add(button);
    controlPanel.add(label);
    controlPanel.add(textField);
    controlPanel.add(startButton);
    controlPanel.add(stopButton);
    add(controlPanel);
    add(dpanel);
    ButtonListener bListen = new ButtonListener();
    button.addActionListener(bListen);
    startButton.addActionListener(bListen);
    stopButton.addActionListener(bListen);
    timer = new Timer(DELAY, bListen);
  }
  private class ButtonListener implements ActionListener{
    public void actionPerformed(ActionEvent e){
      if (e.getSource() == button){
        obj.add(new Shape());
        if (obj.get(obj.size()-1).y > 200){
          obj.get(obj.size()-1).moveY = -obj.get(obj.size()-1).moveY;
        }
      }else if (e.getSource() == timer){
        for (int i = 0; i < obj.size(); i++){
          obj.get(i).move();
        }
        for (int i = 0; i < obj.size(); i++){
          for (int j = i + 1; j < obj.size(); j++){
            if (Math.sqrt(Math.pow((double)obj.get(i).centerCoordX - (double)obj.get(j).centerCoordX,2)) + 
                Math.pow((double)obj.get(i).centerCoordY - (double)obj.get(j).centerCoordY,2) <= obj.get(i).radius + obj.get(j).radius){
              timer.stop();
            }
          }
        }
      }else if (e.getSource() == startButton){
        timer.start();
      }else if (e.getSource() == stopButton){
        timer.stop();
      }
      repaint();
    }
  }
  private class DrawingPanel extends JPanel{
    DrawingPanel(){
      setPreferredSize(new Dimension(400,400));
      setBackground(Color.pink);
    }
    public void paintComponent(Graphics g){
      super.paintComponent(g);
      for(int i = 0; i < obj.size(); i++){
        obj.get(i).display(g);
      }
    }
  }
}
import java.awt.*;
import java.util.*;
public class Shape{
  public int x, y, width, height, moveX = 1, moveY = 1, centerCoordX, centerCoordY, radius;
  private Color colour;
  public boolean reverse = false, sameDirection = true;
  Random generator = new Random();
  public int randomRange(int lo, int hi){
    return generator.nextInt(hi-lo)+lo;
  }
  Shape(){
    width = randomRange(30, 50);
    if (width % 2 != 0){
      width = randomRange(30, 50);
    }
    height = width;
    radius = width/2;
    x = randomRange(0, 400-width);
    y = randomRange(0, 400-height);
    colour = new Color(generator.nextInt(256),generator.nextInt(256),generator.nextInt(256));
  }
  public void display(Graphics g){
    g.setColor(colour);
    g.fillOval(x, y, width, height);
  }
  void move(){
    x += moveX;
    y += moveY;
    centerCoordX = x + width/2;
    centerCoordY = y + height/2;
    if(x >= 400-width){
      moveX = -moveX;
    }if(x <= 0){
      moveX = -moveX;
    }if(y >= 400-height){
      moveY = -moveY;
    }if (y <= 0){
      moveY = -moveY;
    }
  }
}
 
     
     
     
     
    