Смещение при добавлении компонента на панель - 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

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 3.929 из 5
Похожие ответы