【问题标题】:(JavaFX) How do I check for collision between animated circles?(JavaFX) 如何检查动画圆圈之间的碰撞?
【发布时间】:2014-11-29 23:51:29
【问题描述】:

我的任务是有一个用于添加随机位置和方向的球的按钮。我无法检查球之间的碰撞。问题出在第 123 行。谢谢!

        import java.util.ArrayList;
        import java.util.Scanner;
        import javafx.animation.KeyFrame;
        import javafx.animation.Timeline;
        import javafx.beans.property.DoubleProperty;
        import javafx.event.ActionEvent;
        import javafx.scene.layout.Pane;
        import javafx.util.Duration;

        class BallPane extends Pane {

            private double radius = 10;

            private ArrayList<Ball> list = new ArrayList();
            private Timeline animation;

            public BallPane() {
                Scanner kb = new Scanner(System.in);
                System.out.println("\nPlease press RIGHT and LEFT arrow keys to increase and decrease"
                        + " the speed of the balls.");
                animation = new Timeline(
                        new KeyFrame(Duration.millis(50), (ActionEvent e) -> {
                            moveBall();
                        }));
                animation.setCycleCount(Timeline.INDEFINITE);
                animation.play(); // Start animation
            }

            public void addBall() {
                Ball balls = new Ball(BallPane.this);
                getChildren().add(balls.getCircle());
                list.add(balls);
            }

            public void moveBall() {

                double x, y, dx, dy;
                // Check boundaries

                Ball a;
                for (int i = 0; i < list.size(); i++) {
                    a = list.get(i);
                    x = a.getCircle().getCenterX();
                    y = a.getCircle().getCenterY();
                    dx = a.getDirectionX() + (int) Math.random() * 100;
                    dy = a.getDirectionY() + (int) Math.random() * 100;

                    if (x < a.getCircle().getRadius()
                            || x > getWidth() - a.getCircle().getRadius()) {

                        dx *= -1; // Change ball move direction
                    }
                    if (y < a.getCircle().getRadius()
                            || y > getHeight() - a.getCircle().getRadius()) {
                        dy *= -1; // Change ball move direction
                    }
                    // Adjust ball position
                    x += dx;
                    y += dy;
                    a.setDirectionX(dx);
                    a.setDirectionY(dy);
                    a.getCircle().setCenterX(x);
                    a.getCircle().setCenterY(y);
                    // Ball b = list.get(i + 1);
                }
        //line 123
//also trying to use the distance formula to check the distance between two circles' center points
               for (int i = 0; i < Timeline.INDEFINITE; i++) {
                    if (Math.sqrt(Math.pow(list.get(i).getCenterX()
                            - list.get(i + 1).getCenterX(), 2) + Math.pow(list.get(i).getCenterY()
                                    - list.get(i + 1).getCenterY(), 2)) <= 2 * radius) {
                        list.get(i).getCircle();
                        getChildren().remove(i);
                        list.remove(i);
                    }
                }
            }
        }//End of BallPane class.

感谢您的帮助!主要是代码堆栈溢出......你为什么让我输入 this.asdl;kfj dsal;kf jldfjals ;kdjfldksajf l;askfj

【问题讨论】:

  • 你为什么使用i &lt; Timeline.INDEFINITE作为你的循环条件?
  • ...似乎只检查列表中相邻的球是否发生碰撞......但我猜任何组合都必须检查......
  • @James_D 我正在使用时间线 indefenite 因为如果我将它设置为 list.size() 它会超出范围......而 Jens-Peter ......我将如何解决这个问题?

标签: java javafx collision


【解决方案1】:

通过颠倒循环顺序尝试从 Mailkov 的原始帖子修改的以下代码

   for (int i = list.size()-1; i >=1 ; i--)
   {
     for (int j=(i-1); j >=0; j--)
     {
        if (Math.sqrt(Math.pow(list.get(i).getCenterX() - list.get(j).getCenterX(), 2) + 
            Math.pow(list.get(i).getCenterY() - list.get(j).getCenterY(), 2)) <= 2 * radius )
        {
            list.get(i).getCircle();
            getChildren().remove(i);
            list.remove(i);
            break; // I think we need to break out the for (j) loop here
        }
      }
    }

【讨论】:

  • 我认为这不正确,因为碰撞时只爆炸一个球
  • @Malikov 我尝试了你们两个人的代码......但是球直接穿过对方,有时仍然有一些随机球消失。
【解决方案2】:

试试这个:

   ArrayList<Integer> ballexplode=new ArrayList<Integer>();
   for (int i = 0; i < list.size()-1; i++) {
     for (int j=i+1; j < list.size();j++){
        if (Math.sqrt(Math.pow(list.get(i).getCenterX()
                - list.get(j).getCenterX(), 2) + Math.pow(list.get(i).getCenterY()
                        - list.get(j).getCenterY(), 2)) <= 2 * radius) {
            list.get(i).getCircle();
            ballexplode.add(i);
            ballexplode.add(j);
        }
      }
    }

        for (int i=ballexplode.size()-1;i>=0;i--){
        getChildren().remove(ballexplode.get(i));
        list.get(ballexplode.get(i)).getCircle();
         }

【讨论】:

  • @Malikov 有时会有一些随机的球消失,但球仍然会相互穿过......
  • 调用list.remove(i)时,不会影响下一次循环的迭代吗?尝试向后遍历循环以查看问题是否已解决。
  • @fang 那是什么意思...我认为我对碰撞部分的逻辑正确=(
  • @Brij 我在谈论 Mailkov 帖子​​中的逻辑。例如,当使用 i = 5 调用 list.remove(i) 时,第一个 for 循环中的下一次迭代将检查 list.get(6) 和列表中的其他球。但是,list.get(6) 现在是原始列表中的第 7 个球(因为第 5 个已被删除),这意味着您将跳过对某些球的检查。如果向后循环,则从列表中删除项目不会影响访问被删除项目前面的项目。
  • @fang 如果我唠叨太多,我很抱歉,但我是一个初学者程序员....如何向后循环?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
相关资源
最近更新 更多