Reputation: 133
I'm making an java app (for exercise) where there must be a panel and 2 buttons.
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?
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
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