1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > java如何实现多个小球碰撞后反弹以及绘制动态图。

java如何实现多个小球碰撞后反弹以及绘制动态图。

时间:2021-01-23 22:39:39

相关推荐

java如何实现多个小球碰撞后反弹以及绘制动态图。

本次小实验,通过三个类的编写来实现。首先创建一个点类,其中包含对点的构造方法和多个需要点的构造方法。

/*** 点类,表示平面中的点或始点为原点的向量* @author xxx**/public class Point {public double x=0.0; //x坐标或x分量public double y=0.0; //y坐标或y分量/*** 构造方法* @param x x坐标或x分量* @param y y坐标或y分量*/public Point(double x, double y) {this.x=x;this.y=y;}/*** 计算两点之间的距离* @param p0 点p0* @param p1 点p1* @return p0、p1之间的距离*/public static double distance(Point p0, Point p1) {double d = Math.sqrt(Math.pow(p1.x - p0.x, 2) + Math.pow(p1.y - p0.y, 2));return d;}/*** 计算过p0、p1两点的直线与x轴的夹角* @param p0 点p0* @param p1 点p1* @return 过p0、p1两点的直线与x轴的夹角(弧度)*/public static double angle(Point p0, Point p1) {return Math.atan2(p1.y-p0.y, p1.x-p0.x);}/*** 坐标系原点平移到p0,计算p1在新坐标系中的坐标* @param p0 原点移动到的位置* @param p1 需计算坐标的点* @return p1在新坐标系中的坐标*/public static Point translation(Point p0, Point p1) {return new Point(p1.x-p0.x, p1.y-p0.y);}/*** 坐标系绕原点旋转theta角度,计算p点的新坐标* @param p 点p* @param theta 坐标系旋转的角度(弧度)* @return p点在新坐标系中的坐标*/public static Point rotate(Point p, double theta) {double x1=p.x*Math.cos(theta)+p.y*Math.sin(theta);double y1=p.y*Math.cos(theta)-p.x*Math.sin(theta);return new Point(x1, y1);}}

其次,编写关于小球的类,其中包含小球的各个属性,以及边界碰撞检测,小球相互碰撞检测,碰撞后小球反弹等构造方法,以及绘制小球的类方法。

import java.awt.Color;import java.awt.Graphics;/*** 小球类,以圆表示平面中移动的小球** @author xxx**/public class Ball {Point c; // 圆心坐标double radius = 50; // 半径Point v; // 速度向量Color color ; // 颜色/*** 构造方法** @param cx 圆心x坐标* @param cy 圆心y坐标* @param vx x方向速度分量* @param vy y方向速度分量* @param color 小球颜色*/public Ball(double cx, double cy, double vx, double vy, Color color) {this.c = new Point(cx, cy);this.v = new Point(vx, vy);this.color = color;}/*** 移动小球*/public void move() {c.x += v.x;c.y += v.y;}/*** 边界检测,如超出或碰到边界,则修改小球的坐标及运动方向 左上角为坐标原点,需确保小球处于左上角坐标(0,0),宽width,高height的矩形内** @param width 矩形的宽* @param height 矩形的高*/public void checkBorder(double width, double height) {// 撞到左边if (c.x - radius <= 0) {c.x = radius;v.x = -v.x;}// 撞到右边if (c.x + radius >= width) {c.x = width - radius;v.x = -v.x;}// 撞到上边if (c.y - radius <= 0) {c.y = radius;v.y = -v.y;}// 撞到下边if (c.y + radius >= height) {c.y = height - radius;v.y = -v.y;}}/*** 检测两球是否碰撞** @param b1 小球1* @param b2 小球2* @return 相撞返回true,否则返回false*/public static boolean checkCollision(Ball b1, Ball b2) {// //编写如何判断两个小球的距离是否为0,即可看是否碰撞。// if(Point.distance(b1.c,b2.c)>0){// return false;// }// //若距离d<0,返回false,d>0,则返回true。// else {// return true;}double r=b2.radius;if (Point.distance(b1.c,b2.c)<=2*r){return true;}else {return false;}}/*** 改变相撞的两球的速度向量** @param b1 小球1* @param b2 小球2*/public static void change(Ball b1, Ball b2) {// 计算两球中心连线的角度double theta = Point.angle(b1.c,b2.c);// 坐标系绕原点旋转theta角度,计算两球新的速度向量b1.v = Point.rotate(b1.v,theta);b2.v = Point.rotate(b2.v,theta);//Point.translation(b1.c,b2.c)// 交换两球沿中心连线方向的速度double vxt ;vxt = b1.v.x;b1.v.x = b2.v.x;b2.v.x = vxt;// 将坐标系旋转回来,计算两球在原坐标系中的速度向量//Point.translation(b1.c,b2.c)b1.v = Point.rotate(b1.v,-theta);b2.v = Point.rotate(b2.v,-theta);}/*** 绘制小球** @param g Graphics对象*/public void draw(Graphics g) {g.setColor(color); // 设置画笔颜色int x = (int) (c.x - radius); // 外接矩形左上角x座标int y = (int) (c.y - radius); // 外接矩形左上角y座标int width = (int) radius * 2; // 外接矩形的宽度int height = (int) radius * 2; // 外接矩形的高度g.fillOval(x, y, width, height); // 给出椭圆的左上角坐标及宽高,绘制填充椭圆}}

最后,建立测试的主函数方法,定义面板和主窗口,在窗口中绘图,利用计时器实现小球的动态变换即可。

import java.awt.Color;import java.awt.Graphics;import javax.swing.JFrame;import javax.swing.JPanel;import java.util.Timer;import java.util.TimerTask;@SuppressWarnings("serial")class MainPanel extends JPanel {// 定义面板类Ball[] balls; // 小球数组public MainPanel() {balls = new Ball[5]; // 五个小球balls[0] = new Ball(10, 10, 2, 5, Color.YELLOW);balls[1] = new Ball(120, 100, 3, 2, Color.BLUE);balls[2] = new Ball(150, 50, 4, 1, Color.RED);balls[3] = new Ball(250, 0, 5, 3,Color.pink);balls[4] = new Ball(300, 200, 6, 4,Color.green);}@Overridepublic void paintComponent(Graphics g) {// 在paint方法中绘图super.paintComponent(g);// 边界和碰撞检测for (Ball b1 : balls) {b1.checkBorder(this.getWidth(), this.getHeight()); // 边界检测for (Ball b2 : balls) {// 碰撞检测if (b1 != b2 && Ball.checkCollision(b1, b2)) {Ball.change(b1, b2); // 改变两球的速度b1.move(); // 将两球移开一点距离b2.move();}}}// 移动并绘制小球for (Ball b : balls) {b.move(); // 移动小球b.draw(g); // 绘制小球}}}@SuppressWarnings("serial")class GameWindow extends JFrame {// 主窗口类MainPanel panel; // 面板Timer timer; // 计时器TimerTask task; // 任务public GameWindow() {super("测试窗口");panel = new MainPanel(); // 创建面板对象this.add(panel); // 将面板加到窗口中task = new TimerTask() {// 创建任务对象@Overridepublic void run() {// 执行任务要做的事情在此方法中编写panel.repaint(); // 重绘面板刷新}};timer = new Timer(); // 创建计时器timer.schedule(task, 0, 10); // 延迟0秒后每隔10毫秒执行一次任务setBounds(200, 100, 800, 600); // 设置窗口的位置及大小setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置窗口的关闭操作setVisible(true); // 使窗口可见}}public class Test {public static void main(String[] args) {new GameWindow(); // 创建窗口对象,显示窗口}}

【这是本人在校第一次写CSDN,之后还会分享很多在校期间学习到的小实验,仅供参考,若哪不对欢迎指正。最后强调,可免费使用代码,但编写不易,点个关注和小心心再走呗!】

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。