【问题标题】:Java Circle to Circle collision detectionJava圆到圆碰撞检测
【发布时间】:2013-10-07 12:31:54
【问题描述】:

我正在制作一个圆到圆的碰撞检测程序。我可以让球四处移动,但是当检测到碰撞时,球重叠得很远。有什么建议么?提前致谢!

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.lang.Math;

public class ShapePanel extends JPanel{

  private JButton button, startButton, stopButton;
  private JTextField textField;
  private JLabel label;
  private Timer timer;
  private final int DELAY = 10;


  ArrayList<Shape> obj = new ArrayList<Shape>();


  public static void main(String[] args){

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new ShapePanel());
    frame.pack();
    frame.setVisible(true);
  }

  public ShapePanel(){

    JPanel controlPanel = new JPanel();
    DrawingPanel dpanel = new DrawingPanel();
    controlPanel.setPreferredSize(new Dimension(100,400));
    button = new JButton("Add Shape");
    startButton = new JButton("Start");
    stopButton = new JButton("Stop");
    textField = new JTextField(2);
    label = new JLabel("Count:");



    controlPanel.add(button);
    controlPanel.add(label);
    controlPanel.add(textField);
    controlPanel.add(startButton);
    controlPanel.add(stopButton);
    add(controlPanel);
    add(dpanel);

    ButtonListener bListen = new ButtonListener();
    button.addActionListener(bListen);
    startButton.addActionListener(bListen);
    stopButton.addActionListener(bListen);

    timer = new Timer(DELAY, bListen);

  }
  private class ButtonListener implements ActionListener{


    public void actionPerformed(ActionEvent e){

      if (e.getSource() == button){

        obj.add(new Shape());
        if (obj.get(obj.size()-1).y > 200){

          obj.get(obj.size()-1).moveY = -obj.get(obj.size()-1).moveY;
        }

      }else if (e.getSource() == timer){

        for (int i = 0; i < obj.size(); i++){
          obj.get(i).move();
        }

        for (int i = 0; i < obj.size(); i++){

          for (int j = i + 1; j < obj.size(); j++){

            if (Math.sqrt(Math.pow((double)obj.get(i).centerCoordX - (double)obj.get(j).centerCoordX,2)) + 
                Math.pow((double)obj.get(i).centerCoordY - (double)obj.get(j).centerCoordY,2) <= obj.get(i).radius + obj.get(j).radius){

              timer.stop();


            }

          }
        }

      }else if (e.getSource() == startButton){

        timer.start();
      }else if (e.getSource() == stopButton){

        timer.stop();
      }


      repaint();
    }
  }
  private class DrawingPanel extends JPanel{

    DrawingPanel(){

      setPreferredSize(new Dimension(400,400));
      setBackground(Color.pink);

    }
    public void paintComponent(Graphics g){
      super.paintComponent(g);
      for(int i = 0; i < obj.size(); i++){

        obj.get(i).display(g);
      }

    }
  }
}




import java.awt.*;
import java.util.*;

public class Shape{

  public int x, y, width, height, moveX = 1, moveY = 1, centerCoordX, centerCoordY, radius;
  private Color colour;
  public boolean reverse = false, sameDirection = true;

  Random generator = new Random();

  public int randomRange(int lo, int hi){
    return generator.nextInt(hi-lo)+lo;
  }

  Shape(){
    width = randomRange(30, 50);
    if (width % 2 != 0){
      width = randomRange(30, 50);
    }
    height = width;

    radius = width/2;
    x = randomRange(0, 400-width);
    y = randomRange(0, 400-height);
    colour = new Color(generator.nextInt(256),generator.nextInt(256),generator.nextInt(256));
  }

  public void display(Graphics g){

    g.setColor(colour);
    g.fillOval(x, y, width, height);
  }
  void move(){

    x += moveX;
    y += moveY;

    centerCoordX = x + width/2;
    centerCoordY = y + height/2;

    if(x >= 400-width){

      moveX = -moveX;

    }if(x <= 0){

      moveX = -moveX;

    }if(y >= 400-height){

      moveY = -moveY;

    }if (y <= 0){

      moveY = -moveY;

    }


  }
}

【问题讨论】:

  • 请参阅this answer,了解形状之间的碰撞检测以获取提示。

标签: java swing collision-detection geometry


【解决方案1】:

这么多未注释的代码!

如果球的中心在半径之和之内,它们就会发生碰撞。设r1和r2为球半径,x1,y1为球1的中心位置;同样 x2, y2 为 ball2。

测量中心之间距离的平方为(x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)。 (毕达哥拉斯)。

如果小于或等于(r1 + r2) * (r1 + r2),则它们发生碰撞。

这里的关键是不需要计算平方根,这是一项昂贵的计算任务。

【讨论】:

    【解决方案2】:

    我会说这可能是由于您的圈子移动得太快或您的时间步长太高。减少你的时间步。更好的方法是使用像 Box2D 这样的物理库。看看 libgdx,这是一个包含它的 java 库。 它在this link 中讨论了一点

    【讨论】:

      【解决方案3】:

      您应该在每次移动后检查结肠。

      for (int i = 0; i < obj.size(); i++)
      {
          obj.get(i).move();
      
          for (int j = 0; j < obj.size(); j++)
          {
              if (Math.sqrt(Math.pow((double)obj.get(i).centerCoordX - (double)obj.get(j).centerCoordX,2)) + 
                      Math.pow((double)obj.get(i).centerCoordY - (double)obj.get(j).centerCoordY,2) <= obj.get(i).radius + obj.get(j).radius && i!=j)
               {
                    timer.stop();
               }              
           }
        }
      

      【讨论】:

      • 好吧,那不是优化的。
      【解决方案4】:

      你需要这样的东西。

      public boolean overlaps (Circle c1, Circle c2) {
          float dx = c1.x - c2.x;
          float dy = c1.y - c2.y;
          float distance = dx * dx + dy * dy;
          float radiusSum = c1.radius + c2.radius;
          return distance < radiusSum * radiusSum;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-02
        • 2010-10-16
        • 1970-01-01
        • 2013-01-28
        • 2016-08-08
        • 2011-09-12
        相关资源
        最近更新 更多