3

円から円への衝突検出プログラムを作成しています。ボールを動かすことはできますが、衝突が検出されると、ボールがかなり重なってしまいます。助言がありますか?前もって感謝します!

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

4 に答える 4

3

コメントされていないコードがたくさんあります。

ボールの中心が半径の合計内にある場合、ボールはちょうど衝突しています。r1 と r2 をボールの半径、x1 と y1 をボール 1 の中心の位置とする。同様に、ball2 の場合は x2、y2 です。

として中心間の距離の二乗を測定し(x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)ます。(ピタゴラス)。

これが より小さいか等しい場合、それらは衝突してい(r1 + r2) * (r1 + r2)ます。

ここで重要なことは、高価な計算タスクである平方根を計算する必要がないことです。

于 2013-10-07T12:36:48.030 に答える
0

おそらく、円の動きが速すぎるか、時間ステップが高すぎることが原因だと思います。時間ステップを減らします。より良いアプローチは、Box2D のような物理ライブラリを使用することです。それが含まれているJavaライブラリであるlibgdxを見てください。このリンクで少し議論されています

于 2013-10-07T12:36:22.353 に答える
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();
         }              
     }
  }
于 2013-10-07T12:38:29.567 に答える