前面已经实现了一个球在一个窗口中随机运动,下面将在前面的基础上实现两个球的随机运动及碰撞,此次的代码中用到的算法参考了Twinsen写的一文中关于两球碰撞时的算法.程序仍旧有两个类,一个Ball类,一个BallCanvas类,Ball类与前面相同,而BallCanvas类作了修改,修改后的代码如下:

import java.awt.Canvas;

import java.awt.Color;

import java.awt.Graphics;

import java.util.Random;

public class BallCanvas extends Canvas implements Runnable {

private int ballRadius = 40;   //球的半径

private int ballAX,ballAY;        //当前A,B球的位置

private int ballBX,ballBY;

private double ballAXMoveLength= 7;     //A,B球当前速度在X,Y轴上的分速度

private double ballAYMoveLength = 9;    //为了减少计算中数据丢失,用double型而不用int型

private double ballBXMoveLength = 6;    //

private double ballBYMoveLength = 5;     //如果用int型两球最终将停止运动

private Random r;

private boolean move = true;       //标志球是否移动

private int screenWidth, screenHeight;        //屏幕宽及高

private int ballARX, ballARY;  //A球圆心位置

private int ballBRX, ballBRY;   //B球圆心位置

public BallCanvas(int screenWidth, int screenHeight){

r = new Random();

ballAX = r.nextInt(screenWidth – 2*ballRadius);     //随机初始化A球的初始位置

ballAY = r.nextInt(screenHeight – 2*ballRadius);

do{        //随机初始化B球的初始位置,且确定A球跟B球不发生碰撞

ballBX = r.nextInt(screenWidth – 2*ballRadius);

ballBY = r.nextInt(screenHeight – 2*ballRadius);

}while((int)Math.sqrt((ballAX-ballBX)*(ballAX-ballBX) +

(ballAY-ballBY)*(ballAY-ballBY)) < 2*ballRadius);

this.screenHeight = screenHeight;

this.screenWidth = screenWidth;

}

public void paint(Graphics g){

//g.setColor(Color.WHITE);            //此处使用背景色而不用白色,如果要自己清空屏幕,则需加上缓存,不然会产生画面抖动

//g.fillRect(0, 0, screenWidth, screenHeight);

g.setColor(Color.RED);

g.fillArc((int)ballAX, (int)ballAY, (int)ballRadius*2, (int)ballRadius*2, 0, 360);

g.fillArc((int)ballBX, (int)ballBY,(int) ballRadius*2, (int)ballRadius*2, 0, 360);

}

/**

* 退出

*/

public void exit(){

move = false;

}

public void run(){

while(move){

//处理A球

if(ballAX + ballAXMoveLength + 2*ballRadius > screenWidth ||

ballAX + ballAXMoveLength < 0){         //当在X轴上碰到墙时,X轴行进方向改变

ballAXMoveLength*=-1;

}else{

ballAX += ballAXMoveLength;                 //没碰壁时继续前进

}

if(ballAY + ballAYMoveLength + 2*ballRadius > screenHeight ||

ballAY + ballAYMoveLength < 0){         //当在Y轴上碰到墙时,Y轴行进方向改变

ballAYMoveLength*=-1;

}else{

ballAY += ballAYMoveLength;

}

//处理B球

if(ballBX + ballBXMoveLength + 2*ballRadius > screenWidth ||

ballBX + ballBXMoveLength < 0){         //当在X轴上碰到墙时,X轴行进方向改变

ballBXMoveLength*=-1;

}else{

ballBX += ballBXMoveLength;                 //没碰壁时继续前进

}

if(ballBY + ballBYMoveLength + 2*ballRadius > screenHeight ||

ballBY + ballBYMoveLength < 0){         //当在Y轴上碰到墙时,Y轴行进方向改变

ballBYMoveLength*=-1;

}else{

ballBY += ballBYMoveLength;

}

ballsCollide();   //检查两球是否碰撞

repaint();    //更新画面

try{

Thread.sleep(10);

}catch(InterruptedException e){

}

}

}

/**

* 检查并处理两球碰撞

* 此处用向量来计算两球碰撞后的速度,具体算法分析请参见”向量几何在游戏编程中的使用”

*/

public void ballsCollide(){

if(Math.sqrt((ballAX-ballBX)*(ballAX-ballBX) +              //并没有产生碰撞

(ballAY-ballBY)*(ballAY-ballBY)) > 2*ballRadius){

return;

}else{           //碰撞了

ballARX = ballAX + ballRadius;  //A球圆心位置

ballARY = ballAY + ballRadius;

ballBRX = ballBX + ballRadius;   //B球圆心位置

ballBRY = ballBY + ballRadius;

// 求出s'(球心连线上的向量)

double sx = ballARX – ballBRX ;

double sy = ballARY – ballBRY ;

// 求出s1(球心连线上的单位向量)

double s1x = sx / Math.sqrt(sx*sx + sy*sy) ;

double s1y = sy / Math.sqrt(sx*sx + sy*sy) ;

// 求出t'(与球心连线垂直的向量)

double tx = -sy ;

double ty = sx ;

// 求出t1(与球心连线垂直的单位向量)

double t1x = tx / Math.sqrt(tx*tx + ty*ty) ;

double t1y = ty / Math.sqrt(tx*tx + ty*ty) ;

// 求v1a在s1上的投影v1s

double v1s = ballAXMoveLength * s1x + ballAYMoveLength * s1y ;

// 求v1a在t1上的投影v1t

double v1t = ballAXMoveLength * t1x + ballAYMoveLength * t1y ;

// 求v2a在s1上的投影v2s

double v2s = ballBXMoveLength * s1x + ballBYMoveLength * s1y ;

// 求v2a在t1上的投影v2t

double v2t = ballBXMoveLength * t1x + ballBYMoveLength * t1y ;

// 用公式求出v1sf和v2sf

double v1sf = v2s ;

double v2sf = v1s ;

// 最后一步,注意这里我们简化一下,直接将v1sf,v1t和v2sf,v2t投影到x,y轴上,也就是v1’和v2’在x,y轴上的分量

// 先将v1sf和v1t转化为向量

double nsx = v1sf * s1x ;

double nsy = v1sf * s1y ;

double ntx = v1t * t1x ;

double nty = v1t * t1y ;

ballAXMoveLength =(nsx + ntx) ;

ballAYMoveLength =(nsy + nty) ;

// 然后将v2sf和v2t转化为向量

nsx = v2sf * s1x ;

nsy = v2sf * s1y ;

ntx = v2t * t1x ;

nty = v2t * t1y ;

ballBXMoveLength = (nsx + ntx );

ballBYMoveLength =(nsy + nty );

//碰撞之后两球速度变化了,可是两球的位置仍处于碰撞时的位置,此时可能导致程序误以后两球再次发生碰撞

//于是再次处理碰撞,造成程序的死循环,故碰撞后,两球应该以碰撞后的速度迅速产生一段距离避免碰撞的状态

while(Math.sqrt((ballAX-ballBX)*(ballAX-ballBX) +              //仍旧处于碰撞时的位置

(ballAY-ballBY)*(ballAY-ballBY)) < 2*ballRadius){

if(ballAX + ballAXMoveLength + 2*ballRadius > screenWidth ||

ballAX + ballAXMoveLength < 0){         //当在X轴上碰到墙时,X轴行进方向改变

ballAXMoveLength*=-1;

}else{

ballAX += ballAXMoveLength;                 //没碰壁时继续前进

}

if(ballAY + ballAYMoveLength + 2*ballRadius > screenHeight ||

ballAY + ballAYMoveLength < 0){         //当在Y轴上碰到墙时,Y轴行进方向改变

ballAYMoveLength*=-1;

}else{

ballAY += ballAYMoveLength;

}

if(ballBX + ballBXMoveLength + 2*ballRadius > screenWidth ||

ballBX + ballBXMoveLength < 0){         //当在X轴上碰到墙时,X轴行进方向改变

ballBXMoveLength*=-1;

}else{

ballBX += ballBXMoveLength;                 //没碰壁时继续前进

}

if(ballBY + ballBYMoveLength + 2*ballRadius > screenHeight ||

ballBY + ballBYMoveLength < 0){         //当在Y轴上碰到墙时,Y轴行进方向改变

ballBYMoveLength*=-1;

}else{

ballBY += ballBYMoveLength;

}

}

}

}

/**

* 重新调整屏幕大小

*/

public void canvasResize(){

screenWidth = this.getWidth();

screenHeight = this.getHeight();

}

}

Java如何让小球随机运动_用java模拟两球的随机运动及碰撞相关推荐

  1. 【源码+图片素材】Java王者荣耀游戏开发_开发Java游戏项目【王者荣耀】1天搞定!!!腾讯游戏_Java课程设计_Java实战项目_Java初级项目

    王者荣耀是当下热门手游之一,小伙伴们是否想过如何制作一款属于自己的王者荣耀游戏呢? 本课程讲解了一个王者荣耀游戏的详细编写流程,即使你是刚入门Java的新手,只要你简单掌握了该游戏所需要的JavaSE ...

  2. java课后习题七解析_《Java基础入门》_课后习题解析.doc

    <Java基础入门>_课后习题解析 <Java基础入门>课后习题 Java开发入门 一.填空题 1.Java的三大体系分别是_JavaSE_____._JavaEE_____. ...

  3. java jsp取静态常量_获取java静态

    Android NDK开发系列教程4:对类变量进行操作 终于建了一个自己个人小站:https://huangtianyu.gitee.io,以后优先更新小站博客,欢迎进站,O(∩_∩)O~~ 通常我们 ...

  4. java课后习题及答案_《java基础入门》课后习题及答案.doc

    <java基础入门>课后习题及答案.doc <Java 基础入门>课后习题及答案博学谷--让 IT 教学更简单,让 IT 学习更有效<Java 基础入门> 课后习题 ...

  5. java的关键字和保留字_「Java」详解常见的53个关键字

    1.在Java中目前一共有53个关键字: 其中由51+2个保留字=53个关键字 [友情提示 : Java的关键字都是小写哟] 2.Java的保留字有多少个?分别是什么? 答:Java的保留字有2个,J ...

  6. java基础入门课后习题_《Java基础入门》课后习题及答案

    <Java基础入门>课后习题及答案Java基础入门,课后习题,答案 博学谷--让IT教学更简单,让IT学习更有效 <Java基础入门>课后习题 第1章Java开发入门 一.填空 ...

  7. java ug二次开发_使用Java进行UG二次开发:简单的例子(上) | 学步园

    最近因为要进行TeamCenter二次开发(胖客户端定制),所有要开始研究Java了.因此突发奇想为什么不能使用Java进行二次开发呢?现在对UG进行的开发以C/C++应用为主.大多数使用的是原来的U ...

  8. java字符串拆分成数组_用Java实现JVM第八章《数组和字符串》

    小傅哥 | https://bugstack.cn 沉淀.分享.成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获.目前已完成的专题有:Netty4.x实战专题案例.用J ...

  9. java状态模式例子答案_[转载]java设计模式_状态模式(带例子)

    状态模式(STATE) Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循一定的编 ...

最新文章

  1. linux下的文件和文件夹的权限问题
  2. Serial Communications in Win32
  3. Java基础20:Java8新特性终极指南
  4. vim 初学简单设置
  5. 对python来说、一个模块就是一个文件-Python如何将将模块分割成多个文件
  6. 概率编程库Pymc3案例之Coal mining disasters
  7. 前端学习(1360) :学生档案信息管理2
  8. uniapp中自定义导航栏动态获取高度
  9. 常说的「缓存穿透」和「击穿」是什么
  10. 【机器学习实验】scikit-learn的主要模块和基本使用
  11. STM32CubeMX——霍尔编码器、L298N驱动电机
  12. Mac系统文件在Win解压乱码问题
  13. 基于android的智慧停车app
  14. 路由器——计算机网络
  15. 2.12 二项式系数加法解 C实现
  16. php数组函数array flip,PHP array_flip() 函数
  17. 中国房价为什么会居高不下?
  18. 基本数据类型有哪些?
  19. Vue移动端项目(二)
  20. 异常与处理--python

热门文章

  1. 虚拟机的分类_「面试必备」Java虚拟机知识点复习手册(下)
  2. ibm3650m2 如何安装linux4,System x3650M2 (Type 7947) Windows Server 2008安装指南
  3. androidstuido 查看logs_使用 Logcat 写入和查看日志
  4. python编写星号菱形中间是空的_简单空实心图形打印|Python练习系列[3]
  5. 两个整数百分百C语言,2011年9月份计算机二级C语言上机题库(百分百准确),,,[1]
  6. 中央空调如何调节温度html,中央空调怎么调温度
  7. layui动态添加input_layer.prompt添加多个输入框
  8. 最小二乘法与最大似然函数的区别
  9. 指定某行复制多次的方法
  10. java整合mybatis,springboot集成mybatis