2013-10-07 156 views
3

我正在圈圈碰撞检测程序。我可以让球移动,但是当碰撞被发现时,这些球是非常重叠的。有什么建议么?提前致谢!Java圆圈碰撞检测

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; 

    } 


    } 
} 
+4

请参阅[本答案](http://stackoverflow.com/a/14575043/418556)关于形状之间的碰撞检测技巧。 –

回答

3

这么多未注释的代码!

如果球的中心位于半径的总和范围内,球就会碰撞。令r1和r2为球半径,x1,y1为球1中心的位置;对于ball2同样是x2,y2。

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

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

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

0

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

0

你应该在每次移动后检查碰撞。

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(); 
     }    
    } 
    } 
+0

那么,这是没有优化。 –

0

你需要这样的东西。

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