在B站学了好几天,终于搞通了,能跑了,捕鱼的小游戏~
下面分步骤跟大家说说呗~~~
/**
* Java中的窗体类:JFrame(游戏的支架)用来固定游戏界面
* 自定义窗体的固定步骤:
* 1.创建一个任意的类
* 2.继承JFarme类
* 3.写一个构造器,确定窗体的特征
* @author Mr.Wang
*/
public class GameFrame extends JFrame {
//构造器与类同名,并且不能有返回值,也不能有viod
//作用:相当于一个模具,用来物体定性
public GameFrame(){
//设置一个窗体的标题
setTitle("三天打鱼两天晒网");
//设置尺寸
setSize(800 ,480);
//对窗体设置默认关闭(点击关闭,自动终止)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置游戏窗体居中显示
setLocationRelativeTo(null);
}
//程序入口
public static void main(String[] args) {
//使用模具,创建游戏框体
//格式:类名 对象名 = 类名();
//创建出窗体对象
GameFrame frame =new GameFrame();
//创建游戏画板对象
GamePanel panel =new GamePanel();
//在窗体中添加画板
frame.add(panel);
//开始游戏
panel.anction();
//显示窗体 true为显示 false为隐藏
frame.setVisible(true);
}
}
/**
* Java中常用的面板:JPanel 鱼塘
* 自定义画板的步骤
* 1.定义一个任意的类
* 2.继承JPanel类
* 3.写一个偶构造器,确定面板的特点
*
*
* @author Mr.Wang
*/
public class GamePanel extends JPanel {
//定义一张背景图
BufferedImage bg;
//定义一条鱼
//Fish fish = new Fish();
//定义鱼塘中,鱼的总数(如果,需要改变鱼的数量,就改变此变量)
int fishNum = 50;
//鱼的集合,池塘里所有的鱼都存在集合中
List<Fish> fishers =new ArrayList<Fish>();
//定义一张渔网
Net net = new Net();
//定义一个渔网显示的标识
boolean netShow = true;
//构造方法
public GamePanel(){
//设置背景色
setBackground(Color.pink);
//使用工具类,去读取指定路径下的图片
bg = ImageUtil.getImg("../img/bg.jpg");
//创建所有的鱼,装到集合中.for while do..while 三个循环之间的关系
for(int i=0;i<fishNum;i++){
//将鱼装入到集合中
fishers.add(new Fish(this));
}
//开启鼠标监听器
createMouseListener();
}
//游戏开始的方法
public void anction(){
//让每一条鱼都动起来
for(int i=0;i<fishNum;i++){
//获取每一条鱼
Fish fish = fishers.get(i);
fish.start();
}
}
//创建一个鼠标监听器,用来监听鼠标的活动
public void createMouseListener(){
//创建一个鼠标适配器
MouseAdapter adapter =new MouseAdapter() {
//使用匿名内部类
//监听鼠标移动事件
@Override
public void mouseMoved(MouseEvent e){
//获取鼠标移动的位置
int mouse_x =e.getX();
int mouse_y =e.getY();
//让渔网跟随鼠标移动
net.x =mouse_x - net.w/2;
net.y =mouse_y - net.h/2;
//刷新界面
repaint();
}
//鼠标移出事件 当鼠标移出画板,不现实渔网
@Override
public void mouseExited(MouseEvent e) {
//隐藏渔网
netShow =false;
//刷新
repaint();
}
//鼠标切入事件 当鼠标重新切入画板,现实渔网
@Override
public void mouseEntered(MouseEvent e){
//显示渔网
netShow =true;
//刷新
repaint();
}
//鼠标点击事件
@Override
public void mouseClicked(MouseEvent e) {
//获取鼠标点击时对应的数字
int key =e.getModifiers();
System.out.println(key);
//点击左键时,key=16,点击右键时,key=4
//通过key值,判断出鼠标点击的是左键还是右键
//左键捕鱼,右键增加火力(切换渔网)
if(key==16){
//TODO 捕鱼
catchFish();
}
if(key==4){
//切换渔网,增加火力
changeNet();
//重新获取鼠标的位置
int mouse_x =e.getX();
int mouse_y =e.getY();
//让渔网重新跟随鼠标
net.x =mouse_x - net.w/2;
net.y =mouse_y - net.h/2;
}
}
};
//将鼠标适配器加入到监听器中
addMouseMotionListener(adapter);
addMouseListener(adapter);
}
//捕鱼的方法
public void catchFish(){
//遍历所有的鱼,和渔网发生碰撞
for(int i=0;i<fishNum;i++){
//获取每一条鱼
Fish fish = fishers.get(i);
//发生碰撞
if(net.catchFish(fish)){
//捕到鱼了
//将鱼的状态改为捕获状态
fish.catched=true;
}
}
}
//改变渔网,增大火力
//初始化火力值
int power = 1;
private void changeNet() {
// TODO Auto-generated method stub
//火力值增加
power++;
//使用三目运算符,控制火力范围
//当火力大于7时,重新回到1
power = power>7?1:power;
//根据火力值,来选择对应的渔网
net.change(power);
}
//画图的方法,g相当于画笔
@Override
public void paint(Graphics g) {
//画背景图
//g.drawImage(bg ,0 ,0 ,null)
g.drawImage(bg, 0, 0, null);
//绘制所有的鱼
for (int i = 0; i < fishNum; i++) {
//从集合中获取一条鱼
Fish fish = fishers.get(i);
//绘制一条
g.drawImage(fish.img, fish.x, fish.y, fish.w, fish.h, null);
}
//设置画笔颜色
g.setColor(Color.GREEN);
//设置字体
g.setFont(new Font("楷体", Font.BOLD, 20));
//绘制分数
//g.drawString(文字内容,横坐标,纵坐标);
g.drawString("分数:0", 20, 30);
//绘制子弹数
g.drawString("子弹数:100", 300, 30);
//绘制活力值
g.drawString("火力值:" + power, 620, 30);
g.drawString("点击鼠标右键增加火力", 550, 60);
if(netShow){
//绘制渔网
g.drawImage(net.img, net.x,net.y,net.w,net.h,null);
}
}
}
/**
* 鱼类(我们游戏的主角)
*
*
* @author Mr.Wang
* */
public class Fish extends Thread{
//特点(特征),就是属性
//鱼的图片
BufferedImage img;
//鱼的横坐标
int x;
//鱼的纵坐标
int y;
//鱼的宽度
int w;
//鱼的高度
int h;
//随机数对象
Random ran = new Random();
//定义鱼游动的图片
List<BufferedImage> animation =new ArrayList<BufferedImage>();
//定义一个面板
GamePanel panel;
//鱼的状态,定义是否被捕
boolean catched =false;
//定义一个鱼被捕的动画集合
List<BufferedImage> catchAnimation =new ArrayList<BufferedImage>();
//定义一个鱼被捕的动画数量
int catchNum;
//使用模具,对鱼的特征进行设置
public Fish(GamePanel panel){
//this 指代当前对象
this.panel =panel;
//随机鱼的种类
int index = ran.nextInt(9) + 1;//[1-9]
//拼接鱼种类的名字
String fishName = "../img/fish0" + index + "_";
//加载鱼游动时的图片
for(int i=1;i<11;i++){
//小于10的时候,是01、02、03。。。10,,,,布尔运算
String prefix = (i==10?"":"0") + i;//三元运算符
//拼接完整的图片路径
String path =fishName + prefix + ".png";
//使用工具类,读取图片
BufferedImage img = ImageUtil.getImg(path);
//装入集合
animation.add(img);
}
//初始化,鱼被捕时的状态数量
catchNum = index <=7?2:4;
//将鱼被捕时的动画图片,装到集合中
for(int i= 1;i<=catchNum;i++){
//拼接图片路径
String path =fishName + "catch_0" +i +".png";
//根据路径,加载图片
BufferedImage img =ImageUtil.getImg(path);
//添加到集合中
catchAnimation.add(img);
}
//确定,鱼显示的图片
img = animation.get(0);
//获取鱼的宽度
w = img.getWidth();
//获取鱼的高度
h = img.getHeight();
//x[0,n-1]
x = ran.nextInt(800 - w);
//y
y = ran.nextInt(480 - h);
}
//鱼移动的步数
int step_num = 0;
//鱼移动的方法
public void move(){
step_num++;
//切换图片
img =animation.get(step_num%10);//模运算,不大于10
//重新获取,切换后图片的高度
w = img.getWidth();
//宽度
h = img.getHeight();
//鱼向左移动
x -= ran.nextInt(3)+1;
//边界的判断
if(x<=-w){
//重新出现在鱼塘右边
x = 800;
y = ran.nextInt(480-h);
}
}
/**
* 线程启动时,会执行的方法
* */
@Override
public void run(){
/**
* 死循环,让鱼一直动,一直移动到死
* */
for(;;){
//检查鱼,是否被捕获
if(catched){
//显示鱼被捕的动画
fishOver();
//被捕的鱼出场,从右侧从新入场
x = 800;
y = ran.nextInt(480-h);
}
//调用鱼的移动
move();
//线程休眠一会儿
try {
Thread.sleep(150);
//刷新一下
panel.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//鱼被捕的动画
private void fishOver() {
//让动画多循环几次
for(int j=0;j<3;j++)
//从集合中遍历出动画图片
for(int i =0;i<catchNum;i++){
img =catchAnimation.get(i);
w=img.getWidth();
h=img.getHeight();
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
/**
* 渔网类
* @author Mr.Wang
* */
public class Net {
//渔网的图片
BufferedImage img;
//渔网的横坐标
int x;
//渔网的纵坐标
int y;
//渔网的宽度
int w;
//渔网的高度
int h;
//成员变量和局部变量的区别 位置 作用域 存储空间 声明周期
//使用构造器(模具),来初始化属性
public Net(){
//确定渔网的图片
img = ImageUtil.getImg("../img/net_1.png");
//确定渔网大小
w = img.getWidth();
h = img.getHeight();
//确定渔网的初始位置,游戏开始,渔网的位置
x =200;
y =200;
}
//渔网的切换
public void change(int power) {
//根据火力值,来切换渔网的图片
img =ImageUtil.getImg("../img/net_"+power+".png");
//重新获取切换后,渔网的尺寸
h =img.getWidth();
w = img.getHeight();
}
//捕鱼,若返回turn,表示捕到鱼了,
public boolean catchFish(Fish f){
boolean hit =f.x <= x + w && f.x >= x-f.w
&& f.y<=y +h && f.y >= y-f.h;
return hit;
}
}
public class ImageUtil {
public static BufferedImage getImg(String path){
//规定读取图片的步骤(设置洗衣机流程)
//ImageIO 数据传输的通道(类似于自来水管)
//使用到反射机制
try {
//尝试去你给定的路径读取图片
BufferedImage img = ImageIO.read(ImageUtil.class.getResource(path));
return img;
//读取到图片后,将图片返回
} catch (IOException e ){
// 如果找不到图片,怎么办
// 下面的代码,就是输出找不到的原因
// 在实际开发过程中,此处会做异常日志的记录处理
e.printStackTrace();
}
return null;
}
}
|