项目需求:
- 屏幕中出现100个小球进行碰撞运动,完全覆盖的话就吃掉小球。
小球类,Ball.java:
- 小球类中包含小球的属性,初始化构造器,移动方法,绘制方法,和大球吃小球的方法。
- 小球的位置,大小直径都是随机的
- 移动速度,offsetx 和 offsety 也都是随机的,小于0.5就往上移动,大于0.5往下移动。
public class Ball {
double x; //x坐标
double y; //y坐标
int d; //直径
int r; //rgb颜色
int g;
int b;
Color color; // 红黄蓝取颜色的值
double offsetX; //移动的值
double offsetY; //移动的值
//构造器,调用小球类自动执行,初始化小球数据
public Ball(){
d = (int)(Math.random()*(40-2)+2);
x = Math.random()*800-d;
y = Math.random()*600-d;
r = (int)(Math.random()*256);
g = (int)(Math.random()*256);
b = (int)(Math.random()*256);
color = new Color(r,g,b);
offsetX = Math.random()*(6-1)+1;
offsetY = Math.random()*(6-1)+1;
offsetX = Math.random()< 0.5 ? offsetX : -offsetX;
offsetY = Math.random()< 0.5 ? offsetY : -offsetY;
}
public void paint(Graphics2D g){
g.setColor(color);
g.fillOval((int)x,(int)y,d,d);
}
}
移动方法
public void move(){
x += offsetX;
y += offsetY;
if(x>800-d){
offsetX = -offsetX;
x = 800-d;
}else if(y>600-d){
offsetY = -offsetY;
y = 600-d;
}else if(x<0){
offsetX = -offsetX;
x=0;
}else if (y<0){
offsetY = -offsetY;
y=0;
}
}
- 800*600为宽高,大于800就反弹回来。
- 因为double数据有差值,可能会出现溜边的情况,x=800-d就是强行扳回来
吃小球类
- 通过两个球的圆心距来判断是否为包含关系,如果包含就吃掉。
public boolean eaten(Ball ball){
double X = x, Y = y, D = this.d; //大球
double x=ball.x, y=ball.y, d=ball.d; //小球
// int red=ball.r,green = ball.g, blue = ball.b;
Color newColor = ball.color;
//检查球的直径是否合理
if(d > D){
return false; //直径不合理,不进行进一步比较
}
//利用勾股定理计算两个球之间的距离
double a = (X+D/2) - (x+d/2);
double b = (Y+D/2) - (y+d/2);
double c = Math.sqrt(a*a + b*b);
boolean eaten = c < D/2-d/2;
//如果发生吃了,就进行合并
if(eaten){
//计算合并后的圆面积
double R = D/2,r = d/2;
double area = Math.PI*R*R + Math.PI*r*r;
double rx = Math.sqrt(area/Math.PI);
this.d = (int) rx*2; //替换当前圆的直径
this.color = newColor;
}
return eaten;
}
执行方法类 BallApp.java
public class BallApp extends App {
Ball[] balls = new Ball[100];
public BallApp(){
for (int i = 0;i<balls.length;i++){
balls[i] = new Ball();
}
}
@Override
public void painting(Graphics2D g) {
for (int i =0;i<balls.length;i++){
balls[i].move();
balls[i].paint(g);
}
eating();
// g.drawOval(22,60,10,10); 圆圈
}
public void eating(){
//大球和小球
Ball[] big = balls;
Ball[] small = balls;
boolean[] eaten = new boolean[small.length]; //创建了吃掉标志,默认都是false,表示没吃掉。boolean默认false
int n = 0; //记录有几个球被吃掉了
for (int i = 0;i<big.length;i++){
//每一个大球
//如果大球已经被吃掉了,就忽略
if(eaten[i]){
continue;
}
for (int j=0;j<small.length;j++){
//每一个小球
//球不能吃自己
if(big[i]==small[j]){
continue;
}
//如果小球被吃掉就忽略
if(eaten[j]){
continue;
}
if(big[i].eaten(small[j])){
System.out.println("吃...");
System.out.println(big[i].x+ ","+big[i].y+ ","+big[i].d);
System.out.println(small[j].x+ ","+small[j].y+ ","+small[j].d);
//把小球的位置设置为true
eaten[j] = true;
n++;
}
}
}
System.out.println(Arrays.toString(eaten));
System.out.println(n);
if(n==0){
//什么都没吃掉
return;
}
//缩容处理
Ball[] arr = new Ball[small.length]; //此时为新数组,但都为空
int index = 0;
for (int i =0;i<small.length; i++){
if (!eaten[i]){
//如果index不为true
arr[index++] = small[i]; //就放入arr中,不为true的元素都放进了数组,后面的部分为0
// index++;
}
}
System.out.println(Arrays.toString(arr));
balls = Arrays.copyOf(arr,arr.length-n); //缩容处理,并替换原数组
}
public static void main(String[] args) {
BallApp app = new BallApp();
app.start();
}
}
- 给小球数组创建eaten被吃的标志,然后把没被吃的小球放在新数组,被吃的小球就变成了最后的0,在进行缩容处理,把这些0去掉。