Java游戏项目——仿4399小游戏《黄金矿工》
简介
作者简介:青铜码农,和大多数同学一样从零开始一步步学习,一步步积累。期待您的关注,让我们一起成长~注:本人学疏才浅,文章如有错误之处,敬请指正~
内容简介:实现4399《黄金矿工》小游戏
目录
功能预览:
游戏中一些对象的介绍 :
实现步骤:
1.创建Game类继承JFrame
2.创建图片Background类,以便绘制地图
3.绘制绳索
4.绳索的延长与收回
5.双缓存技术
6.创建金块
7.抓取判定
8.抓取返回
9.多个金块
10.创建石头
11.设置不同的回收速度
12.解决物体位置重叠
13.设置多种金块
14.绳索的钩爪
16.添加快速抓取功能
17.设置关卡
18.设置游戏状态
19.倒计时效果:
20.失败状态:
21.成功状态:
22.重置游戏
23.游戏商店:
功能预览:
《黄金矿工》
游戏中一些对象的介绍 :
实现步骤:
1.创建Game类继承JFrame
在类中创建一个Game方法,以便初始化窗口
void Game() {setVisible(true);setSize(800, 824);// 窗口大小setLocationRelativeTo(null);// 窗口将放置在屏幕中央setTitle("CodeDragons黄金矿工");// 设置标题setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 关闭程序}
2.创建图片Background类,以便绘制地图
import java.awt.*;
/*** @author WayLon* @create 2021-07-15 19:19* 备注:*/
public class Background {// 背景图片初始化Image bg= Toolkit.getDefaultToolkit().getImage("src/images/土壤.jpg");Image people=Toolkit.getDefaultToolkit().getImage("src/images/人物.png");public void BackgroundPaint(Graphics g){g.drawImage(bg, 0, 0, null);g.drawImage(people, 380, 190, null);}
}
再返回Game类中创建一个paint()方法
Background bg = new Background();/*** 绘制游戏地图** @param g*/public void paint(Graphics g) {bg.BackgroundPaint(g);}
在Game类中创建一个main()方法以便启动程序
/*** 启动程序*/public static void main(String[] args) {Game frame = new Game();frame.Game();}
运行效果如图:
3.绘制绳索
说明:绳索会左右摇摆且可以收回来。
创建一个绳索Rope类,并初始化绳索的起点坐标和终点坐标以及绳索的长度,绳索摆动的角度
绳索的终点坐标算法如图:
import java.awt.*;/*** @author WayLon* @create 2021-07-15 19:14* 备注:*/
public class Rope {// 绳索的起点坐标int x = 505;int y = 253;// 绳索的终点坐标int endx = 400;int endy = 700;// 初始化绳索的长度double length = 200;// 初始化绳索的角度double angle = 0;public void Ropepaint(Graphics g) {angle=angle+0.005;// 每次调用这个方法就将绳索的角度加0.005,以便实现绳索的不停转动endx = (int) (x + length * Math.cos(angle*Math.PI));endy = (int) (y + length * Math.sin(angle*Math.PI));Graphics2D g2d=(Graphics2D) g;g2d.setStroke(new BasicStroke(2));// 设置绳索粗细g2d.drawLine(x, y, endx, endy);// 画绳索}
}
运行效果如图:
如果想让绳索不停的转动,只需要在Game类中的Game()方法添加以下代码:
void Game() {// 此处为不做改变的代码while (true) {repaint();try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}
效果如图:
先别着急,此时的绳索是360°旋转, 而绳索只能在X轴下方来回摆动,所以可以设置绳索的角度取值范围的为0-π。(且此时的整个画面是不停的闪动的,需要用到双缓存技术去解决,后面再讲这个问题),这里我们只讨论绳索需要在X轴下方来回摆动,则需要在Rope类添加以下代码:
public class Rope {// 绳索的起点坐标// 绳索的终点坐标// 初始化绳索的长度// 初始化绳索的角度// 以下为新增代码// 初始化方向.1表示顺时针0~180度,-1表示逆时针0~180度int dir = 1;public void Ropepaint(Graphics g) {if (angle <= 0) {dir = 1;} else if (angle >= 1) {dir = -1;}// 此处省略原有代码}
}
效果如图:
眼尖的同学在这里会发现,绳索还是超越了地平线。这个问题很好解决,只需要将新增代码修饰为以下代码:
public class Rope {// 绳索的起点坐标// 绳索的终点坐标// 初始化绳索的长度// 初始化绳索的角度// 以下为新增代码// 初始化方向.1表示顺时针0~180度,-1表示逆时针0~180度int dir = 1;public void Ropepaint(Graphics g) {if (angle <= 0.1) {dir = 1;} else if (angle >= 0.9) {dir = -1;}// 此处省略原有代码}
}
再来看一下效果:
嗯,这就完美许多了。
4.绳索的延长与收回
实现思路:
首先给绳索定义一个状态state,0表示摇摆,1表示抓取,2表示收回。
初始化状态state为0,=,当玩家按下键盘向下键时, 令state=1,当state=1时,延长绳索,且当绳索的长度小于500时,延长绳索的长度,直到绳索的长度等于500,此时再令state=2,收回绳索,当state=2且绳索的长度大于130时,收回绳索直到绳索长度等于130,也就是原始的绳索长度。当收回绳索的长度等于原始的长度时,令state=0恢复原来摆动的状态,以此循环类推。
为了代码整洁,下面我们将Ropepaint()方法里的这几行代码单独用一个方法封装起来。
void Rope(Graphics g) {endx = (int) (x + length * Math.cos(angle * Math.PI));endy = (int) (y + length * Math.sin(angle * Math.PI));Graphics2D g2d = (Graphics2D) g;g2d.setStroke(new BasicStroke(2));// 设置绳索粗细g2d.drawLine(x, y, endx, endy);// 画绳索}
在Game类中的Game()方法添加键盘事件,如下:
addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {if (e.getKeyCode() == KeyEvent.VK_DOWN) {rope.state = 1;}}});
绳索的延长已收回完整代码如下:
public class Rope {// 绳索的起点坐标// 绳索的终点坐标// 初始化绳索的长度// 初始化绳索的角度// 初始化方向.1表示顺时针0~180度,-1表示逆时针0~180度// 初始化绳索的状态,0表示摇摆,1表示抓取,2表示收回int state = 0;void Rope(Graphics g) {endx = (int) (x + length * Math.cos(angle * Math.PI));endy = (int) (y + length * Math.sin(angle * Math.PI));Graphics2D g2d = (Graphics2D) g;g2d.setStroke(new BasicStroke(2));// 设置绳索粗细g2d.drawLine(x, y, endx, endy);// 画绳索}public void Ropepaint(Graphics g) {switch (state) {case 0:// 当state=0时,摆动绳索if (angle <= 0.1) {dir = 1;} else if (angle >= 0.9) {dir = -1;}angle += 0.005 * dir;Rope(g);break;case 1:// 当state=1时,延长绳索抓取if (length < 650) {// 当绳索的长度小于650时,延长绳索的长度直到绳索的长度等于650length += 10;Rope(g);} else {state = 2;// 绳索长度等于650时,令state=2}break;case 2:// 当state=2时,收回绳索if (length > 130) {// 当state=2且绳索的长度大于130时,收回绳索直到绳索长度等于130,也就是原始的绳索长度length -= 10;Rope(g);} else {state = 0;// 当收回绳索的长度等于原始的长度时,令state=0恢复原来摆动的状态}break;}}
}
效果图如下:
代码敲到这里,相信很多同学已经被这个闪动的画面闪得不想再继续码下去了,那好,现在我们就来解决这个烦人的问题。
5.双缓存技术
原理讲解:双缓冲技术在很多动画中被采用。主要原理是创建一幅BufferedImage图像,将每一帧画入图像,然后调用drawImage方法,将整个BufferedImage图像一次画到屏幕上去。
代码实现:
首先在Game类中创建一个画布offFlickerImage;再将Game类中的paint方法改写成以下代码:
public void paint(Graphics g) {offFlickerImage=this.createImage(800,824);Graphics gImage=offFlickerImage.getGraphics();bg.BackgroundPaint(gImage);rope.Ropepaint(gImage);g.drawImage(offFlickerImage,0,0,null);}
运行一下,是不是更加完美了呢?
6.创建金块
因为金块都有一些相同的属性,例如宽高度。所以我们可以创建一个Object类作为Gold类的父类。
Object类:
import java.awt.*;/*** @author WayLon* @create 2021-07-15 22:01* 备注:*/
public class Object {// 物体的坐标int x;int y;// 物体的宽高int width;int height;// 图片Image image;// 标记是否能移动boolean flag;public void goldPaint(Graphics g) {g.drawImage(image, x, y, null);}public int getWidth() {return width;}
}
Gold类:
import java.awt.*;/*** @author WayLon* @create 2021-07-15 22:19* 备注:*/
public class Gold extends Object {public Gold() {this.x = (int) (Math.random() * 750);this.y = (int) (Math.random() * 300 + 400);this.width = 55;this.height = 55;this.flag = false;this.image = Toolkit.getDefaultToolkit().getImage("src/images/金元宝.png");}
}
在Game类中new一个Gold类对象,再往paint()方法中调用Gold类的drawImage()方法。
public class Game extends JFrame {Gold gold = new Gold();public Game() {// 此处省略不做改变的代码}/*** 启动程序*/public static void main(String[] args) {// 此处省略不做改变的代码}/*** 绘制游戏地图** @param g*/public void paint(Graphics g) {// 此处省略不做改变的代码gold.goldPaint(gImage);g.drawImage(offFlickerImage, 0, 0, null);}
}
运行效果如图:
7.抓取判定
此模块运用的是Java游戏中的碰撞检测,查看相关知识点可点击→矩形碰撞检测 & 圆形和像素碰撞检测。
修改Rope类中的代码:
public class Rope {// 绳索的起点坐标// 绳索的终点坐标// 初始化绳索的长度// 初始化绳索的角度// 初始化方向.1表示顺时针0~180度,-1表示逆时针0~180度// 初始化绳索的状态,0表示摇摆,1表示抓取,2表示收回Game frame;Rope(Game frame) {this.frame = frame;}void judge() {if (endx > this.frame.gold.x && endx < this.frame.gold.x + this.frame.gold.width &&endy > this.frame.gold.y && endy < this.frame.gold.y + this.frame.gold.height) {System.out.println("抓到啦!");}}void Rope(Graphics g) {// 此处省略不做修改的代码}public void Ropepaint(Graphics g) {judge();switch (state) {// 此处省略不做修改的代码}
}
效果如图:
8.抓取返回
之前的state状态新增一个3,用来表示抓取返回。
public class Rope {// 绳索的起点坐标// 绳索的终点坐标// 初始化绳索的长度// 初始化绳索的角度// 初始化方向.1表示顺时针0~180度,-1表示逆时针0~180度// 初始化绳索的状态,0表示摇摆,1表示抓取,2表示收回Game frame;Rope(Game frame) {this.frame = frame;}void judge() {if (endx > this.frame.gold.x && endx < this.frame.gold.x + this.frame.gold.width &&endy > this.frame.gold.y && endy < this.frame.gold.y + this.frame.gold.height) {state = 3;this.frame.gold.flag = true;}}void Rope(Graphics g) {
// 此处省略不做修改的代码}public void Ropepaint(Graphics g) {judge();switch (state) {case 0:
// 此处省略不做修改的代码break;case 1:
// 此处省略不做修改的代码break;case 2:
// 此处省略不做修改的代码break;case 3:if (length > 130) {length -= 10;Rope(g);this.frame.gold.x = endx - this.frame.gold.getWidth() / 2;this.frame.gold.y = endy;} else {// 直接移到屏幕外this.frame.gold.x = -100;this.frame.gold.y = -100;state = 0;}break;}}
}
效果如图:
9.多个金块
利用list集合存储金块。在Game类中添加以下新代码,并删除两行代码(别漏删了,要不然后面会出现其中某一个金块钓不起来的糟糕情况):
public class Game extends JFrame {// 此处省略不做改变的代码Gold gold = new Gold();// 删除此行代码List<Object> goldList = new ArrayList<Object>();// 储存金块,有这个集合后,上面一行代码可删除{for (int i = 0; i < 5; i++) {goldList.add(new Gold());}}public Game() {
// 此处省略不做改变的代码}/*** 启动程序*/public static void main(String[] args) {
// 此处省略不做改变的代码}/*** 绘制游戏地图** @param g*/public void paint(Graphics g) {
// 此处省略不做改变的代码for (Object o : goldList) {o.goldPaint(gImage);}gold.goldPaint(gImage);// 删除此行代码g.drawImage(offFlickerImage, 0, 0, null);// 此处行是不做改变的代码}
}
修改Rope类中的judge()方法和Ropepaint()方法:
public class Rope {
// 此处为不做修改的代码块void judge() {for (Object o : this.frame.goldList) {if (endx > o.x && endx < o.x + o.width &&endy > o.y && endy < o.y + o.height) {state = 3;o.flag=true;}}}void Rope(Graphics g) {
// 此处为不做修改的代码块}public void Ropepaint(Graphics g) {judge();switch (state) {case 0:// 此处为不做修改的代码块case 1:// 此处为不做修改的代码块case 2:// 此处为不做修改的代码块case 3:if (length > 130) {// 当state=2且绳索的长度大于130时,收回绳索直到绳索长度等于130,也就是原始的绳索长度length -= 10;Rope(g);for (Object o : this.frame.goldList) {if (o.flag) {o.x = endx - o.getWidth() / 2;o.y = endy;if (length <= 130) {// 直接移到屏幕外o.x = -100;o.y = -100;o.flag = false;state = 0;// 当收回绳索的长度等于原始的长度时,令state=0恢复原来摆动的状态}}}}break;}}
}
效果如图:
10.创建石头
首先创建一个石头类Stone继承Object类。
import java.awt.*;/*** @author WayLon* @create 2021-07-16 9:56* 备注:*/
public class Stone extends Object {public Stone() {this.x = (int) (Math.random() * 750);this.y = (int) (Math.random() * 300 + 400);this.width = 70;this.height = 70;this.flag = false;this.image = Toolkit.getDefaultToolkit().getImage("src/images/石头.png");}
}
再修改Game类:
public class Game extends JFrame {// 此处省略不做修改的代码块{// 生成金块for (int i = 0; i < 5; i++) {// 此处省略不做修改的代码块}// 生成石头for (int i = 0; i < 2; i++) {goldList.add(new Stone());}}public Game() {
// 此处省略不做修改的代码块}/*** 启动程序*/public static void main(String[] args) {
// 此处省略不做修改的代码块}/*** 绘制游戏地图** @param g*/public void paint(Graphics g) {
// 此处省略不做修改的代码块}
}
效果如图:
11.设置不同的回收速度
给Object类添加一个变量m,用于表示物体的质量。
public class Object {// 物体的坐标// 物体的宽高// 图片// 标记是否能移动// 物体的质量int m;public void goldPaint(Graphics g) {// 此处省略不做改变的代码块}public int getWidth() {// 此处省略不做改变的代码块}
}
再到Gold类和Stone类中给物体的质量赋值(石头的质量要明显大于金块的质量)。
public class Gold extends Object {public Gold() {// 此处省略不做修改的代码块this.m=35;}
}
public class Stone extends Object {public Stone() {// 此处省略不做改变的代码块this.m=100;}
}
再到Rope类中新增以下代码:
public class Rope {// 此处为不做修改的代码块Rope(Game frame) {// 此处为不做修改的代码块}void judge() {// 此处为不做修改的代码块}void Rope(Graphics g) {// 此处为不做修改的代码块}public void Ropepaint(Graphics g) {// 此处为不做修改的代码块switch (state) {case 0: // 此处为不做修改的代码块case 1: // 此处为不做修改的代码块case 2: // 此处为不做修改的代码块case 3:int m=0;if (length > 130) { // 此处为不做修改的代码块}try {Thread.sleep(m);} catch (InterruptedException e) {e.printStackTrace();}break;}}
}
效果如图:
12.解决物体位置重叠
在Object类中添加获取矩形的方法:
// 获取矩形public Rectangle getR() {return new Rectangle(x, y, width, height)}
import java.awt.*;/*** @author WayLon* @create 2021-07-15 22:01* 备注:*/
public class Object {// 物体的坐标int x;int y;// 物体的宽高int width;int height;// 图片Image image;// 标记是否能移动boolean flag;// 物体的质量int m;public void goldPaint(Graphics g) {g.drawImage(image, x, y, null);}public int getWidth() {return width;}
}
13.设置多种金块
在Gold类中添加以下代码:
public class Gold extends Object {public Gold() {// 此处为不做修改的代码块}
}class GoldTwo extends Gold {public GoldTwo() {this.width = 55;this.height = 37;this.m = 110;this.image = Toolkit.getDefaultToolkit().getImage("src/images/金条.png");}
}class GoldThree extends Gold {public GoldThree() {this.width = 55;this.height = 55;this.m = 65;this.image = Toolkit.getDefaultToolkit().getImage("src/images/戒指.png");}
}
且不同的金块按照不同的概率出现。元宝占50%,戒指占35%,金条占15%。
在Game的第一个循环中替换为以下代码:
public class Game extends JFrame {// 此处为不做修改的代码块{for (int i = 0; i < 8; i++) {double probability = Math.random();if (probability < 0.15) {goldList.add(new GoldThree());} else if (probability < 0.35 && probability > 0.15) {goldList.add(new GoldTwo());} else if (probability > 0.35) {goldList.add(new Gold());}}for (int i = 0; i < 3; i++) {// 此处为不做修改的代码块}}public Game() {
// 此处为不做修改的代码块}/*** 启动程序*/public static void main(String[] args) {
// 此处为不做修改的代码块}/*** 绘制游戏地图** @param g*/public void paint(Graphics g) {
// 此处为不做修改的代码块}
}
运行效果:
14.绳索的钩爪
public class Rope {// 此处为不做修改的代码块// 钩爪的图片Image hook = Toolkit.getDefaultToolkit().getImage("src/images/钳子.png");Rope(Game frame) {// 此处为不做修改的代码块}void judge() {// 此处为不做修改的代码块}void Rope(Graphics g) {// 此处为不做修改的代码块g2d.drawImage(hook,endx-35,endy-3,null);}public void Ropepaint(Graphics g) {// 此处为不做修改的代码块}
}
15.金钱设置
先在Object类中设定一个cost变量;
// 物体的金钱数int cost;
再到Stone类和Gold类进行初始化。
元宝价值为50;金条为550;戒指为250;石头为11;
再到Background类中,将总钱数写入:
public class Background {// 总钱数static int count = 0;// 背景图片初始化Image bg = Toolkit.getDefaultToolkit().getImage("src/images/土壤.jpg");Image people = Toolkit.getDefaultToolkit().getImage("src/images/人物.png");public static void drawText(Graphics g, int size, Color color, String s, int x, int y) {g.setColor(color);g.setFont(new Font("楷体", Font.BOLD, 24));g.drawString(s, x, y);}public void BackgroundPaint(Graphics g) {g.drawImage(bg, 0, 0, null);g.drawImage(people, 380, 190, null);drawText(g, 24, new Color(143, 112, 1), "金钱:$" + count, 30, 250);}
}
再到Rope类中的case 3:添加一行代码实现加钱:
public class Rope {Rope(Game frame) {this.frame = frame;}void judge() {}void Rope(Graphics g) {}public void Ropepaint(Graphics g) {judge();switch (state) {case 0:case 1:case 2:case 3:// 此处为不做改变的代码if (length <= 130) {// 直接移到屏幕外o.x = -100;o.y = -100;o.flag = false;Background.count += o.cost;// 增加此行代码state = 0;}}}}// 此处为不做改变的代码}}
}
效果如图:
16.添加快速抓取功能
在物体被抓取的时候,按下键盘的向上键也就是使用魔法水物品,物体将迅速被拉回。
首先需要在Background类中添加魔法水。
public class Background {// 总钱数// 此处为不做改变的代码// 爆竹的数量static int firecrackersNum = 3;// 爆竹的状态static boolean fcFlag = false;// 背景图片初始化// 此处为不做改变的代码Image firecrackers = Toolkit.getDefaultToolkit().getImage("src/images/魔法水.png");public static void drawText(Graphics g, int size, Color color, String s, int x, int y) {// 此处为不做改变的代码}public void BackgroundPaint(Graphics g) {// 此处为不做改变的代码g.drawImage(firecrackers, 580, 250, null);drawText(g, 24, new Color(143, 112, 1), "*" + firecrackersNum, 630, 290);}
}
效果如图:
接下来在Game类中的Game()方法添加新的键盘事件:
public Game() {// 此处为不做改变的代码addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {if (e.getKeyCode() == KeyEvent.VK_DOWN) {// 此处为不做改变的代码}if (e.getKeyCode() == KeyEvent.VK_UP && rope.state == 3 && Background.firecrackersNum > 0) {// 当按下向上键且绳索的状态为3时和有魔法水的情况下Background.firecrackersNum--;Background.fcFlag = true;}}});}
再修改Rope()类中Ropepaint()方法中的case 3:
public void Ropepaint(Graphics g) {judge();switch (state) {case 0:// 此处为不做改变的代码case 1:// 此处为不做改变的代码case 2:// 此处为不做改变的代码case 3:// 此处为不做改变的代码if (length <= 130) {// 直接移到屏幕外// 此处为不做改变的代码Background.count += o.cost;// 新增此行代码state = 0;Background.fcFlag = false;// 新增此行代码}if (Background.fcFlag) {// 新增此行代码m = 1;}}}}// 此处为不做改变的代码}}
效果图如下:
17.设置关卡
当达到目标钱数后,将进入下一关。
在Backgound类中添加以下两个变量:
public class Background {// 总钱数// 爆竹的数量// 爆竹的状态// 关卡数static int level = 1;// 目标钱数int goal = level * 100;// 背景图片初始化public static void drawText(Graphics g, int size, Color color, String s, int x, int y) {// 此处为不做改变的代码}public void BackgroundPaint(Graphics g) {// 此处为不做改变的代码}
}
再到Game类中添加新代码:
public class Game extends JFrame {// 此处为不做改变的代码/*** 启动程序*/public static void main(String[] args) {// 此处为不做改变的代码}void Game() {// 此处为不做改变的代码while (true) {repaint();nextLevel();// 此行为新增代码// 此处为不做改变的代码}}/*** 下一关*/private void nextLevel() {// 此代码块为新增代码if (Background.count >= bg.goal) {Background.level++;dispose();Game game1 = new Game();game1.Game();}}/*** 绘制游戏地图** @param g*/public void paint(Graphics g) {// 此处为不做改变的代码}
}
再到Background类中绘制相应的面板以便显示目前关数和目标钱数:
public class Background {// 总钱数// 爆竹的数量// 爆竹的状态// 关卡数static int level = 1;// 目标钱数int goal = level * 100;// 背景图片初始化public static void drawText(Graphics g, int size, Color color, String s, int x, int y) {// 此处为不做改变的代码}public void BackgroundPaint(Graphics g) {// 此处为不做改变的代码// 关卡数drawText(g, 20, new Color(143, 112, 1), "第" + level+"关", 370, 60);// 目标钱数drawText(g, 24, new Color(143, 112, 1), "目标钱数:$" + goal, 27, 280);}
}
public void BackgroundPaint(Graphics g) {g.drawImage(bg, 0, 0, null);switch (Game.start) {case 0:drawText(g, 110, new Color(0,0,0), "按空格键以开始游戏", 200, 400);break;case 1:g.drawImage(people, 380, 190, null);drawText(g, 24, new Color(143, 112, 1), "金钱:$" + count, 30, 250);g.drawImage(firecrackers, 580, 250, null);drawText(g, 24, new Color(143, 112, 1), "*" + firecrackersNum, 630, 290);// 关卡数drawText(g, 20, new Color(143, 112, 1), "第" + level + "关", 370, 60);// 目标钱数drawText(g, 24, new Color(143, 112, 1), "目标钱数:$" + goal, 27, 280);break;case 2:break;case 3:break;case 4:break;default:}}
18.设置游戏状态
游戏的最基本的三种状态:游戏开始前、游戏中、游戏结束,游戏结束又分为以失败结束和以通关结束
接下来是根据游戏的状态进行绘制组件:
先在Game类中添加一个游戏状态的变量:
static int start;// 0未开始 1游戏中 2商店 3游戏失败 4游戏成功
并修改该类中的Game()方法:
void Game() {// 此处为不做改变的代码addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {switch (start) {case 0:if (e.getKeyCode() == KeyEvent.VK_SPACE) {start = 1;}break;case 1:if (e.getKeyCode() == KeyEvent.VK_DOWN) {rope.state = 1;}if (e.getKeyCode() == KeyEvent.VK_UP && rope.state == 3 && Background.firecrackersNum > 0) {// 当按下向上键且绳索的状态为3时Background.firecrackersNum--;Background.fcFlag = true;}break;case 2:break;case 3:break;case 4:break;default:}}});while (true) {// 此处为不做改变的代码}}
背景是在任何时候都会绘制,代码不需要根据start的值进行变化。
魔法水,关卡数,目标钱数都是在游戏开始才绘制,所以将Background类中的BackgroundPaint()方法修改为以下代码:
public void BackgroundPaint(Graphics g) {g.drawImage(bg, 0, 0, null);switch (Game.start) {case 0:drawText(g, 30, new Color(252, 25, 68), "按空格键以开始游戏", 280, 120);break;case 1:g.drawImage(people, 380, 190, null);drawText(g, 24, new Color(143, 112, 1), "金钱:$" + count, 30, 250);g.drawImage(firecrackers, 580, 250, null);drawText(g, 24, new Color(143, 112, 1), "*" + firecrackersNum, 630, 290);// 关卡数drawText(g, 20, new Color(143, 112, 1), "第" + level + "关", 370, 60);// 目标钱数drawText(g, 24, new Color(143, 112, 1), "目标钱数:$" + goal, 27, 280);break;case 2:break;case 3:break;case 4:break;default:}}
19.倒计时效果:
在Background类中创建两个变量:
// 游戏开始时间long startTime = 40;// 游戏结束时间long endTime;
并在case 1:中添加以下代码:
// 倒计时
endTime = System.currentTimeMillis();
long t = 40 - (endTime - startTime) / 1000;
drawText(g, 24, new Color(143, 112, 1), "时间:" + t, 30, 220);
返回Game类中Game()方法中的case 0 :初始化startTime:
void Game() {// 此处为不做改变的代码addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {switch (start) {case 0:if (e.getKeyCode() == KeyEvent.VK_SPACE) {start = 1;bg.startTime = System.currentTimeMillis();// 游戏开始时顺便给起始时间赋值}break;case 1:// 此处为不做改变的代码break;case 2:break;case 3:break;case 4:break;default:}}});while (true) {// 此处为不做改变的代码}}
运行效果:
20.失败状态:
先在Background类中创建一个gameTime()方法,以便判断游戏开始后,游戏时间是否大于所设时间,如果是,则代表已经超时了,游戏结束,反之游戏还有剩余时间。
/*** 倒计时** @return true代表倒计时完成,false表示正在倒计时*/boolean gameTime() {long tim = (endTime - startTime) / 1000;if (tim > 40) {return true;}return false;}
在Game类中的nextLevel()方法中修改通关成功的条件:
private void nextLevel() {if (start == 1 && bg.gameTime()) {// 通过成功就进入下一关if (Background.count >= bg.goal) {Background.level++;dispose();Game game1 = new Game();game1.Game();} else {start = 3;// 不成功则进入失败状态}}}
返回 Background类中的BackgroundPaint()方法的case 3:添加以下代码:
case 3:drawText(g, 80, new Color(252, 25, 68), "游戏失败,再接再厉!", 280, 120);// 显示失败信息drawText(g, 50, new Color(12, 207, 103), "所得金钱:$" + count, 305, 150);// 显示所得钱数break;
运行效果:
21.成功状态:
修改Game类中的nextLevel()方法:
private void nextLevel() {if (start == 1 && bg.gameTime()) {// 通过成功就进入下一关if (Background.count >= bg.goal) {if (Background.level == 5) {start = 4;} else {Background.level++;}dispose();Game game1 = new Game();game1.Game();} else {start = 3;// 不成功则进入失败状态}}}
返回 Background类中的BackgroundPaint()方法的case 4:添加以下代码:
case 4:drawText(g, 80, new Color(120, 157, 210), "恭喜你,成功过关!", 280, 120);// 显示失败信息drawText(g, 50, new Color(174, 164, 162), "所得金钱:$" + count, 305, 150);// 显示所得钱数break;
运行效果:
22.重置游戏
在Rope类中添加Reset()方法:
/*** 重置绳索*/void Reset() {angle = 0;length = 130;}
在Background类中添加以下方法:
/*** 重置游戏*/void Reset() {// 总钱数count = 0;// 爆竹的数量firecrackersNum = 3;// 爆竹的状态fcFlag = false;// 关卡数level = 1;// 目标钱数goal = level * 100;}
金块石头的重置实在Game类中的nextLevel中,同时,在进入下一关的时候需要重置时间:
private void nextLevel() {if (start == 1 && bg.gameTime()) {// 通过成功就进入下一关if (Background.count >= bg.goal) {if (Background.level == 5) {start = 4;} else {Background.level++;bg.startTime = System.currentTimeMillis();// 重置时间}} else {start = 3;// 不成功则进入失败状态}dispose();Game game1 = new Game();game1.Game();}}
接下来在Game类中Game()方法的case 4:添加以下代码:
void Game() {// 此处为不做改变的代码addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {switch (start) {case 0:// 此处为不做改变的代码break;case 1:// 此处为不做改变的代码break;case 2:break;case 3:break;case 4:if (e.getKeyCode()==KeyEvent.VK_SPACE){start=0;bg.Reset();rope.Reset();}break;default:}}});while (true) {// 此处为不做改变的代码}}
运行效果:
23.游戏商店:
修改Background类:
public class Background {// 总钱数static int count = 0;// 爆竹的数量static int firecrackersNum = 3;// 爆竹的状态// 关卡数// 目标钱数// 游戏开始时间// 游戏结束时间// 魔法水价格int price = 150;// 是否进入商店boolean enter = false;// 背景图片初始化public static void drawText(Graphics g, int size, Color color, String s, int x, int y) {// 此处为不做改变的代码}public void BackgroundPaint(Graphics g) {g.drawImage(bg, 0, 0, null);switch (Game.start) {case 0:// 此处为不做改变的代码case 1:// 此处为不做改变的代码case 2:g.drawImage(firecrackers, 220, 70, null);drawText(g, 50, new Color(252, 25, 68), "价格:" + price, 280, 100);if (count < 150) {drawText(g, 50, new Color(174, 164, 162), "余额不足", 260, 165);} else {drawText(g, 50, new Color(12, 207, 103), "是否购买?", 280, 130);drawText(g, 50, new Color(174, 164, 162), "是:空格键 否:Esc键", 260, 165);}if (enter) {count = count - price;firecrackersNum++;enter = false;Game.start = 1;startTime = System.currentTimeMillis();}break;case 3:// 此处为不做改变的代码case 4:// 此处为不做改变的代码default:}}/*** 倒计时** @return true代表倒计时完成,false表示正在倒计时*/boolean gameTime() {// 此处为不做改变的代码}/*** 重置游戏*/void Reset() {// 此处为不做改变的代码}
}
在Game类中的Game()方法添加键盘事件:
void Game() {// 此处为不做改变的代码addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {switch (start) {case 0:// 此处为不做改变的代码case 1:// 此处为不做改变的代码case 2:if (e.getKeyCode() == KeyEvent.VK_SPACE) {bg.enter = true;}if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {start = 1;bg.startTime = System.currentTimeMillis();}break;case 3:case 4:// 此处为不做改变的代码default:}}});while (true) {// 此处为不做改变的代码}}
运行效果:
至此,此小游戏完美结束。有脑洞的同学可自行添加功能。
我是码龙,如果我的文章对你有帮助,请点个 赞
<黄金矿工中文版>是一款休闲益智小游戏,游戏中你需要看准时机出钩子勾取金子或者砖石来获得金钱的累加,达到一定的金钱数才能够闯关成功,游戏十分经典,强烈推荐大家学会编写这款游戏,休闲时没网也 ... java小游戏-java小游戏-黄金矿工 1 窗口绘制 2 绘制图片 3 红线绘制 4 红线摇摆 5 红线抓取 6 创建金块 7 双缓存技术 8 抓取判断 9 抓取返回 10 多个金块 11 Bug金 ... Java初学者的小伙伴们,相信大家肯定缺少很多的练手项目吧!今天就给大家推荐一款特别好上手的一个Java小游戏--黄金矿工. 大家听到这个名字的时候,童年的回忆肯定一下子,涌上心头,那如果让大家制作一 ... 你玩过4399曾经最火的黄金矿工小游戏吗,黄金矿工小游戏是一款休闲娱乐的一个挖宝游戏,在游戏中地下会有许多的宝藏,你得想办法把它们都挖出来,作为矿工的你,对你来说是轻车熟路的,能不能挖到宝,看你抓取的 ... 黄金矿工 项目结构 前期准备 Stone类 Gold类(包含Gold类,GoldMini类,GoldPlus类) GameWin类 Line类 Parent类 Sky类 项目结构 GameWin类,游 ... Day 1:窗口绘制并导入背景图片 public class mygame extends JFrame {bj b=new bj();void launch() throws Interrupted ... 基于Java+Swing实现雷电小游戏 一.系统介绍 二.功能展示 三.其他系统 四.获取源码 一.系统介绍 基于java的雷电游戏基本功能包括:敌方飞机随机飞行.我方飞机手动控制飞行,射击比拼,游戏 ... 用Java开发贪食蛇小游戏 一.实验内容 1.实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子&qu ... 用java实现简单的小游戏(你一定玩过) 对于java初学者来说,通过一些学习小游戏来对swing学习以及对java基础的学习是一个好的方法,同时也给学习带来了很多的乐趣,接下来就给大家分享一个jav ...Java游戏项目——仿4399小游戏《黄金矿工》相关推荐
最新文章
热门文章