球相互碰撞

时间:2018-03-01 10:36:49

标签: java algorithm swing

我正在研究移动球的动画,它必须与墙壁相互碰撞。 一半的工作完成了。球已经可以与墙壁碰撞。 但我不知道如何使球相互碰撞。我尝试在整个ArrayList集合中使用循环,但是球被错误地删除了。 也许你可以帮我完成这项任务。

MainClass.java

import java.awt.EventQueue;
import javax.swing.Timer;

public class MainClass
{
    public static Timer t; 

    public static void main(String[] args)  
    {

        UI myUI = new UI();
        EventQueue.invokeLater(myUI);

        t = new Timer(10, myUI);
        t.start();
    }

}

UI.java。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;


public class UI extends JFrame implements Runnable, ActionListener
{
    private static final long serialVersionUID = 1L;
    @Override
    public void run()
    {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(600, 500);
        setLocationRelativeTo(null);
        setTitle("Bouncing Balls!");

        add(new DrawingSurface());
        setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        repaint();
    }


}

DrawingSurface.java

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JPanel;

public class DrawingSurface extends JPanel
{
    private static final long serialVersionUID = 1L;
    static ArrayList<BouncingBall> bList = new ArrayList<BouncingBall>();
    private final int numBalls = 2;
    Random r = new Random();
    int rangeMin = 1, rangeMax = 3;
    double randomXSpeed;
    double randomYSpeed;


    // create a list of balls in the constructor. This way it happens only one time
    // rather than EVERY time you re-draw...
    public DrawingSurface()
    {
        for(int i = 0; i < numBalls ; i++)
        {
            randomXSpeed = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
            randomYSpeed = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
            // Notice I delegate ALL of the ball functionality to the BouncingBall class. 
            // I don't want give it anything to create a new ball. 
            // The only place the balls exist is in the ArrayList.
            bList.add(new BouncingBall(r.nextInt(400), r.nextInt(300), randomXSpeed, randomYSpeed));  
        }
    }


    public void paintComponent(Graphics gContext)
    {

        // loop through the array list and tell each ball the size of the window
        // and give it the graphics context so it can draw itself.
        for(int i = 0; i < bList.size(); i++)
        {
            bList.get(i).updatePosition(getWidth(), getHeight(), (Graphics2D)gContext);
        }
    }
}

BouncingBall.java

import java.awt.Color;
import java.awt.Graphics2D;

import javax.swing.JPanel;

// a class that manages the position of randomly colored ball, and draws it.
public class BouncingBall extends JPanel
{

    private static final long serialVersionUID = 1L;
    public int x,y;
    Double xMove;
    Double yMove;
    public final static int size = 20; //size of the ball
    private Color c;

    public BouncingBall(int width, int height, Double xSpeed, Double ySpeed)
    {
        x = width; //starting position
        y = height; //starting position

        xMove = xSpeed; //starting velocity
        yMove = ySpeed; //starting velocity     

        //pick a random color
        c = new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255));
    }

    //pass in the height and width of the current window so we can tell where we should bounce
    public void updatePosition(int width, int height, Graphics2D g)
    {
        //update the position
        y += yMove;
        x += xMove;
        Double xSpeed = 0.0, ySpeed = 0.0;

        //if the ball moves to the right edge of the window, turn around. 
        if(x > width - size)
        {   
            x = width - size;
            xMove *= -1;
            if (xMove > 0) {
                xSpeed = xMove + (Math.random() * (1));
            }
            if (xMove <= 0) {
                xSpeed = xMove - (Math.random() * (1));
            }
            if (yMove > 0) {
                ySpeed = yMove + (Math.random() * (1));
            }
            if (yMove <= 0) {
                ySpeed = yMove - (Math.random() * (1));
            }
            DrawingSurface.bList.add(new BouncingBall(x, y, xSpeed, ySpeed));
            c = new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255));
        }

        //if the ball moves to the left edge of the window, turn around.
        if(x < 1)
        {
            x = 1;
            xMove *= -1;
            if (xMove > 0) {
                xSpeed = xMove + (Math.random() * (1));
            }
            if (xMove <= 0) {
                xSpeed = xMove - (Math.random() * (1));
            }
            if (yMove > 0) {
                ySpeed = yMove + (Math.random() * (1));
            }
            if (yMove <= 0) {
                ySpeed = yMove - (Math.random() * (1));
            }
            DrawingSurface.bList.add(new BouncingBall(x, y, xSpeed, ySpeed));
            c = new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255));
        }

        //if the ball moves to the bottom of the screen, turn around.
        if(y > height - size )
        {
            y = height - size;
            yMove *= -1;
            if (xMove > 0) {
                xSpeed = xMove + (Math.random() * (1));
            }
            if (xMove <= 0) {
                xSpeed = xMove - (Math.random() * (1));
            }
            if (yMove > 0) {
                ySpeed = yMove + (Math.random() * (1));
            }
            if (yMove <= 0) {
                ySpeed = yMove - (Math.random() * (1));
            }
            DrawingSurface.bList.add(new BouncingBall(x, y, xSpeed, ySpeed));
            c = new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255));
        }

        //if the ball moves to the top of the screen, turn around.
        if(y < 1)
        {
            y = 1;
            yMove *= -1;
            if (xMove > 0) {
                xSpeed = xMove + (Math.random() * (1));
            }
            if (xMove <= 0) {
                xSpeed = xMove - (Math.random() * (1));
            }
            if (yMove > 0) {
                ySpeed = yMove + (Math.random() * (1));
            }
            if (yMove <= 0) {
                ySpeed = yMove - (Math.random() * (1));
            }
            DrawingSurface.bList.add(new BouncingBall(x, y, xSpeed, ySpeed));
            c = new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255));
        }

        g.setColor(c);
        g.fillOval(x, y, size, size);
    }


}

1 个答案:

答案 0 :(得分:1)

为了检测每个球相互碰撞,一个简单的方法是用一对嵌套的环循环球的集合。因此,每个球将与所有其他球进行碰撞检查:

//From your list of balls
ArrayList<BouncingBall> bList = new ArrayList<BouncingBall>();

for(BouncingBall b1 : bList)
    for(BouncingBall b2 : bList)
        if(b1.intersects(b2)){
            //do whatever (such as bouncing off) when the balls collide
            b1.flipDirection();
            b2.flipDirection();              
        }

为了使用intersects()方法,您的BouncingBall类可以从Java扩展到Rectangle类。或者,如果您不能将BouncingBall课程扩展到另一个班级。

你可以让他们返回界限:

class BouncingBall{
    public Rectangle getBounds(){
        return new Rectangle(x, y, width ,height);
    }
}

然后您仍然可以使用intersects()方法:

//to check for collision using intersects() method
for(BouncingBall b1 : bList)
    for(BouncingBall b2 : bList)
        if(b1.getBounds().intersects(b2.getBounds())){
            //do whatever (such as bouncing off) when the balls collide
            b1.flipDirection();
            b2.flipDirection();              
        }

使用嵌套循环来检测像这样的简单球类动画的碰撞就足够了。除非您制作的游戏中需要检查数千个或更多实体的碰撞所需的每个帧,否则您将需要不同的碰撞检测算法,例如Quad-tree。

我之前使用相同的算法编写了这样的程序,并且它运行得非常好:

enter image description here