学习使用AWT时编写的一个模拟d性碰撞的程序。
package Package1; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; import java.util.Random; public class BallsTest { //创建窗口对象 public frame frame = new frame("这是一个窗口容器frame"); //设置桌面(画布)宽度和高度 public int TABLE_WIDTH = 500; public int TABLE_HEIGHT = 300; //设置球拍的宽度和高度 public final int RACKET_WIDTH = 80; public final int RACKET_HEIGHT = 20; //定义变量,记录球拍的坐标 public int racketX = 120; public final int racketY = 280; //设置小球颜色 public Color[] Allcolor = {Color.BLUE, Color.GREEN, Color.CYAN, Color.BLACK, Color.MAGENTA}; //是否结束游戏 volatile boolean flag = false; //小球个数 public volatile int num = 2; //设置重力加速度 public int gravity = 1; //设置刷新周期 public int delay = 30; private class Ball { //设置小球的半径 public volatile int ballRadius; //定义变量,记录小球的坐标 public volatile double ballX; public volatile double ballY; //定义变量,记录小球在x和y方向上分别移动的速度 public volatile double speedX; public volatile double speedY; //设置小球颜色 public Color color; Random random = new Random(); //初始化时随机生成坐标速度等信息 public Ball() { int SPEEDMAX = 20; int R_MIN = 20; int R_MAX = 25; this.ballRadius = random.nextInt(R_MAX - R_MIN) + R_MIN; this.ballX = random.nextInt(TABLE_WIDTH - 2 * this.ballRadius); this.ballY = random.nextInt(TABLE_HEIGHT / 2); this.speedX = random.nextInt(SPEEDMAX * 2) - SPEEDMAX + 5; this.speedY = 0; this.color = Allcolor[random.nextInt(Allcolor.length)]; } public Ball(int ballX, int ballY, int speedX, int speedY, int ballRadius) { this.ballX = ballX; this.ballY = ballY; this.speedX = speedX; this.speedY = speedY; this.ballRadius = ballRadius; } public int getBallRadius() { return ballRadius; } public void setBallRadius(int BallRadius) { this.ballRadius = BallRadius; } public double getBallX() { return ballX; } public void setBallX(int ballX) { this.ballX = ballX; } public double getBallY() { return ballY; } public void setBallY(int ballY) { this.ballY = ballY; } public double getSpeedX() { return speedX; } public void setSpeedX(int speedX) { this.speedX = speedX; } public double getSpeedY() { return speedY; } public void setSpeedY(int speedY) { this.speedY = speedY; } } ArrayListballs = new ArrayList (); //创建一些小球 //给小球组设置运动线程,并检测碰撞来修改它们的速度 private class BallMovement implements Runnable { //每个线程负责跟踪一个小球 private int ballId; //跟踪的小球索引 public BallMovement(int ballId) { this.ballId = ballId; } private boolean isTouched(int ballId, int ballIdOther) { //碰撞检测 Ball ball0 = balls.get(ballId); Ball ball1 = balls.get(ballIdOther); //获取本小球和其它小球的半径和速度、位置 int ball0Radius = ball0.getBallRadius(); double ball0X = ball0.getBallX(); double ball0Y = ball0.getBallY(); double x0 = ball0X + ball0Radius; double y0 = ball0Y + ball0Radius; int ball1Radius = ball1.getBallRadius(); double ball1X = ball1.getBallX(); double ball1Y = ball1.getBallY(); double x1 = ball1X + ball1Radius; double y1 = ball1Y + ball1Radius; //根据是否发生碰撞改变各自小球类的内部变量值 double deltaX = x1 - x0; double deltaY = y1 - y0; double distance = Math.sqrt((Math.pow(deltaX, 2) + Math.pow(deltaY, 2))); //如果发生碰撞 boolean b = false; double d = ball0Radius + ball1Radius; if (distance <= d) { // double d = ball0.ballRadius + ball1.getBallRadius(); // double x0 = ball0.ballX + ball0.ballRadius; // double y0 = ball0.ballY + ball0.ballRadius; // double x1 = ball1.ballX + ball1.ballRadius; // double y1 = ball1.ballY + ball1.ballRadius; // double deltaX = x1 - x0; // double deltaY = y1 - y0; //--------------------------------- // double theta = Math.atan(deltaY/deltaX); // //修正一下两个小球的位置 // theta = Math.abs(Math.atan(deltaY/deltaX)); // double dx = d*Math.cos(theta); // double dy = d*Math.sin(theta); // if(deltaY >= 0 && deltaX >= 0) { // ball0.ballX = x1 - dx - ball0.ballRadius; // ball0.ballY = y1 - dy - ball0.ballRadius; // } // if(deltaY < 0 && deltaX >= 0) { // ball0.ballX = x1 - dx - ball0.ballRadius; // ball0.ballY = y1 + dy - ball0.ballRadius; // } // if(deltaY >= 0 && deltaX < 0) { // ball0.ballX = x1 + dx - ball0.ballRadius; // ball0.ballY = y1 - dy - ball0.ballRadius; // } // if(deltaY < 0 && deltaX < 0) { // ball0.ballX = x1 + dx - ball0.ballRadius; // ball0.ballY = y1 + dy - ball0.ballRadius; // } b = true; } return b; } @Override public void run() { double v0X; double v0Y; double l0; double victor01X; double victor01Y; double theta0; double vicTheta0; double vTheta0; double v1X; double v1Y; double l1; double victor10X; double victor10Y; double theta1; double vicTheta1; double vTheta1; double vicLength; double tempTheta1; double tempTheta2; while (!flag) { try { Thread.sleep(delay); //设置刷新时间 } catch (InterruptedException e) { e.printStackTrace(); } //更新该小球下一时间点的位置 balls.get(ballId).speedY += gravity; balls.get(ballId).ballX += balls.get(ballId).speedX; balls.get(ballId).ballY += balls.get(ballId).speedY; if (balls.get(ballId).ballX < 0) { balls.get(ballId).ballX = 0; balls.get(ballId).speedX = -balls.get(ballId).speedX; //反向运动 } else if (balls.get(ballId).ballX > (TABLE_WIDTH - balls.get(ballId).ballRadius * 2)) { balls.get(ballId).ballX = (TABLE_WIDTH - balls.get(ballId).ballRadius * 2); balls.get(ballId).speedX = -balls.get(ballId).speedX; //反向运动 } if (balls.get(ballId).ballY < 0) { balls.get(ballId).ballY = 0; balls.get(ballId).speedY = -balls.get(ballId).speedY; //反向运动 } else if (balls.get(ballId).ballY > (TABLE_HEIGHT - balls.get(ballId).ballRadius * 2)) { balls.get(ballId).ballY = (TABLE_HEIGHT - balls.get(ballId).ballRadius * 2); balls.get(ballId).speedY = -balls.get(ballId).speedY; //反向运动 } //更新该小球的速度属性 for (int j = 0; j < balls.size(); j++) { if (j > ballId && isTouched(ballId, j)) { //与所有其它小球进行碰撞检测 Ball ball0 = balls.get(ballId); Ball ball1 = balls.get(j); victor01X = ball1.getBallX() + ball1.getBallRadius() - (ball0.getBallX() + ball0.getBallRadius()); victor01Y = ball1.getBallY() + ball1.getBallRadius() - (ball0.getBallY() + ball0.getBallRadius()); vicTheta0 = Math.atan(victor01Y / victor01X); vicLength = Math.sqrt(Math.pow(victor01X, 2) + Math.pow(victor01Y, 2)); v0X = (double) ball0.getSpeedX(); v0Y = (double) ball0.getSpeedY(); l0 = Math.sqrt(Math.pow(v0X, 2) + Math.pow(v0Y, 2)); vTheta0 = Math.atan(v0Y / v0X); theta0 = Math.acos((v0X * victor01X + v0Y * victor01Y) / (l0 * vicLength)); if (vTheta0 > vicTheta0) { tempTheta1 = vicTheta0 + Math.PI - theta0; } else { tempTheta1 = vicTheta0 - Math.PI + theta0; } victor10X = -victor01X; victor10Y = -victor01Y; vicTheta1 = Math.atan(victor10Y / victor10X); v1X = (double) ball1.getSpeedX(); v1Y = (double) ball1.getSpeedY(); l1 = Math.sqrt(Math.pow(v1X, 2) + Math.pow(v1Y, 2)); vTheta1 = Math.atan(v1Y / v1X); theta1 = Math.acos((v1X * victor10X + v1Y * victor10Y) / (l1 * vicLength)); if (vTheta1 > vicTheta1) { tempTheta2 = vicTheta1 + Math.PI - theta1; } else { tempTheta2 = vicTheta1 - Math.PI + theta1; } ball0.speedX = (l1 * Math.cos(tempTheta2)); ball0.speedY = (l1 * Math.sin(tempTheta2)); ball1.speedX = (l0 * Math.cos(tempTheta1)); ball1.speedY = (l0 * Math.sin(tempTheta1)); } } } } } //自定义一个类继承Canvas充当画布 private class MyCanvas extends Canvas { public MyCanvas(int TABLE_WIDTH, int TABLE_HEIGHT) { this.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT)); } @Override public void paint(Graphics g) { //在这里绘制内容 if (flag) { //游戏结束 g.setColor(Color.BLUE); g.setFont(new Font("Times", Font.BOLD, 30)); g.drawString("游戏结束!", 80, 200); } else { //游戏中 //绘制小球 for (int i = 0; i < balls.size(); i++) { g.setColor(balls.get(i).color); g.fillOval((int) balls.get(i).ballX, (int) balls.get(i).ballY, balls.get(i).getBallRadius() * 2, balls.get(i).getBallRadius() * 2); } //绘制球拍 g.setColor(Color.PINK); g.fillRect(racketX, racketY, RACKET_WIDTH, RACKET_HEIGHT); } } } //创建绘画区域(桌面) MyCanvas myCanvas = new MyCanvas(TABLE_WIDTH, TABLE_HEIGHT); Timer timer = new Timer(delay, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { myCanvas.repaint(); } }); //组装视图以及游戏逻辑的控制 public void init() { //添加一系列小球 balls = new ArrayList (); for (int i = 0; i < num; i++) { balls.add(new Ball()); } //给球拍添加监听器以便控制球拍 MouseMotionListener mouseMotionListener = new MouseMotionAdapter() { @Override public void mouseMoved(MouseEvent e) { //获取当前鼠标位置 int mouseX = e.getX(); if (mouseX < (RACKET_WIDTH / 2)) { //设置球拍的位置 racketX = 0; } else if (mouseX > (TABLE_WIDTH - RACKET_WIDTH / 2)) { racketX = TABLE_WIDTH - RACKET_WIDTH; } else { racketX = mouseX - (RACKET_WIDTH / 2); } } }; //给frame和myCanvas注册监听器 myCanvas.addMouseMotionListener(mouseMotionListener); frame.addMouseMotionListener(mouseMotionListener); frame.add(myCanvas); //通过pack()方法设置最佳大小 frame.pack(); //设置frame可见 frame.setVisible(true); frame.setLocation(500, 200); //加入线程 timer.start(); for (int i = 0; i < balls.size(); i++) { new Thread(new BallMovement(i)).start(); } } public static void main(String[] args) { new BallsTest().init(); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)