Смещение при добавлении компонента на панель - Java
Формулировка задачи:
Доброго времени суток.
Реализуя анимация соударения множества шаров друг о друга наткнулся на одну проблему:
Шары - экземпляры класса Ellipse2D, отрисовываю внутри класса Ball расширяющего JPanel. Получается что для каждого изображения шара - своя панель. Размеры панели соответствуют размерам шара. Проблема в том, что хоть размеры шара и панели его содержащей одинаковы, их центры не совпадают. Это становится заметно при обработке столкновений шаров: в одном случае они отскакивают от стены и друг друга даже не коснувшись, в другом сперва "срастаются" о потом происходит реакция на столкновение. Кто может знать в чем проблема - подскажите пожалуйста или скиньте ссылку где можно подробно об этом узнать. Ниже привожу код:
Класс шаров:
Класс фрейма:
Класс - точка входа в программу:
package simple9PG;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
public class Ball extends JComponent {
private static ArrayList<Ball> balls = new ArrayList<>();
//проверяем столкновение шаров друг с другом и границами фрейма, и перемещаем их.
static void moveAndDetection(JFrame frame) {
for (int i = 0; i < balls.size(); i++) {
//проверим столкновение с границами фрейма
Ball ball = balls.get(i);
if (ball.getX() + ball.speedX + ball.radius > frame.getWidth()) {
ball.speedX *= -1;
} else if (ball.getX() + ball.speedX - ball.radius < 0) {
ball.speedX *= -1;
}
if (ball.getY() + ball.speedY + ball.radius > frame.getHeight()) {
ball.speedY *= -1;
} else if (ball.getY() + ball.speedY - ball.radius < 0) {
ball.speedY *= -1;
}
//проверим столкновение с другими шарами
for (int j = i + 1; j < balls.size(); j++) {
Ball otherBall = balls.get(j);
int x = (ball.getX() - ball.radius) - (otherBall.getX() - otherBall.radius);
int y = (ball.getY() - ball.radius) - (otherBall.getY() - otherBall.radius);
double xy = Math.sqrt(x * x + y * y);
//упрощенная реакция на столкновение шаров
if (xy <= ball.radius + otherBall.radius) {
float sX = ball.speedX;
float sY = ball.speedY;
float sumSpeedX = Math.abs(ball.speedX) + Math.abs(otherBall.speedX);
float sumSpeedY = Math.abs(ball.speedY) + Math.abs(otherBall.speedY);
ball.speedX = otherBall.speedX;
ball.speedY = otherBall.speedY;
otherBall.speedX = sX;
otherBall.speedY = sY;
}
}
ball.setLocation(ball.getX() + (int)ball.speedX, ball.getY() + (int)ball.speedY);
}
}
private float speedX;
private float speedY;
private Color color;
private int radius;
public Ball(float speed, int radius) {
balls.add(this);
this.radius = radius;
speedX = speed;
speedY = -speed;//speedY можно сделать положительным - разницы нет.
setSize(radius * 2, radius * 2);
setLocation((int)(Math.random() * (550 - radius * 2)),
(int)(Math.random() * (500 - radius * 2)));
//установим случайный цвет для шарика
color = new Color((int)(Math.random() * 255), (int)(Math.random() * 255),
(int)(Math.random() * 255));
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Ellipse2D ellipse = new Ellipse2D.Float(0, 0, radius * 2, radius * 2);
g2.setColor(color);
g2.fill(ellipse);
}
}package simple9PG;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Bouns {
private Timer timer;
private JFrame frame;
public Bouns() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(550, 550);
frame.setLayout(null);
frame.add(new Ball(5, 20));
frame.add(new Ball(4, 30));
frame.add(new Ball(3, 25));
frame.add(new Ball(4, 27));
frame.add(new Ball(1, 35));
frame.add(new Ball(2, 40));
frame.add(new Ball(4, 22));
frame.add(new Ball(6, 23));
frame.add(new Ball(12, 15));
timer = new Timer(30, new TimerListener());
timer.start();
frame.setVisible(true);
}
});
}
private class TimerListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent event) {
Ball.moveAndDetection(simple9PG.Bouns.this.frame);
}
}
}import simple9PG.Bouns;
public class Main {
public static void main(String[] args) {
Bouns bouns = new Bouns();
}
}Решение задачи: «Смещение при добавлении компонента на панель»
textual
Листинг программы
xy <= ball.radius + otherBall.radius