《黄金矿工》小游戏

前言:游戏跟着尚学堂做的,目前还有一些问题,我会改正的。

文章目录

  • 一、黄金矿工小游戏结构
  • 二、图片准备
  • 三.实现代码

一、游戏结构

这个小游戏是看的b站上尚学堂出的视频,视频中一共是六个类,然后我又加了个音乐,又创建了一个类。(音乐用的是蛋仔派对的音频,最近比较沉迷蛋仔派对)

1.GameWin是小游戏的主类

2.Gold是金块类,用于存储金块

3.Line类 线类,矿工的绳子

4.Parent金块和石块提取出的父类

5.Sky背景类,存放天空和背景

6.Stone 石块类,存放石块

7.Music类,存放音乐,在主类中调用

imgs包中存放图片和音乐

二、图片准备

图片本来准备在网站上找的,没找到合适的,最后加的尚学堂老师微信要来的图片,总共是九张。

 

 

 三.实现代码

GameWin类

变量

1.state整个游戏的状态0未开始1运行2商店3失败4胜利

2.image展示的图片

3.gameTime倒计时

4.start是否开始的判断条件

方法

1.launch窗口事件,在launch方法中添加鼠标事件,其中左键1右键3滚轮2。点击左键实现抓取,在商店中点击左键可购买药水。右键使用药水爆破石块或者加速拉取金块,在商店中点击右键进入下一关并且不购买药水。

2.next Level下一关

3.paint绘制方法(重写方法)

4.main主方法

代码实现

package huangjinkuanggong;

import java.util.*;
import java.util.List;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class GameWin extends JFrame {
	static int state;// 整个游戏的状态 0未开始 1 运行 2商店 3失败 4胜利
	Sky sky = new Sky();// 背景类
	Line line = new Line(this);// 钩子的线类
	Image image;// 图片
	public static long gameTime = 30;// 倒计时初始时间
	public Thread start;// 是否开始
	List<Parent> parentList = new ArrayList<>();// 存放父类
	{
		boolean isPlace = true;// 是否可以放置
		for (int i = 0; i < 7; i++) {

			// 生成不同金块
			Double random = Math.random();
			// 先存放金块
			Gold gold;
			if (random < 0.3)// 概率30%以下生成小金块
			{
				gold = new GoldMini();
			} else if (random < 0.7)// 概率70%以下30%以上生成普通金块
			{
				gold = new Gold();
			} else// 其他以下生成大金块
			{
				gold = new Goldplus();
			}
			// 判断是否重叠
			for (Parent parent : parentList) {
				if (gold.getRec().intersects(parent.getRec())) {
					isPlace = false;
				}
			}
			// 添加未重叠元素
			if (isPlace) {
				parentList.add(gold);
			} else {
				isPlace = true;
				i--;
			}

		}
		// 利用for循环来存放石块
		for (int i = 0; i < 3; i++) {
			Stone stone = new Stone();
			for (Parent parent : parentList) {
				if (stone.getRec().intersects(parent.getRec())) {
					isPlace = false;
				}
			}
			if (isPlace) {
				parentList.add(stone);// 存储多个石块
			} else {
				isPlace = true;
				i--;
			}
		}

	}

	void launch() { // 定义窗口事件,无参构造方法
		this.setVisible(true); // 窗口可见
		this.setSize(768, 1000); // 窗口大小
		this.setResizable(false);
		this.setLocationRelativeTo(null); // 窗口位置
		this.setTitle("黄金矿工"); // 窗口名称
		setDefaultCloseOperation(EXIT_ON_CLOSE); // 关闭窗口操作
		// 在launch中添加鼠标事件
		addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				super.mouseClicked(e);
				switch (state) {
				case 0:
					if (e.getButton() == 3) {
						if (start == null) {
							start = new Thread(() -> {
								try {
									while (true) {
										gameTime -= 1;
										Thread.sleep(1000);
									}
								} catch (Exception ex) {
									ex.printStackTrace();
								}
							});
							start.start();
						}
						state = 1;
					}
					break;
				case 1:

					if (e.getButton() == 1 && line.state == 0) // 1左键 2滑轮 3右键
					{
						line.state = 1;
					}
					// 设置右键事件
					if (e.getButton() == 3 && line.state == 3) {
						if (Sky.yaoBasic > 0) {
							Sky.yaoBasic--;
							Sky.yaoState = true;
						}
					}
					;
				case 2:
					if (e.getButton() == 1)// 是否选择购买药水
					{
						System.out.println("购买");
						state = 1;
						sky.shop = true;// 调整状态
					}
					if (e.getButton() == 3)// 不购买,进入下一个关
					{
						System.out.println("不购买");
						state = 1;
						System.currentTimeMillis();
					}
					break;
				case 3:
					// 设置重开
					if (e.getButton() == 1) {
						state = 0;
						sky.reGame();
						line.reGame();
					}
					break;
				case 4:
					// 当点击左键时可以重新开始
					if (e.getButton() == 1) {
						state = 0;
						sky.reGame();
						line.reGame();
					}
					break;
				default:
				}

			}
		});
		// 用死循环来实现窗口的重新绘制
		while (true) {
			repaint();
			// 调用下一关
			nextLevel();
			// 降低刷新率,在循环里面设置
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void nextLevel() {
		if (GameWin.gameTime <= 0) {
			System.out.println(sky.total);
			System.out.println(sky.goal);
			if (sky.total >= sky.goal) {
				if (sky.level == 5) {
					state = 4;
					System.out.println("通关");
				} else {
					sky.level++;
					GameWin.state = 2;
					System.out.println("商店:" + state);
				}

			} else {
				// 失败,状态调为失败,展示失败页面
				GameWin.state = 3;
			}
			dispose();
			System.out.println(state);
			// 刷新窗体
			GameWin.gameTime = 30;
		    
			GameWin gameWin1 = new GameWin();
			gameWin1.launch();
		}

	}

	public void paint(Graphics g) {
		image = this.createImage(768, 1000);
		// 为了放置金块和石块的闪动,先绘制一个窗口
		Graphics grap = image.getGraphics();
		sky.paint(grap);
		if (state == 1) {
			line.paint(grap);

			// 绘制金块
			for (Parent gold : parentList) {
				gold.parin(grap);
			}
		}
		g.drawImage(image, 0, 0, null);
	}

	public static void main(String[] args) throws InterruptedException {
		Music audioPlayWave = new Music("/huangjinkuanggong/src/imgs/张紫宁 - 蛋仔星派对 (和声伴奏)(2023-05-28 20-27-09 314).wav");
		audioPlayWave.start();
		@SuppressWarnings("unused")
		int musicOpenlab =1;
		GameWin gameWin = new GameWin();
		gameWin.launch();

	}
}

2.Parent类

定义多次用到的变量

代码实现

package huangjinkuanggong;

import java.awt.*;

public class Parent {
	// 坐标
	int x, y;
	// 宽高
	int w, h;
	// 图片
	Image img;
	// 标记
	boolean flag;
	// 重量
	int m;
	// 钱
	int money;
	// 类型 1是金块,2是石头
	int type;

	// 绘制方法
	void parin(Graphics g) {
		g.drawImage(img, x, y, null);
	}

	public int getW() {
		return w;
	}

	// 获取矩形
	public Rectangle getRec(){
        return new Rectangle(x,y,w,h);
    }
}

3.Gold类(包含大金块,金块,小金块)

Gold类继承Parent类中的方法和类中定义的金块属性

代码实现

package huangjinkuanggong;

import java.awt.*;

public class Gold extends Parent {

	Gold() {
		this.x = (int) (Math.random() * 500);// 生成金块的横坐标
		this.y = (int) (Math.random() * 550 + 250);//生成金块的纵坐标
		this.w = 105;// 金块的宽
		this.h = 105;// 金块的高
		this.flag = false;// 是否背勾中了
		this.m = 180;// 金块的重量
		this.money = 200;// 金块的价钱
		this.type = 1;
		this.img = Toolkit.getDefaultToolkit().getImage("src/imgs/gold1.gif");
	}
}

class GoldMini extends Gold {
	GoldMini() {
		this.w = 72;// 金块的宽
		this.h = 72;// 金块的高
		this.m = 70;// 金块的重量
		this.money = 100;// 金块的价钱
		this.img = Toolkit.getDefaultToolkit().getImage("src/imgs/gold0.gif");
	}
}

class Goldplus extends Gold {
	Goldplus() {
		this.w = 175;// 金块的宽
		this.x = (int) (Math.random() * 550);
		this.h = 175;// 金块的高
		this.m = 230;// 金块的重量
		this.money = 500;// 金块的价钱
		this.img = Toolkit.getDefaultToolkit().getImage("src/imgs/gold2.gif");
	}
}

4.Stone类

类中有关于石块的相关参数,继承Parent中的方法和属性

代码实现

package huangjinkuanggong;
import java.awt.*;

public class Stone extends Parent {
	Stone() {
		this.x = (int) (Math.random() * 700);
		this.y = (int) (Math.random() * 550 + 300);
		this.w = 53;
		this.h = 53;
		this.flag = false;
		this.m = 150;
		this.money = 50;
		this.type = 2;
		this.img = Toolkit.getDefaultToolkit().getImage("src/imgs/rock1.png");
	}
}

5.Line类

类中的变量

x,y,endx,endy分别表示起点横坐标,纵坐标,终点横坐标纵坐标

length,maxLength,minLength表示绳子初始长度,最大最小长度

fangxiang表示绳子摇摆的方向,n是线的角度百分比

state绳子状态0摇摆状态1乡下抓取2抓取返回3绳子抓取到物体

gouzi钩爪图片

类中的方法

logic检测钩子是否碰撞物体,碰撞检测

lines绘制钩子和绳子

paint 完成绳子状态

reGame充值元素

代码实现

package huangjinkuanggong;

import java.awt.*;

public class Line {
	int x = 380, y = 180;// 起点坐标
	int endx = 500, endy = 500;// 终点坐标
	// 线段长度
	double length = 50;
	double n = 0;
	double maxLength = 750;
	double minLength = 50;
	// 方向
	int fangxiang = 1;
	// 状态
	int state = 0;
	// 添加钩爪图片
	Image gouzi = Toolkit.getDefaultToolkit().getImage("src/imgs/hook.png");

	GameWin gameWin;

	Line(GameWin gameWin) {
		this.gameWin = gameWin;
	}
	//抓取判断
	void logic() {
		for (Parent obj : this.gameWin.parentList) {
			if (endx > obj.x && endx < obj.x + obj.w && endy > obj.y && endx < obj.x + obj.h) {
				state = 3;// 碰撞检测
				obj.flag = true;
			}
		}
	}

	// 绘制
	void lines(Graphics g) {  
		// 动态获取钩子摆动的坐标
		endx = (int) (x + (length * Math.cos(n * Math.PI)));
		endy = (int) (y + (length * Math.sin(n * Math.PI)));
		g.setColor(Color.BLACK);
		g.drawLine(x - 1, y - 1, endx, endy);
		g.drawLine(x + 1, y + 1, endx, endy);
		g.drawLine(x, y, endx, endy);
		g.drawImage(gouzi, endx - 36, endy - 2, null);// 让钩子在中间
	}

	public void paint(Graphics g) {

		logic();//调用判断
		if (state == 0) {
			if (n < 0.1) {
				fangxiang = 1;
			} else if (n > 0.9) {
				fangxiang = -1;
			}
			n = n + 0.005 * fangxiang;
			lines(g);
		} else if (state == 1) {
			if (length < maxLength) {
				length = length + 10;
				lines(g);
			} else {
				state = 2;
			}
		} else if (state == 2) {
			if (length > minLength) {
				length = length - 10;
				lines(g);
			} else {
				state = 0;
			}
		} else if (state == 3) {
			int m = 1;
			if (length > minLength) {
				length = length - 10;
				lines(g);
				for (Parent object : this.gameWin.parentList) {
					if (object.flag) {
						m = object.m;
						object.x = endx - object.getW()/2+18 ;// 把金块放钩子中间
						object.y = endy+8;
						if (length <= minLength) {
							object.x = -150;
							object.y = -150;
							object.flag = false;    
							Sky.yaoState = false;
							Sky.total += object.money;
							state = 0;
						}
						if (Sky.yaoState) {
							if (object.type == 1) {
								m = 1;
							}
							if (object.type == 2) {
								object.x = -150;
								object.y = -150;
								object.flag = false;
								Sky.yaoState = false;
								state = 2;
							}
						}
					}

				}
				try {
					Thread.sleep(m);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

			}
		}

	}

	// 重置元素
	void reGame() {
		n = 0;// 线的角度百分比
		length = 50;// 线的长度
	}
}

6.Sky背景类

代码实现

类中变量
level 关卡数
goal 目标金额
total 总金额
yaoBasic 初始药水值
yaoState 药水状态 使用或未使用
price 药水价格
shop 是否购买药水
加一些的图片
类中方法
paint 绘制不同状态的窗口样式
draw 提取公共的代码
reGame 重置元素

package huangjinkuanggong;

import java.awt.*;

public class Sky {
	// 定义
	static int level = 1;
	// 目标金额
	int goal = level * 200 + 100;
	// 总金额
	static int total = 0;
	static int yaoBasic = 3;// 初始药水值
	// 药水状态
	static boolean yaoState = false;
	int price = (int) Math.random() * 100 + 10;
	// 是否购买药水
	boolean shop = false;
	// 开始和结束
	Image yao = Toolkit.getDefaultToolkit().getImage("src/imgs/water.png");
	Image bg = Toolkit.getDefaultToolkit().getImage("src/imgs/bg1.jpg");
	Image bg1 = Toolkit.getDefaultToolkit().getImage("src/imgs/bg.jpg");// 抓矿背景
	Image bg2 = Toolkit.getDefaultToolkit().getImage("src/imgs/bg.jpg");// 商店背景
	Image miner = Toolkit.getDefaultToolkit().getImage("src/imgs/people.png");

	public void paint(Graphics g) {
		g.drawImage(bg, 0, 0, null);
		g.drawImage(bg1, 0, 200, null);
		switch (GameWin.state) {
		case 0:
			g.drawImage(bg2, 0, 200, null);
			draw(g, 50, "准备开始,点击右键", 150, 400, Color.BLACK);
			break;
		case 1:
			g.drawImage(miner, 310, 50, null);
			draw(g, 30, "目标得分" + goal, 30, 110, Color.black);
			draw(g, 30, "总金额:" + total, 30, 150, Color.BLACK);
			// 药水绘制
			g.drawImage(yao, 480, 90, null);
			draw(g, 30, "x" + yaoBasic, 550, 150, Color.BLACK);
			// 计算时间

			draw(g, 30, "剩余时间:" + GameWin.gameTime, 520, 90, Color.BLACK);
			//repaint
			break;
		case 2:
			g.drawImage(bg2, 0, 200, null);
			draw(g, 60, "商店", 220, 280, Color.black);
			System.out.println("...........");
			g.drawImage(yao, 340, 500, null);

			// 药水价格
			draw(g, 30, "价格" + price, 337, 650, Color.black);
//                //是否购买
//                draw(g,30,"是否购买",300,450,Color.black);
			if (shop && total >= price) {
				total -= price;
				yaoBasic++;
				shop = false;
				System.currentTimeMillis();
			}
			break;
		case 3:
			g.drawImage(bg2, 0, 200, null);
			draw(g, 50, "你失败啦!", 250, 350, Color.RED);// rapaint
			draw(g, 50, "总金额!" + total, 200, 450, Color.BLACK);
			break;
		case 4:
			g.drawImage(bg2, 0, 200, null);
			draw(g, 50, "您通关啦!", 250, 350, Color.RED);// rapaint
			draw(g, 50, "总金额!" + total, 200, 450, Color.BLACK);
			break;
		default:
		}

	}

	public static void draw(Graphics g, int size, String str, int x, int y, Color color) {
		g.setColor(color);
		g.setFont(new Font("楷体", Font.BOLD, size));
		g.drawString(str, x, y);
	}

	// 重置元素
	void reGame() {
		// 定义关卡数
		int level = 1;
		// 目标金额
		int goal = level * 200 + 100;
		// 总金额
		int total = 0;
		int yaoBasic = 3;// 初始药水值
		// 药水状态
		boolean yaoState = false;
	}
}

7.Music类

这个是在网上找的方法,用音频转换器转换音乐为wav格式

代码实现

package huangjinkuanggong;
import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Music extends Thread {
       private String fileName;
       private final int EXTERNAL_BUFFER_SIZE = 524288;

public Music(String wavFile) {
       this.fileName = wavFile;
}

@SuppressWarnings("unused")
public void run() {
       File soundFile = new File(fileName); // 播放音乐的文件名
       if (!soundFile.exists()) {
           System.err.println("Wave file not found:" + fileName);
           return;
 }
       while (true) { // 设置循环播放
       AudioInputStream audioInputStream = null; // 创建音频输入流对象
 try {
       audioInputStream = AudioSystem.getAudioInputStream(soundFile); // 创建音频对象
     } catch (UnsupportedAudioFileException e1) {
             e1.printStackTrace();
          return;
 } catch (IOException e1) {
       e1.printStackTrace();
          return;
 }
       AudioFormat format = audioInputStream.getFormat(); // 音频格式
       SourceDataLine auline = null; // 源数据线
       DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
 try {
       auline = (SourceDataLine) AudioSystem.getLine(info);
       auline.open(format);
 } catch (LineUnavailableException e) {
       e.printStackTrace();
         return;
 } catch (Exception e) {
       e.printStackTrace();
  return;
 }
       if (auline.isControlSupported(FloatControl.Type.PAN)) {
           FloatControl pan = (FloatControl) auline.getControl(FloatControl.Type.PAN);
 }
       auline.start();
 int nBytesRead = 0;
 byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
 try {
     while (nBytesRead != -1) {
     nBytesRead = audioInputStream.read(abData, 0, abData.length);
     if (nBytesRead >= 0)
        auline.write(abData, 0, nBytesRead);
  }
 } catch (IOException e) {
     e.printStackTrace();
     return;
 } finally {
     auline.drain();
//auline.close();
             }
       }
        }
}

总结

目前代码还有些问题,稍后更新

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值