Pacheko
Pacheko

Reputation: 133

Change ball color when colliding

I'm making an java app (for exercise) where there must be a panel and 2 buttons.

  1. Each time you press the start button a ball must be displayed and it moves based on thread. The user can display all the way up to 10 independent balls.
  2. By pressing the stop button, 1 ball must be removed with each time the stop button is pressed (example, when there is 4 balls, the user must press 4 times stop button to remove all the balls independently)
  3. All the x- and y coordinates of the balls must be stored in a Matrix
  4. When 1 or more ball(s) are colliding with each other, only the colliding balls must change color from red to blue

Ok I'm almost done with it completely ( from point 1 to 4 ), but here comes my problem. When a ball is colliding with another, instead of changing the colors of the colliding balls to blue, my code is changing all the balls color from red to blue. I know that my error lies at the new Balls().setColor(Color.Blue), but I have no idea how to change only the colliding balls.

Below follows a screen shot of the java app and the code. Can anyone help me with this headache?

Printscreen: enter image description here

source code:

import java.awt.Color;             
import java.awt.Dimension;    
import java.awt.FlowLayout;   
import java.awt.Graphics;    
import java.awt.event.ActionEvent;   
import java.awt.event.ActionListener;   
import java.util.ArrayList;  
import java.util.List;  
import javax.swing.JButton;    
import javax.swing.JFrame;    
import javax.swing.JLabel;  
import javax.swing.JPanel;`


public class BouncingBalls extends JPanel implements ActionListener {

protected List<Ball> balls = new ArrayList<Ball>(10);
private final Container container;
private final DrawCanvas canvas;
private  int canvasWidth;
private  int canvasHeight;
public JButton start, stop;
int [][] coords= new int[11][2];
int ammountOfBalls = 0;
static Color clr= Color.RED;


public static int random(int maxRange) {
    return (int) Math.round((Math.random() * maxRange));
}

public BouncingBalls(int width, int height) {
    setLayout(new FlowLayout());
     start= new JButton("start");
    start.addActionListener(this);
     stop= new JButton("stop");
    stop.addActionListener(this);
    add(start);
    add(stop);
    add(new JLabel(""));
    container = new Container();
    canvasWidth = width;
    canvasHeight = height;
    canvas = new DrawCanvas();
    this.setLayout(new FlowLayout());
    this.add(canvas);
    start();

}

public void start() {

    Thread t = new Thread() {
        @Override
        public void run() {

            while (true) {

                update();
                getPositions();
                collisionDetection();
                repaint();
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                }
            }
        }

        private void collisionDetection() {
            // The algorithm  that detects collision
          for(int i=0;i<ammountOfBalls;i++){
            for(int j=i+1; j<ammountOfBalls; j++){
                  if(collisionMethod(i,j)){  // my collision method
                      //HOW DO I CHANGE ONLY THE COLLIDING BALLS COLOR HERE????
                     new Ball().setColor(Color.BLUE);  // this line here changes the color of all the balls on the panel
                      System.out.println("Its a hit");
                  }
              }

           }  

        }

        private void getPositions() {
            int row=0;
            for (Ball ball : balls) {
             int x =ball.getXPosition();
             int y =ball.getYPosition();
             coords[row][0]=x;
             coords[row][1]=y;
             row++;
            }

        }

        private boolean collisionMethod(int i, int j) {
           float xd = coords[i][0]-coords[j][0];
           float yd=coords[i][1]-coords[j][1];
           float radius= new Ball().ballRadius;
           float sqrRadius= radius * radius;
           float distSqr= (xd * xd) + (yd * yd);

           if(distSqr <= sqrRadius)
               return true;

            return false;
        }
      };
    t.start();
}

public void update() {
    for (Ball ball : balls) {
        ball.move(container);
    }
 }

@Override
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == start){
        if(ammountOfBalls < 10){
            // to limit the ammount of balls to 10
            balls.add(new Ball());
            ammountOfBalls++;
       }
    }

    else if( e.getSource() == stop){
        if(ammountOfBalls > 0){
      ammountOfBalls --;
      balls.remove(ammountOfBalls);

    }

    }
}

class DrawCanvas extends JPanel {

    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        container.draw(g);
        for (Ball ball : balls) {
            ball.draw(g);
        }
    }
    @Override
    public Dimension getPreferredSize() {
        return (new Dimension(700, 400));
    }
}

public static void main(String[] args) {
            JFrame f = new JFrame("Bouncing Balls");
            f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
            f.setPreferredSize(new Dimension(800,500));
            f.setContentPane(new BouncingBalls(800,800));
            f.pack();
            f.setVisible(true);
    }


public static class Ball {

    public int random(int maxRange) {
        return (int) Math.round(Math.random() * maxRange);
    }

int x = random(700); // method to get random coords for the x-value
int y = random(400); // method to get random coords for the y-value  ...... these are used to get random positions for the balls instead of only static
int xMovement = 10;
int yMovement = 10;
int ballRadius = 20;
int i = 0;


public Color getColor(){
  return clr;
}
public Color setColor(Color color){
clr=color;
return clr;
}
    public void draw(Graphics g) {
        g.setColor(getColor());
        g.fillOval(x,y,ballRadius,ballRadius);

    }
    public int getXPosition(){
        return x;
    }
    public int getYPosition(){
        return y;
    }

    public void move(Container container) {
        x += xMovement;
        y += yMovement;

        if (x - ballRadius < 0) {
            xMovement = -xMovement;
            x = ballRadius;
        } 
        else if (x + ballRadius > 700) {
            xMovement = -xMovement;
            x = 700 - ballRadius;
        }

        if (y - ballRadius < 0) {
            yMovement = -yMovement;
            y = ballRadius;
        } 
        else if (y + ballRadius > 400) {
            yMovement = -yMovement;
            y = 400 - ballRadius;
        }
    }
}



public static class Container {
    private static final int hightPanel = 800;
    private static final int widthPanel=  800;

    public void draw(Graphics g) {
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, widthPanel, hightPanel);
    }
}
}

`

Upvotes: 1

Views: 1584

Answers (1)

dcsohl
dcsohl

Reputation: 7406

You have defined clr as a static field of your application. When your Ball class calls setColor() you are changing the value of clr to blue... and then any Ball that calls getColor() will see that clr is blue.

Solution: Don't make clr an application-wide static field. Define it in the Ball class as a non-static field, so each Ball has its own color.

Upvotes: 5

Related Questions