我正在制作一个圈子来圈出碰撞检测程序。我可以让球移动,但是当检测到碰撞时,球很重叠。有什么建议?提前谢谢!
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;
}
}
}
答案 0 :(得分:3)
这么多未注释的代码!
如果球的中心在半径的总和范围内,球就会发生碰撞。设r1和r2为球半径,x1,y1为球1中心的位置;类似于ball2的x2,y2。
测量中心之间距离的平方为(x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)
。 (毕达哥拉斯)。
如果它小于或等于(r1 + r2) * (r1 + r2)
,则会发生碰撞。
这里的关键是无需计算平方根,这是一项昂贵的计算任务。
答案 1 :(得分:0)
我想说这可能是因为你的圈子移动得太快或你的时间步长太高了。减少你的时间步。更好的方法是使用像Box2D这样的物理库。看看libgdx,包含它的java库。 它在this link
中讨论了一下答案 2 :(得分: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();
}
}
}
答案 3 :(得分: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;
}