gpt4 book ai didi

java - 球/圆碰撞问题

转载 作者:行者123 更新时间:2023-12-01 14:28:27 28 4
gpt4 key购买 nike

我试图让球弹起,或者在它们碰撞时反转方向。我让它检查移动方法中的碰撞。它检查两个球之间是否发生碰撞,如果发生碰撞,它将反转速度。问题是,有时球会互相穿过,主要是较小的球。球要么弹跳得早,要么弹得晚,要么粘在一起振动,要么穿过彼此。

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);

}
}
}

更新版本:根据 J W 和 ZnW 的建议。并添加了更多球,以便您可以更清楚地看到问题

public class Balls2{

public static void main(String[] args){
new Balls2();
}


public Balls2(){
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(350,350,0,0,150,Color.PINK,this));

balls.add(new Ball(500,0,0,10,20,Color.RED,this));
balls.add(new Ball(0,500,10,0,20,Color.CYAN,this));
balls.add(new Ball(500,1000,0,-10,20,Color.ORANGE,this));
balls.add(new Ball(1000,500,-10,0,20,Color.GREEN,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();
ball.checkCollision();
}

}});
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{
private int x;
private int y;
private int speedX;
private int speedY;
private int radius;
private int height;
private int width;
private Color color;
private 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(){

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;
}


x += speedX;
y += speedY;

}
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;
}
}
}
}
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);

}
}
}

最佳答案

每个球的球移动和球碰撞不应在同一函数中完成。假设你有球 A 和 B 即将碰撞。球 A 移动,然后检查是否发生碰撞,找到碰撞并反转方向。然后球 B 移动,当它移动时,它可能会在检测到它之前移出碰撞区域。然后它检查是否有碰撞,没有发现碰撞,就继续朝同一方向前进。

所有球都应该移动,然后您应该检查是否有任何碰撞(反之亦然 - 它们是等效的)。

因此,我将从 move() 函数中删除球碰撞检查,并创建一个新函数(基于 ZnW 建议的改进):

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;
}
}
}
}

然后在 actionPerformed 函数中,添加一个循环来检查冲突:

for(Ball ball : balls){
ball.checkCollision();
}

关于java - 球/圆碰撞问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17001386/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com