【精选】Java游戏项目

您所在的位置:网站首页 java项目报告总结 【精选】Java游戏项目

【精选】Java游戏项目

2023-11-17 16:32| 来源: 网络整理| 查看: 265

简介

作者简介:青铜码农,和大多数同学一样从零开始一步步学习,一步步积累。期待您的关注,让我们一起成长~注:本人学疏才浅,文章如有错误之处,敬请指正~

内容简介:实现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 = 1) { dir = -1; } // 此处省略原有代码 } }

效果如图:

眼尖的同学在这里会发现,绳索还是超越了地平线。这个问题很好解决,只需要将新增代码修饰为以下代码:

public class Rope { // 绳索的起点坐标 // 绳索的终点坐标 // 初始化绳索的长度 // 初始化绳索的角度 // 以下为新增代码 // 初始化方向.1表示顺时针0~180度,-1表示逆时针0~180度 int dir = 1; public void Ropepaint(Graphics g) { 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() { @Override public 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.9) { dir = -1; } angle += 0.005 * dir; Rope(g); break; case 1:// 当state=1时,延长绳索抓取 if (length < 650) {// 当绳索的长度小于650时,延长绳索的长度直到绳索的长度等于650 length += 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 goldList = new ArrayList();// 储存金块,有这个集合后,上面一行代码可删除 { 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) { // 此处为不做修改的代码块 } 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 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 = 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() { @Override public 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() { @Override public 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() { @Override public 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() { @Override public 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) { // 此处为不做改变的代码 } }

 运行效果:

至此,此小游戏完美结束。有脑洞的同学可自行添加功能。

 我是码龙,如果我的文章对你有帮助,请点个 赞👍🏻 支持我一下,谢谢~



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3