【精选】Java游戏项目 |
您所在的位置:网站首页 › java项目报告总结 › 【精选】Java游戏项目 |
简介
作者简介:青铜码农,和大多数同学一样从零开始一步步学习,一步步积累。期待您的关注,让我们一起成长~注:本人学疏才浅,文章如有错误之处,敬请指正~ 内容简介:实现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.游戏商店: 功能预览:《黄金矿工》 游戏中一些对象的介绍 :在类中创建一个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(); }运行效果如图: 说明:绳索会左右摇摆且可以收回来。 创建一个绳索Rope类,并初始化绳索的起点坐标和终点坐标以及绳索的长度,绳索摆动的角度 绳索的终点坐标算法如图: 运行效果如图: 如果想让绳索不停的转动,只需要在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); } }运行效果如图: 此模块运用的是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) { // 此处省略不做修改的代码 } }效果如图: 之前的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; } } }效果如图: 利用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; } } }效果如图: 在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) { // 此处为不做修改的代码块 } }运行效果: 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: } }![]() 在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) { // 此处为不做改变的代码 } }运行效果: 先在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;运行效果: 修改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;运行效果: 在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) { // 此处为不做改变的代码 } } 运行效果:![]() 修改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 |