当前位置:   article > 正文

Java实现大鱼吃小鱼游戏(开源)_java大鱼吃小鱼

java大鱼吃小鱼

前言 :

游戏参考于B站_【尚学堂】大鱼吃小鱼,主体框架不变,代码稍有改动。

大鱼吃小鱼:又称吞食鱼,是一款动作类小游戏。通过不断的吞吃比自己小的鱼类快速成长,最终成为海洋霸主。

游戏主要Java知识:变量、数据类型、判断语句、循环结构、类的继承、简单窗口创建、图形图片绘制、双缓存技术、鼠标事件、键盘事件。

非常适合在同学Java学习结束后,作为不错的结课作业或者练手项目。

源码已经在文章结束语后打包,有兴趣的同学可以免费下载,创作不易,点个免费的赞支持一下!

运行环境:jdk-17.05

操作方法:w,s,a,d (英文输入法)控制小鱼方向

游戏主要框架:

游戏素材:

游戏代码:

(1)Bg类

  1. import java.awt.*;
  2. public class Bg {
  3. void paintSelf(Graphics g, int fishLevel) {
  4. g.drawImage(GameUtils.bgimg, 0, 0, null);
  5. switch (GameWin.state) {
  6. case 0:
  7. GameUtils.drawWord(g, "开始", Color.red, 80, 600, 400);
  8. break;
  9. case 1:
  10. GameUtils.drawWord(g, "积分" + GameUtils.count, Color.ORANGE, 50, 200, 120);
  11. GameUtils.drawWord(g, "难度" + GameUtils.level, Color.ORANGE, 50, 600, 120);
  12. GameUtils.drawWord(g, "等级" + fishLevel, Color.ORANGE, 50, 1000, 120);
  13. break;
  14. case 2:
  15. GameUtils.drawWord(g, "积分" + GameUtils.count, Color.ORANGE, 50, 200, 120);
  16. GameUtils.drawWord(g, "难度" + GameUtils.level, Color.ORANGE, 50, 600, 120);
  17. GameUtils.drawWord(g, "等级" + fishLevel, Color.ORANGE, 50, 1000, 120);
  18. GameUtils.drawWord(g, "失败", Color.red, 80, 580, 450);
  19. break;
  20. case 3:
  21. GameUtils.drawWord(g, "积分" + GameUtils.count, Color.ORANGE, 50, 200, 120);
  22. GameUtils.drawWord(g, "难度" + GameUtils.level, Color.ORANGE, 50, 600, 120);
  23. GameUtils.drawWord(g, "等级" + fishLevel, Color.ORANGE, 50, 1000, 120);
  24. GameUtils.drawWord(g, "胜利了!", Color.ORANGE, 80, 580, 450);
  25. case 4:
  26. break;
  27. default:
  28. }
  29. }
  30. }

(2)Enamy类

  1. import java.awt.*;
  2. //敌方鱼父类
  3. public class Enamy {
  4. //定义图片
  5. Image img;
  6. //物体坐标
  7. int x;
  8. int y;
  9. int width;
  10. int height;
  11. //移动速度
  12. int speed;
  13. //方向
  14. int dir = 1;
  15. //类型
  16. int type;
  17. //分值
  18. int count;
  19. //绘制自身方法
  20. public void paintSelf(Graphics g) {
  21. g.drawImage(img, x, y, width, height, null);
  22. }
  23. //获取自身矩形,用于碰撞检测
  24. public Rectangle getRec() {
  25. return new Rectangle(x, y, width - 45, height - 30);
  26. }
  27. }
  28. //敌方鱼左类
  29. class Enamy_1_L extends Enamy {
  30. Enamy_1_L() {
  31. this.x = -45;
  32. this.y = (int) (Math.random() * 980);
  33. this.width = 40;
  34. this.height = 55;
  35. this.speed = 1;
  36. this.count = 1;
  37. this.type = 1;
  38. this.img = GameUtils.enamyl_1img;
  39. }
  40. @Override
  41. public Rectangle getRec() {
  42. return new Rectangle(x, y, width, height);
  43. }
  44. }
  45. //敌方鱼右类
  46. class Enamy_1_R extends Enamy_1_L {
  47. Enamy_1_R() {
  48. this.x = 1400;
  49. dir = -1;
  50. this.img = GameUtils.enamyr_1img;
  51. }
  52. }
  53. class Enamy_2_L extends Enamy {
  54. Enamy_2_L() {
  55. this.x = -100;
  56. this.y = (int) (Math.random() * 900 + 100);
  57. this.width = 180;
  58. this.height = 80;
  59. this.speed = 5;
  60. this.count = 3;
  61. this.type = 2;
  62. this.img = GameUtils.enamyl_2img;
  63. }
  64. }
  65. class Enamy_2_R extends Enamy_2_L {
  66. Enamy_2_R() {
  67. this.x = 1400;
  68. dir = -1;
  69. this.img = GameUtils.enamyr_2img;
  70. }
  71. }
  72. class Enamy_3_L extends Enamy {
  73. Enamy_3_L() {
  74. this.x = -300;
  75. this.y = (int) (Math.random() * 980);
  76. this.width = 250;
  77. this.height = 150;
  78. this.speed = 3;
  79. this.count = 10;
  80. this.type = 3;
  81. this.img = GameUtils.enamyl_3img;
  82. }
  83. }
  84. class Enamy_3_R extends Enamy_3_L {
  85. Enamy_3_R() {
  86. this.x = 1400;
  87. dir = -1;
  88. this.img = GameUtils.enamyr_3img;
  89. }
  90. }
  91. class Enamy_Boss extends Enamy {
  92. Enamy_Boss() {
  93. this.x = -1200;
  94. this.y = (int) (Math.random() * 700 + 100);
  95. this.width = 250;
  96. this.height = 200;
  97. this.speed = 80;
  98. this.type = 10;
  99. this.img = GameUtils.bossimg;
  100. }
  101. }

(3)GameUtils类

  1. import java.awt.*;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class GameUtils {
  5. //方向
  6. static boolean UP = false;
  7. static boolean DOWN = false;
  8. static boolean LEFT = false;
  9. static boolean RIGHT = false;
  10. //分数
  11. static int count = 0;
  12. //关卡等级
  13. static int level = 0;
  14. //背景图
  15. public static Image bgimg = Toolkit.getDefaultToolkit().createImage("src/images/sea.jpg");
  16. //敌方鱼类集合
  17. public static List<Enamy> EnamyList = new ArrayList<>();
  18. //敌方鱼类
  19. public static Image enamyl_1img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish1_r.gif");
  20. public static Image enamyr_1img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish1_l.gif");
  21. public static Image enamyl_2img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish2_r.png");
  22. public static Image enamyr_2img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish2_l.png");
  23. public static Image enamyl_3img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish3_r.gif");
  24. public static Image enamyr_3img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish3_l.gif");
  25. public static Image bossimg = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/boss.gif");
  26. //我方鱼类
  27. public static Image MyFishimg_L = Toolkit.getDefaultToolkit().createImage("src/images/myFish/myfish_left.gif");
  28. public static Image MyFishimg_R = Toolkit.getDefaultToolkit().createImage("src/images/myFish/myfish_right.gif");
  29. //绘制文字的工具类
  30. public static void drawWord(Graphics g, String str, Color color, int size, int x, int y) {
  31. g.setColor(color);
  32. g.setFont(new Font("宋体", Font.BOLD, size));
  33. g.drawString(str, x, y);
  34. }
  35. }

(4)GameWin类

  1. package com.mzy;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. import java.awt.event.KeyAdapter;
  5. import java.awt.event.KeyEvent;
  6. import java.awt.event.MouseAdapter;
  7. import java.awt.event.MouseEvent;
  8. public class GameWin extends JFrame {
  9. /**
  10. * 游戏状态 0未开始,1游戏中,2通关失败,3通关成功,4暂停,5重新开始
  11. */
  12. //定义游戏默认状态
  13. static int state = 0;
  14. //双缓存图片
  15. Image offScreenImage;
  16. //窗口宽高
  17. int width = 1320;
  18. int height = 780;
  19. //计数器
  20. double random;
  21. int time = 0;
  22. //背景对象
  23. Bg bg = new Bg();
  24. //敌方鱼类
  25. Enamy enamy = new Enamy_1_L();
  26. //我方鱼类
  27. MyFish myFish = new MyFish();
  28. //boss鱼类
  29. Enamy boss;
  30. //是否生成boss
  31. boolean isboss = false;
  32. /**
  33. * 游戏操作方法
  34. */
  35. public void launch() {
  36. Music audioPlayWave = new Music("src/皇家萌卫.wav");
  37. audioPlayWave.start();
  38. @SuppressWarnings("unused")
  39. int musicOpenLab = 1;
  40. //界面布局
  41. this.setVisible(true);
  42. this.setSize(width, height);
  43. this.setLocationRelativeTo(null);
  44. this.setTitle("大鱼吃小鱼");
  45. this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
  46. //开始或者失败后重新游戏
  47. this.addMouseListener(new MouseAdapter() {
  48. @Override
  49. public void mouseClicked(MouseEvent e) {
  50. super.mouseClicked(e);
  51. if (e.getButton() == 1 && state == 0) {
  52. state = 1;
  53. repaint();
  54. }
  55. if (e.getButton() == 1 && (state == 2 || state == 3)) {
  56. reGame();
  57. state = 1;
  58. }
  59. }
  60. });
  61. //键盘移动我方鱼类
  62. this.addKeyListener(new KeyAdapter() {
  63. @Override //按压
  64. public void keyPressed(KeyEvent e) {
  65. super.keyPressed(e);
  66. if (e.getKeyCode() == 87) {
  67. GameUtils.UP = true;
  68. }
  69. if (e.getKeyCode() == 83) {
  70. GameUtils.DOWN = true;
  71. }
  72. if (e.getKeyCode() == 65) {
  73. GameUtils.LEFT = true;
  74. }
  75. if (e.getKeyCode() == 68) {
  76. GameUtils.RIGHT = true;
  77. }
  78. if (e.getKeyCode() == 32) {
  79. switch (state) {
  80. case 1:
  81. state = 4;
  82. GameUtils.drawWord(getGraphics(), "游戏暂停!", Color.red, 50, 580, 450);
  83. break;
  84. case 4:
  85. state = 1;
  86. break;
  87. }
  88. }
  89. }
  90. @Override //抬起
  91. public void keyReleased(KeyEvent e) {
  92. if (e.getKeyCode() == 87) {
  93. GameUtils.UP = false;
  94. }
  95. if (e.getKeyCode() == 83) {
  96. GameUtils.DOWN = false;
  97. }
  98. if (e.getKeyCode() == 65) {
  99. GameUtils.LEFT = false;
  100. }
  101. if (e.getKeyCode() == 68) {
  102. GameUtils.RIGHT = false;
  103. }
  104. }
  105. });
  106. //线程操纵游戏帧率
  107. while (true) {
  108. repaint();
  109. time++;
  110. try {
  111. Thread.sleep(40);
  112. } catch (InterruptedException e) {
  113. e.printStackTrace();
  114. }
  115. }
  116. }
  117. /**
  118. * 游戏阶段绘制鱼类
  119. */
  120. @Override
  121. public void paint(Graphics g) {
  122. //双缓存加载图片
  123. offScreenImage = createImage(width, height);
  124. Graphics gImage = offScreenImage.getGraphics();
  125. bg.paintSelf(gImage, myFish.level);
  126. switch (state) {
  127. case 0:
  128. break;
  129. case 1:
  130. myFish.paintSelf(gImage);
  131. logic();
  132. for (Enamy enamy : GameUtils.EnamyList) {
  133. enamy.paintSelf(gImage);
  134. }
  135. if (isboss) {
  136. boss.x = boss.x + boss.dir * boss.speed;
  137. boss.paintSelf(gImage);
  138. if (boss.x < 0) {
  139. gImage.setColor(Color.red);
  140. gImage.fillRect(boss.x, boss.y + 100, 2400, boss.height / 20);
  141. }
  142. }
  143. break;
  144. case 2:
  145. for (Enamy enamy : GameUtils.EnamyList) {
  146. enamy.paintSelf(gImage);
  147. }
  148. if (isboss) {
  149. boss.paintSelf(gImage);
  150. }
  151. break;
  152. case 3:
  153. myFish.paintSelf(gImage);
  154. break;
  155. case 4:
  156. return;
  157. default:
  158. }
  159. g.drawImage(offScreenImage, 0, 0, null);
  160. }
  161. /**
  162. * 游戏关卡难度逻辑
  163. */
  164. void logic() {
  165. //关卡难度
  166. if (GameUtils.count < 5) {
  167. GameUtils.level = 0;
  168. } else if (GameUtils.count < 15) {
  169. GameUtils.level = 1;
  170. } else if (GameUtils.count < 40) {
  171. GameUtils.level = 2;
  172. } else if (GameUtils.count < 75) {
  173. GameUtils.level = 3;
  174. } else if (GameUtils.count > 150) {
  175. state = 3;
  176. }
  177. //我方鱼升级
  178. if (29 < GameUtils.count && GameUtils.count < 79) {
  179. myFish.level = 2;
  180. } else if (GameUtils.count > 79) {
  181. myFish.level = 3;
  182. }
  183. //阶段生成敌方鱼
  184. random = Math.random();
  185. switch (GameUtils.level) {
  186. case 3:
  187. if (time % 120 == 0) {
  188. boss = new Enamy_Boss();
  189. isboss = true;
  190. }
  191. case 2:
  192. if (time % 120 == 0) {
  193. if (random < 0.5) {
  194. enamy = new Enamy_3_L();
  195. } else {
  196. enamy = new Enamy_3_R();
  197. }
  198. }
  199. GameUtils.EnamyList.add(enamy);
  200. case 1:
  201. if (time % 60 == 0) {
  202. if (random < 0.5) {
  203. enamy = new Enamy_2_L();
  204. } else {
  205. enamy = new Enamy_2_R();
  206. }
  207. }
  208. GameUtils.EnamyList.add(enamy);
  209. case 0:
  210. if (time % 10 == 0) {
  211. if (random < 0.5) {
  212. enamy = new Enamy_1_L();
  213. } else {
  214. enamy = new Enamy_1_R();
  215. }
  216. }
  217. GameUtils.EnamyList.add(enamy);
  218. break;
  219. default:
  220. }
  221. //生成敌方鱼
  222. for (Enamy enamy : GameUtils.EnamyList) {
  223. enamy.x = enamy.x + enamy.dir * enamy.speed;
  224. //boss鱼碰撞检测
  225. if (isboss) {
  226. if (boss.getRec().intersects(enamy.getRec())) {
  227. enamy.x = -200;
  228. enamy.y = -200;
  229. }
  230. if (boss.getRec().intersects(myFish.getRec())) {
  231. state = 2;
  232. }
  233. }
  234. //我方鱼与敌方鱼碰撞检测
  235. if (myFish.getRec().intersects(enamy.getRec())) {
  236. if (myFish.level >= enamy.type) {
  237. enamy.x = -200;
  238. enamy.y = -200;
  239. GameUtils.count += enamy.count;
  240. } else {
  241. state = 2;
  242. }
  243. }
  244. }
  245. }
  246. public static void main(String[] args) {
  247. GameWin gameWin = new GameWin();
  248. gameWin.launch();
  249. }
  250. //重新开始
  251. void reGame() {
  252. GameUtils.EnamyList.clear();
  253. time = 0;
  254. myFish.level = 1;
  255. GameUtils.count = 0;
  256. myFish.x = 650;
  257. myFish.y = 400;
  258. myFish.width = 45;
  259. myFish.height = 45;
  260. boss = null;
  261. isboss = false;
  262. }
  263. }

(5)Music类

  1. package com.mzy;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import javax.sound.sampled.AudioFormat;
  5. import javax.sound.sampled.AudioInputStream;
  6. import javax.sound.sampled.AudioSystem;
  7. import javax.sound.sampled.DataLine;
  8. import javax.sound.sampled.FloatControl;
  9. import javax.sound.sampled.LineUnavailableException;
  10. import javax.sound.sampled.SourceDataLine;
  11. import javax.sound.sampled.UnsupportedAudioFileException;
  12. public class Music extends Thread {
  13. private String fileName;
  14. private final int EXTERNAL_BUFFER_SIZE = 524288;
  15. public Music(String wavFile) {
  16. this.fileName = wavFile;
  17. }
  18. @SuppressWarnings("unused")
  19. public void run() {
  20. System.out.println("音乐播放");
  21. File soundFile = new File(fileName); // 播放音乐的文件名
  22. if (!soundFile.exists()) {
  23. System.err.println("Wave file not found:" + fileName);
  24. return;
  25. }
  26. while (true) { // 设置循环播放
  27. AudioInputStream audioInputStream = null; // 创建音频输入流对象
  28. try {
  29. audioInputStream = AudioSystem.getAudioInputStream(soundFile); // 创建音频对象
  30. } catch (UnsupportedAudioFileException e1) {
  31. e1.printStackTrace();
  32. return;
  33. } catch (IOException e1) {
  34. e1.printStackTrace();
  35. return;
  36. }
  37. AudioFormat format = audioInputStream.getFormat(); // 音频格式
  38. SourceDataLine auline = null; // 源数据线
  39. DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
  40. try {
  41. auline = (SourceDataLine) AudioSystem.getLine(info);
  42. auline.open(format);
  43. } catch (LineUnavailableException e) {
  44. e.printStackTrace();
  45. return;
  46. } catch (Exception e) {
  47. e.printStackTrace();
  48. return;
  49. }
  50. if (auline.isControlSupported(FloatControl.Type.PAN)) {
  51. FloatControl pan = (FloatControl) auline.getControl(FloatControl.Type.PAN);
  52. }
  53. auline.start();
  54. int nBytesRead = 0;
  55. byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
  56. try {
  57. while (nBytesRead != -1) {
  58. nBytesRead = audioInputStream.read(abData, 0, abData.length);
  59. if (nBytesRead >= 0)
  60. auline.write(abData, 0, nBytesRead);
  61. }
  62. } catch (IOException e) {
  63. e.printStackTrace();
  64. return;
  65. } finally {
  66. auline.drain();
  67. // auline.close();
  68. }
  69. }
  70. }
  71. }

(6)MyFish类

  1. import java.awt.*;
  2. public class MyFish {
  3. //图片
  4. Image img = GameUtils.MyFishimg_L;
  5. //坐标
  6. int x = 650;
  7. int y = 400;
  8. int width = 45;
  9. int height = 45;
  10. //移动速度
  11. int speed = 20;
  12. //等级
  13. int level = 1;
  14. //移动
  15. void logic() {
  16. if (GameUtils.UP) {
  17. y = y - speed;
  18. }
  19. if (GameUtils.DOWN) {
  20. y = y + speed;
  21. }
  22. if (GameUtils.LEFT) {
  23. x = x - speed;
  24. img = GameUtils.MyFishimg_L;
  25. }
  26. if (GameUtils.RIGHT) {
  27. x = x + speed;
  28. img = GameUtils.MyFishimg_R;
  29. }
  30. }
  31. //绘制自身方法
  32. public void paintSelf(Graphics g) {
  33. logic();
  34. g.drawImage(img, x, y, width + GameUtils.count, height + GameUtils.count, null);
  35. }
  36. //获取自身矩形方法,用于碰撞检测
  37. public Rectangle getRec() {
  38. return new Rectangle(x, y, width + GameUtils.count, height + GameUtils.count);
  39. }
  40. }

结束语:

游戏还有很多缺陷地方,比如我方鱼可以离开界面,敌方鱼在离开界面后没有及时清除,游戏玩法过于简单。都需要小伙伴们自己去改进,挖掘。

游戏源码下载解压后,注意打开项目的文件夹位置,出现报错,游戏界面白屏等问题,都可以私信帮忙解决。

源码:

链接:https://pan.baidu.com/s/1QyuhE1KaM_RupqLpUkr1JA 
提取码:2czk

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/804633
推荐阅读
相关标签
  

闽ICP备14008679号