import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class GGame extends JPanel {
GGame(){
//生成100个小球
for (int i = 0; i <100 ; i++) {
//创建一个小球对象
Ball b=new Ball();
//每次循环将创建好的小球对象放置到数组对应的位置
balls[i]=b;
}
}
// 宽度
// 修饰词: final static
public final static int width = 1200;
public final static int height =700;
// 创建一堆Ball小球 = 小球数组,存储了100个小球对象
Ball[] balls =new Ball[100];
// alt + /?
// main函数(方法) 程序的入口函数
public static void main(String[] args) {
// //开始画窗口
// 1.1 . 画框
JFrame jframe = new JFrame();
// 1.2 画板
JPanel jpanel = new GGame();
// 1.3 将画板放置到画框中
jframe.add(jpanel);
// 2. 设置画框主题
jframe.setTitle("这是我的第一个小游戏");
// 3. 让画框显示 true 表示显示,默认是false不显示
jframe.setVisible(true);
// 4. 设置画框的尺寸
jframe.setSize(width,height);
// 5. 设置画框的位置
jframe.setLocationRelativeTo(null);
// 6. 设置默认关闭方式 3 代表就是关闭即退出7
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// @Override 表示重写,是子类不满足父类的功能,自己来实现的过程
// 方法重写是指子类中定义了一个与父类中同名、同参数列表、同返回类型的方法,且子类方法的访问权限不能低于父类方法的访问权限
@Override
public void paint(Graphics g) {
// g表示的就是画笔
// 1. 画背景
// 1.1 获取图片对象
File file =new File("src/background.jpg");
// 1.2 开始画图片
try {
g.drawImage(ImageIO.read(file), 0,0,null);
} catch (IOException e) {
throw new RuntimeException(e);
}
Date date=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("YYYY年MM月dd日 HH:mm:ss");
String time=sdf.format(date);
// 画字符串:使用黄色
g.setColor(Color.yellow);
// 设置字体
g.setFont(new Font("黑体",Font.BOLD,30));
g.drawString("作者:zyz",50, 30 );
g.drawString("项目:泡泡大战",50, 70 );
g.drawString("时间:"+time,50,110);
g.drawString("当前小球个数:"+balls.length,50,150);
// 给画笔设置颜色: 红色
g.setColor(Color.red);
// 通过使用for循环,获取数组中的每一个小球
for (int i = 0; i <balls.length; i++) {
//让数组中的每一个小球开始移动
balls[i].step();
//把数组中的每个小球画在画板上
balls[i].drawBall(g);
}
//启动碰撞判断的方法
action(balls,balls);
// 重复画,表示当前界面的内容会按照内置的间隔时间进行画内容
repaint();
}
//进行小球碰撞后确定下一次该出现多少小球
public void action(Ball[] big,Ball[] small){
//创建标记数组,当前和当前数组相同
boolean[] flag=new boolean[balls.length ];//flag中存储100个false
//计数
int num=0;
//遍历所有的大球
for (int i = 0; i < big.length; i++) {
//如果当前的球被吃掉了,不要进行isHit碰撞的判断
if (flag[i]){
continue;//跳过当前循环,执行下一次循环
}
// 遍历所有的小球
for (int j = 0; j <small.length ; j++) {
if (flag[j]){
continue;//跳过当前循环,执行下一次循环
}
//是同一个,不需要进行isHit的判断
if (i==j){
continue;//跳过当前循环,执行下一次循环
}
if (big[i].isHit(small[j])){
//程序能够执行到此说明大球是吃掉小球
flag[j]=true;
//被吃掉的小球计数+1
num++;
}
}
}
System.out.println("被吃掉的小球个数:"+num);
//创建一个新的100个长度的小球数组
Ball[] newBalls= new Ball[balls.length ];
//控制新数组的下标
int index=0;
for (int i = 0; i <balls.length ; i++) {
if(!flag[i]){
//i位置没有被标记的小球(没被吃掉了) 标记是:false
newBalls[index]=small[i];
index++;
}
}
//做缩容,第一个参数是要被缩容的数组,第二个参数长度
//balls是当前类声明的成员变量,也是整个游戏窗口中运行的所有小球数组(其中一定不包含那些被吃掉的)
balls = Arrays.copyOf(newBalls,newBalls.length-num);
}
}
import com.sun.org.apache.xerces.internal.impl.xpath.XPath;
import java.awt.*;
import java.util.Random;
//这是小球的模版
public class Ball {
public static void main(String[] args) {
//创建小球对象
Ball b1 = new Ball();
Ball b2 = new Ball();
Ball b3 = new Ball();
}
//当前的方法是Ball类的构造方法
Ball() {
Random r = new Random();
//生成50到200之间的整数
//r.nextInt(150)的最小值是0
//r.nextInt(150)最大值是150
width = r.nextInt(100) + 20;
big_d = width;
x = r.nextInt(1200- big_d);
y = r.nextInt(700 - big_d);
//速度的大小
offx = r.nextInt(20) + 5;
offy = r.nextInt(20) + 5;
int flag = r.nextInt(10);
// 对生成的随机数进行判断
if (flag > 5) {
offx = offx;
offy = offy;
} else {
offx = -offx;
offy = -offy;
}
//颜色的随机数
int red = r.nextInt(255);
int green = r.nextInt(255);
int blue = r.nextInt(255);
color = new Color(red, green, blue);
}
int big_d;
// 位置
int width;
int height;
int x;
int y;
//速度
int offx;
int offy;
Color color;
//行为;小球移动的方法
public void step() {
// 改变变量的值
x = x + offx;
y = y + offy;
// 界限判断 左右界限
if (x > 1200- big_d) {
offx = -offx;
x = 1200 - big_d;
}
if (x < 0) {
offx = -offx;
x = 0;
}
// 界限判断 上下界限
if (y >700 -big_d) {
offy = -offy;
y = 700 - big_d;
}
if (y < 0) {
offy = -offy;
y = 0;
}
}
// 小球画画的方法
public void drawBall(Graphics g) {
//g当前方法的画笔
//给画笔设置随机色
g.setColor(color);
//使用设置了随机色的画笔画圆
g.fillOval(x, y, big_d, big_d);
}
//小球碰撞的方法
public boolean isHit(Ball other) {
//大球数据
int X= this.x, Y= this.y, D= this.width, R = D/2;
//小球数据
int x= other.x, y= other.y, d= other.width, r = d/2;
//求两个直角边的长度
int A=(Y+R)-(y-r);
int B=(x+r)-(X+R);
//通过两个直角边计算斜边的长度
double len=Math.sqrt((A*A)+(B*B));
//圆心距
if(len<=R-r){
//计算大圆的面积
double area1=Math.PI*R*R;
//计算小圆的面积
double area2=Math.PI*r*r;
//计算最终大圆的半径
double new_r =Math.sqrt( (area1+area2)/Math.PI);
//计算最终大圆的直径(宽度)
big_d=(int)(2*new_r);
//大球吃了小球
return true;
}
//没有发生碰撞,不能被吃掉
return false;
}
}