Java 球/圆碰撞问题
我试图让球反弹,或者在碰撞时反转方向。我让它检查move方法中的冲突。它检查两个球之间是否有碰撞,如果是真的,它将反转速度。 问题是,有时球只是互相穿过,而较小的球大多是。球要么反弹到早,要么反弹到晚,要么粘在一起振动,要么相互穿过Java 球/圆碰撞问题,java,swing,collision,geometry,Java,Swing,Collision,Geometry,我试图让球反弹,或者在碰撞时反转方向。我让它检查move方法中的冲突。它检查两个球之间是否有碰撞,如果是真的,它将反转速度。 问题是,有时球只是互相穿过,而较小的球大多是。球要么反弹到早,要么反弹到晚,要么粘在一起振动,要么相互穿过 public class Balls{ public static void main(String[] args){ new Balls(); } public Balls(){ JFrame frame = new JFrame("Ball
public class Balls{
public static void main(String[] args){
new Balls();
}
public Balls(){
JFrame frame = new JFrame("Balls");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(1000,1000);
frame.add(new ballHolder());
}
public class ballHolder extends JPanel{
;
public List<Ball> balls = new ArrayList<>();
public ballHolder(){
//add balls(x,y,speedX,speedY,radius,color,parent)
balls.add(new Ball(670,180,2,9,20,Color.RED,this));
balls.add(new Ball(570,380,-8,-9,20,Color.ORANGE,this));
balls.add(new Ball(170,780,2,2,50,Color.PINK,this));
balls.add(new Ball(470,680,5,3,50,Color.GREEN,this));
balls.add(new Ball(270,280,9,7,50,Color.CYAN,this));
System.out.println("Number of Balls: "+ balls.size());
Timer timer = new Timer(20, new ActionListener(){
public void actionPerformed(ActionEvent e) {
for(Ball ball : balls){
ball.move();
}
repaint();
}});
timer.start();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for(Ball ball : balls){
ball.paint(g2);
}
}
//gets list of balls
public List<Ball> getBalls(){
return balls;
}
}
public class Ball{
int x;
int y;
public int speedX;
public int speedY;
int radius;
int height;
int width;
Color color;
ballHolder parent;
public Ball(int x,int y,int speedX,int speedY,int radius,Color color,ballHolder parent){
this.x = x;
this.y = y;
this.speedX = speedX;
this.speedY = speedY;
this.radius = radius;
this.color = color;
this.parent = parent;
this.height = radius * 2;
this.width = radius * 2;
}
//moves ball
public void move(){
x += speedX;
y += speedY;
if(x + width > parent.getWidth()){
x = parent.getWidth() - width;
speedX = -speedX;
}else if (0 > x){
x = 0;
speedX = -speedX;
}
if(y + height > parent.getHeight()){
y = parent.getHeight() - height;
speedY = -speedY;
}else if (0 > y){
y = 0;
speedY = -speedY;
}
//check for ball collision
for(int i=0;i < parent.getBalls().size();i++){
for(int j=0;j < parent.getBalls().size();j++){
if(i != j){
if(ballCollision(parent.getBalls().get(i), parent.getBalls().get(j))){
System.out.println("Collision");
parent.getBalls().get(i).speedX *= -1;
parent.getBalls().get(i).speedY *= -1;
}
}
}
}
}
//checks for collision
public boolean ballCollision(Ball a, Ball b){
if((b.x-a.x)*(b.x-a.x) + (a.y-b.y)*(a.y-b.y) <= (a.radius+b.radius)*(a.radius+b.radius)){
return true;
}else{
return false;
}
}
private void paint(Graphics g2){
g2.setColor(color);
g2.fillOval(x, y, width, height);
}
}
}
公共类舞会{
公共静态void main(字符串[]args){
新球();
}
公众舞会(){
JFrame=新JFrame(“球”);
frame.setDefaultCloseOperation(关闭时退出frame);
frame.setVisible(true);
框架设置尺寸(10001000);
框架。添加(新球座());
}
公共级别持球人扩展JPanel{
;
public List balls=new ArrayList();
公众持球人(){
//添加球(x、y、速度x、速度、半径、颜色、父对象)
添加(新球(670180,2,9,20,颜色。红色,此));
添加(新球(570380,-8,-9,20,颜色。橙色,此));
添加(新球(170780,2,2,50,颜色。粉红色,此));
添加(新球(470680,5,3,50,颜色。绿色,此));
添加(新球(270280,9,7,50,颜色。青色,此));
System.out.println(“球数:+Balls.size());
计时器计时器=新计时器(20,新ActionListener(){
已执行的公共无效操作(操作事件e){
用于(球:球){
ball.move();
}
重新油漆();
}});
timer.start();
}
公共组件(图形g){
超级组件(g);
图形2d g2=(图形2d)g;
用于(球:球){
球形涂料(g2);
}
}
//获取球的列表
公共列表getBalls(){
回球;
}
}
公共班级舞会{
int x;
int-y;
公共int speedX;
公共卫生服务;
整数半径;
内部高度;
整数宽度;
颜色;
持球人父母;
公共球(整数x,整数y,整数speedX,整数speedY,整数半径,颜色,球座父球){
这个.x=x;
这个。y=y;
this.speedX=speedX;
这个。迅速的=迅速的;
这个半径=半径;
这个颜色=颜色;
this.parent=parent;
该高度=半径*2;
该宽度=半径*2;
}
//移动球
公开作废动议(){
x+=速度x;
y+=快速;
如果(x+width>parent.getWidth()){
x=父级.getWidth()-宽度;
speedX=-speedX;
}如果(0>x){
x=0;
speedX=-speedX;
}
如果(y+height>parent.getHeight()){
y=父级。getHeight()-高度;
迅捷=-迅捷;
}如果(0>y){
y=0;
迅捷=-迅捷;
}
//检查有无碰撞
对于(int i=0;ix){
x=0;
speedX=-speedX;
}
如果(y+height>parent.getHeight()){
y=父级。getHeight()-高度;
迅捷=-迅捷;
}如果(0>y){
y=0;
迅捷=-迅捷;
}
x+=速度x;
y+=快速;
}
公共无效检查冲突(){
对于(int j=0;j 如果((b.x-a.x)*(b.x-a.x)+(a.y-b.y)*(a.y-b.y)尝试在所有计算之后修改位置。
而且你有非常“资源昂贵”的碰撞检查,你应该像这样比较球:
for (int j = 0; j < parent.getBalls().size(); j++)
if (parent.getBalls().get(j) != this)
if (ballCollision(parent.getBalls().get(j), this)) {
System.out.println("Collision");
parent.getBalls().get(j).speedX *= -1;
parent.getBalls().get(j).speedY *= -1;
speedX *= -1;
speedY *= -1;
}
}
for(int j=0;j
您只是在比较每个球中的所有球。您应该只比较当前球和另一个球,而不是每次比较所有其他球之间的所有球。球移动和球碰撞不应该对每个球使用相同的函数。假设您有球A和球B即将碰撞。球A移动,然后检查碰撞,找到一个并反转方向。然后球B移动,当它移动时,它可能会在检测到之前移出碰撞区域。然后它检查碰撞,但没有找到,并继续朝同一方向移动
所有的球都应该移动,然后你应该检查是否有碰撞(反之亦然,它们是等效的)
因此,我将从move()
函数中删除球碰撞检查,并创建一个新函数(基于ZnW建议的改进):
这是一个很好的改进。但是,更新碰撞中涉及的两个球不起作用,因为两个球都会
for (int j = 0; j < parent.getBalls().size(); j++)
if (parent.getBalls().get(j) != this)
if (ballCollision(parent.getBalls().get(j), this)) {
System.out.println("Collision");
parent.getBalls().get(j).speedX *= -1;
parent.getBalls().get(j).speedY *= -1;
speedX *= -1;
speedY *= -1;
}
}
public void checkCollision(){
for(int j=0;j < parent.getBalls().size();j++){
if(parent.getBalls().get(j) != this){
if(ballCollision(parent.getBalls().get(j), this)){
System.out.println("Collision");
speedX *= -1;
speedY *= -1;
}
}
}
}
for(Ball ball : balls){
ball.checkCollision();
}