黄金矿工
实现黄金矿工游戏大体可以分为4个类
1.背景类
package com.zhou.GUI;
import java.awt.*;
/**
* @author:Zhou_jx,
*/
public class Bg {
//关卡数
static int level = 1;
//目标得分
int goal = level*15;
//总分
static int countsum = 0;
//药水数量
static int waternum = 3;
//药水状态 true表示正在使用
static boolean waterState = false;
//开始时间
long startTime;
//结束时间
long endTime;
//药水价格
int price = (int) (Math.random()*10+1);
//是否进入商店
boolean shop = false;
//判断时间
boolean gameTime(){
//单位转换为秒
long time = (endTime-startTime)/1000;
return time > 30;
}
//读取图片路径
Image bg = Toolkit.getDefaultToolkit().getImage("imgs/bg.jpg");
Image bg1 = Toolkit.getDefaultToolkit().getImage("imgs/bg1.jpg");
Image bg2 = Toolkit.getDefaultToolkit().getImage("imgs/peo.png");
Image water = Toolkit.getDefaultToolkit().getImage("imgs/water.png");
//绘制
//除开背景图片一类,其他的绘制都需要在游戏进行中才会进行绘制
void paintSelf(Graphics g){
//绘制地下位置
g.drawImage(bg,0,200,null);
//绘制天空的位置
g.drawImage(bg1,0,0,null);
//根据窗口的状态来选择绘制
switch (GameWin.state){
case 0:
//当游戏未开始时,显示的信息
drawWord(g,80,Color.BLACK,"开始游戏",200,400);
break;
case 1:
//绘制人物的位置
g.drawImage(bg2,322,50,null);
//调用绘制字符串的方法,打印总分
drawWord(g,30,Color.black,"积分:"+countsum,30,150);
//绘制药水
g.drawImage(water,500,100,null);
//调用绘制方法,打印药水数量
drawWord(g,30,Color.green,"*"+waternum,560,150);
//绘制关卡数
drawWord(g,20,Color.black,"第"+level+"关",30,60);
//绘制目标积分
drawWord(g,30,Color.black,"目标"+goal,30,110);
//局部变量计算时间
endTime = System.currentTimeMillis();
//计算玩家剩余的时间
long time = 30-(endTime-startTime)/1000;
//用三目运算来显示玩家的剩余时间
drawWord(g,30,Color.black,"时间剩余"+(time>=0?time:0),580,80);
break;
case 2:
//绘制药水
g.drawImage(water,300,400,null);
//调用绘制方法,打印药水数量
drawWord(g,30,Color.green,"价格"+waternum,300,500);
//绘制关卡数
drawWord(g,20,Color.black,"是否购买"+level+"关",300,550);
//当玩家确定购买时
if(shop){
//用游戏总分扣除药水钱
countsum = countsum-price;
//药水数量加一
waternum++;
//重置购买药水的状态
shop = false;
GameWin.state = 1;
//重置时间
startTime = System.currentTimeMillis();
}
break;
case 3:
//失败的时候打印的画面
drawWord(g,80,Color.RED,"游戏失败",250,350);
drawWord(g,80,Color.RED,"积分"+countsum,250,450);
break;
case 4:
//成功的时候打印的画面
drawWord(g,80,Color.YELLOW,"游戏成功",250,350);
drawWord(g,80,Color.YELLOW,"积分"+countsum,250,450);
break;
}
}
//绘制字符串的方法
public static void drawWord(Graphics g,int size,Color color,String str,int x,int y){
//绘制游戏分数的颜色,字体,名字,位置;
g.setColor(color);
g.setFont(new Font("仿宋",Font.BOLD,size));
g.drawString(str,x,y);
}
//重置背景元素
void reGame(){
//关卡数
level = 1;
//目标得分
goal = level*15;
//总分
countsum = 0;
//药水数量
int waternum = 3;
//药水状态 true表示正在使用
waterState = false;
}
}
2.窗口类
package com.zhou.GUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
/**
* 继承JFrame,才有窗口以及监听鼠标的功能
* @author:Zhou_jx,
*/
public class GameWin extends JFrame {
//游戏状态0表示未开始,1表示运行中,2表示商店,3表示失败,4表示胜利
static int state;
//金块集合
ArrayList<Object> objectList = new ArrayList<>();
//背景类实例化
Bg bg = new Bg();
//实例化线
Line line = new Line(this);
//实现金块类
{
//设置一个参数,判断是否可以放置的依据
boolean isPlace = true;
for (int i = 0; i < Math.random()*9+3*Bg.level; i++) {
double random = Math.random();
Gold gold;//用来存放生成的金块对象
//生成三种不同大小金块的概率
if (random<0.3)
gold = new GoldMini();
else if (random<0.7)
gold = new Gold();
else
gold = new GoldPlus();
//遍历所有的金块,看集合中包含的金块是否有与新金块坐标重合的,重合即打回去重做
for(Object obj:objectList){
if(gold.getRec().intersects(obj.getRec())){
isPlace = false;
i--;
}
}
if(isPlace)
objectList.add(gold);
else{
isPlace = true;
i--;
}
}
//随机10块以内的石头
for (int i = 0; i < Math.random()*9+1; i++) {
boolean isRock = true;
//将创建的石头放到rock对象里面
Rock rock;
rock = new Rock();
//遍历所有的rock判断坐标是否重复
for (Object object:objectList){
if(rock.getRec().intersects(object.getRec())){
isRock = false;
i--;
}
}
if(isRock)
objectList.add(rock);
else {
i--;
}
}
}
//添加一张画布,想实现双缓存技术
Image offScreenImage;
//下一关
public void nextLevel(){
//判断游戏时间是否足够
if(bg.gameTime()&&state==1){
//判断是否达到目标分数
if(Bg.countsum>=bg.goal){
if(Bg.level==5){
state = 4;
}
else {
//满足条件,关卡等级加一
state = 2;
Bg.level++;
}
}
else
state = 3;
//释放组件
dispose();
//生成下一个等级的窗口
GameWin gameWin = new GameWin();
gameWin.lunch();
}
}
void lunch(){
//让窗口可视化
this.setVisible(true);
//设置窗口的宽高
this.setSize(768,1000);
//设置窗口位置,默认剧中
this.setLocationRelativeTo(null);
//窗口标题,自定义
this.setTitle("黄金矿工");
//关闭窗口
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//鼠标点击事件
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
switch (state){
case 0:
if(e.getButton()==3){
state = 1;
bg.startTime = System.currentTimeMillis();
}
break;
case 1:
//左右摇摆,点击左键
if(e.getButton()==1&&line.state==0)
line.state=1;
//抓取返回,点击右键
if(e.getButton()==3&&line.state==3&&Bg.waternum>0){
Bg.waterState=true;
Bg.waternum--;
}
break;
case 2:
//商店购买事件
if(e.getButton()==1){
bg.shop = true;
}
if(e.getButton()==3){
state = 1;
bg.startTime = System.currentTimeMillis();
}
break;
case 3:
case 4:
//重置游戏
if(e.getButton()==1){
state = 0;
bg.reGame();
line.reGame();
}
break;
}
}
});
//重复绘画画布,这样可以达到一直刷新线条的视觉
while (true){
nextLevel();
try {
repaint();
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void paint(Graphics g){
//画布大小
offScreenImage = this.createImage(768,1000);
//给画布画笔
Graphics gImage = offScreenImage.getGraphics();
//绘制背景图片
bg.paintSelf(gImage);
//绘制物体绘制线,都会在状态1的时候绘制
if(state==1){
//绘制金块集合
for(Object object:objectList){
object.piantSelf(gImage);
}
//绘制线
line.paintSelf(gImage);
}
g.drawImage(offScreenImage,0,0,null);
}
//主方法,程序的入口
public static void main(String[] args) {
//实例化
GameWin gameWin = new GameWin();
gameWin.lunch();
}
}
3.勾爪(线)类
package com.zhou.GUI;
import java.awt.*;
/**
* @author:Zhou_jx,
*/
public class Line {
//线的起点坐标
int x=400;
int y=180;
//终点坐标
int endx=500;
int endy=500;
//线长
double len = 100;
//线最小值
double Mixlen = 100;
double Maxlen = 750;
double n = 0;
//方向判定参数
int dir = 1;
//定义状态 0
int state;
//勾爪图片
Image hook = Toolkit.getDefaultToolkit().getImage("imgs/hook.png");
//获取主函数中的参数
GameWin frame;
Line(GameWin frame){
this.frame = frame;
}
//判断是否抓取成功
void logic(){
for (Object object:this.frame.objectList){
if(endx>object.x&&endx<object.x+object.width
&& endy>object.y&&endy<object.y+object.height){
state = 3;
object.flag = true;
}
}
}
//由于绘画线时的参数时代码都一样,所以写一个方法来调用避免重复代码
void linePaint(Graphics g){
g.drawLine(x-1,y-1,endx,endy);
g.drawLine(x,y,endx,endy);
g.drawLine(x+1,y+1,endx,endy);
g.drawImage(hook,endx-36,endy-2,null);
}
//线运行时不同的状态,0为正常运动状态,1为鼠标点击左键后进行抓取状态,2为抓取中了之后线的行动,3为抓中之后线对于不同物体的抓取速度
void paintSelf(Graphics g){
logic();
switch (state){
case 0:
if (n<=0.1)
dir = 1;
else if(n>=0.9)
dir = -1;
n=n+0.005*dir;
endx = (int) (x+len*Math.cos(n*Math.PI));
endy = (int) (y+len*Math.sin(n*Math.PI));
g.setColor(Color.red);
linePaint(g);
break;
case 1:
if(len<=Maxlen){
len +=12;
endx = (int) (x+len*Math.cos(n*Math.PI));
endy = (int) (y+len*Math.sin(n*Math.PI));
g.setColor(Color.YELLOW);
linePaint(g);
}else {
state = 2;
}
break;
case 2:
if(len>=Mixlen){
len -=12;
endx = (int) (x+len*Math.cos(n*Math.PI));
endy = (int) (y+len*Math.sin(n*Math.PI));
g.setColor(Color.BLUE);
linePaint(g);
}else
state = 0;
break;
case 3://抓取返回
int m = 1;
if(len>=Mixlen){
len = len-10;
endx = (int) (x+len*Math.cos(n*Math.PI));
endy = (int) (y+len*Math.sin(n*Math.PI));
g.setColor(Color.PINK);
linePaint(g);
for (Object object:this.frame.objectList){
if (object.flag){
m = object.m;
object.x=endx- (object.getWidth()/2);
object.y=endy;
if(len<=Mixlen){
//移除被抓中的物体
object.x=-150;
object.y=-150;
//令其显示参数为f
object.flag = false;
//药水状态
Bg.waterState = false;
Bg.countsum += object.getCount();
state = 0;
}
if(Bg.waterState){
if(object.type==1){
m=1;
}
if (object.type==2){
//移除被抓中的物体
object.x=-150;
object.y=-150;
//令其显示参数为f
object.flag = false;
Bg.waterState = false;
state = 2;
}
}
}
}
}
try {
Thread.sleep(m);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
}
//重置线元素
void reGame(){
n = 0;
len = 100;
}
}
4.物体类
-
父类Object
package com.zhou.GUI; import java.awt.*; /** * @author:Zhou_jx, */ public class Object { //坐标 int x; int y; //宽高 int width; int height; //图片 Image img; //区别值 boolean flag = false; //质量 int m; //积分 int count; //类型 1为金块, 2为石块 int type; //绘画自己 void piantSelf(Graphics g){ g.drawImage(img,x,y,null); } //获得自己的宽度 public int getWidth() { return width; } //获取矩形坐标 public Rectangle getRec(){ return new Rectangle(x,y,width,height); } //获取子类积分的方法 public int getCount(){ return count; } }
-
子类金块类
package com.zhou.GUI; import java.awt.*; /** * @author:Zhou_jx, */ public class Gold extends Object{ //使用无参构造函数重写父类 Gold(){ this.x = (int) (Math.random()*700); this.y = (int) (Math.random()*550+300); this.width = 52; this.height = 52; this.flag=false; this.m = 30; this.count = 4; this.type = 1; this.img = Toolkit.getDefaultToolkit().getImage("imgs/gold1.gif"); } } //小金块类 //使用无参构造函数重写父类 class GoldMini extends Gold { GoldMini() { this.width = 36; this.height = 36; this.m = 15; this.count = 2; this.img = Toolkit.getDefaultToolkit().getImage("imgs/gold0.gif"); } } //大金块类 //使用无参构造函数重写父类 class GoldPlus extends Gold { GoldPlus() { this.x = (int) (Math.random()*650); this.width = 105; this.height = 105; this.m = 70; this.count = 8; this.img = Toolkit.getDefaultToolkit().getImage("imgs/gold2.gif"); } }
-
石头类
package com.zhou.GUI; import java.awt.*; /** * @author:Zhou_jx, */ //继承父类Obejct public class Rock extends Object{ //使用无参构造方法重写父类 Rock() { this.x = (int) (Math.random()*700); this.y = (int) (Math.random()*550+300); this.width = 71; this.height = 71; this.flag=false; this.m = 50; this.count = 1; this.type = 2; this.img = Toolkit.getDefaultToolkit().getImage("imgs/rock1.png"); } }
运行截图
需要使用的图片
ps
详情可以去【尚学堂】只用了2小时做出了Java黄金矿工小游戏项目_java初级项目_java练手项目_java项目实战_Java游戏开发实战教学_java小游戏_哔哩哔哩_bilibili观看;