Java如何让小球随机运动_用java模拟两球的随机运动及碰撞
前面已經實現了一個球在一個窗口中隨機運動,下面將在前面的基礎上實現兩個球的隨機運動及碰撞,此次的代碼中用到的算法參考了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模拟两球的随机运动及碰撞的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java游戏+弹幕_JAVA 弹幕小游戏
- 下一篇: settime java import_