前言

《泡泡堂对战版》是一个基于java的自制游戏,使用了MVC模式,分离了模型、视图和控制器,使得项目结构清晰易于扩展,使用配置文件来设置游戏基本配置,扩展地图人物道具等。同时,该程序编写期间用了单例模式、工厂模式、模板模式等设计模式。为了游戏的可玩性,特意设计了平滑碰撞以及机器人。

主要设计

  1. 设计游戏界面,用swing实现

  2. 绘制游戏启动界面、结束界面、地图、主角、道具

  3. 实现泡泡爆炸

  4. 为了尽量复原泡泡堂游戏,初步实现了机器人功能。该机器人可以判断障碍物释放炸弹、规避炸弹、攻击玩家。

  5. 实现道具掉落和相应属性加成

  6. 实现游戏音效和背景音乐

  7. 平滑碰撞:人物在拐角处移动的时候经常不是刚好对齐的状态,程序会判定玩家碰撞了障碍物所以导致玩家无法拐弯。所以我们在处理这种情况的时候,会让玩家进行平滑的移动使得玩家看上去是滑进去的,增强玩家游戏体验

  8. 设计单/双人模式

功能截图

游戏启动界面:

道具说明:

游戏开始:

释放炸弹·:

炸弹爆炸效果:

代码实现

游戏启动类


public class GameStart {private static GameFrame gameFrame;//游戏启动入口public static void main(String[] args) {// 资源加载try {ElementLoader.getElementLoader().readGamePro();ElementLoader.getElementLoader().readImagePro();ElementLoader.getElementLoader().readCharactorsPro();ElementLoader.getElementLoader().readBubblePro();ElementLoader.getElementLoader().readSquarePro();} catch (IOException e) {System.out.println("资源加载失败");e.printStackTrace();}//初始化gameFrame = new GameFrame();//界面显示gameFrame.setVisible(true);//音乐播放GameMusicPlayer musicPlayer = new GameMusicPlayer();musicPlayer.start();}/*** 界面切换* @param panelName 界面名称*/public static void changeJPanel(String panelName){if(panelName == "game") {GameController.setGameRunning(true);gameFrame.addListener();} else {GameController.setGameRunning(false);gameFrame.removeListener();}gameFrame.changePanel(panelName);//强制刷新,否则监听无效gameFrame.setVisible(false);gameFrame.setVisible(true);}public static void startNewGame() {GameController.setGameRunning(true);gameFrame.startGame();changeJPanel("game");}}

核心监听类


public class GameThread extends Thread{private boolean running; //表示当前关卡是否在进行private boolean over = false; //表示游戏是否结束,结束返回开始菜单private static int sleepTime = 20; //runGame刷新时间//倒计时变量private static int allTime = 600*1000; //10分钟@Overridepublic void run() {while(!over) {running = true;//当前关卡正在进行//加载元素loadElement();//显示人物,流程,自动化runGame();//结束当前关overGame(over);}GameStart.changeJPanel("over");}//加载元素private void loadElement() {ElementManager.getManager().loadMap();//加载地图及其元素}/*** 关卡结束* 如果over为真则游戏失败返回界面,否则进入下一关* @param over*/private void overGame(Boolean over) {ElementManager.getManager().overGame(over);}//显示人物,游戏流程,自动化private void runGame() {allTime = 600*1000;while(running) {Map<String, List<SuperElement>> map = ElementManager.getManager().getMap();Set<String> set = map.keySet();for(String key:set) {List<SuperElement> list = map.get(key);for(int i=list.size()-1; i>=0; i--) {list.get(i).update();if(!list.get(i).isAlive())list.remove(i);}}//添加游戏的流程控制linkGame()?//玩家与炸弹碰撞死亡playerBoom();//可破坏物与炸弹碰撞fragilityBoom();//电脑与炸弹碰撞死亡npcBoom();//电脑与道具碰撞效果,暂时不开启//npcMagicBox();//玩家与道具碰撞效果playerMagicBox();//检测是否玩家全部死亡defeat();//控制runGame进程allTime = allTime - sleepTime;try {  sleep(20);} catch (InterruptedException e) {// TODO: handle exceptione.printStackTrace();}}}private void defeat() {boolean allDead = true;int surviveP = 0;int winner = 2;//0为玩家1,1为玩家2,2为电脑获胜List<SuperElement> playerList = ElementManager.getManager().getElementList("player");List<SuperElement> npcList = ElementManager.getManager().getElementList("npc");for(SuperElement se:playerList) {if(!((Player)se).isDead()) {surviveP++;}}for(SuperElement npc:npcList) {if(!((Npc)npc).isDead()) {allDead = false;}}//玩家失败if(surviveP==0||(allTime<=0 && !allDead)) {running = false;over = true;OverJPanel.getResult().setText("defeated");}//玩家胜利if(allDead&&surviveP==1) {running = false;over = true;for(SuperElement se:playerList) {if(!((Player)se).isDead()) {surviveP++;winner = ((Player)se).getPlayerNum();}}OverJPanel.getResult().setText("player "+(winner+1)+" win");}//时间到,两个玩家都活着if(allTime<=0&&surviveP==2&&allDead) {running = false;over = true;int score1 = ((Player)playerList.get(0)).score;int score2 = ((Player)playerList.get(0)).score;if(score1==score2) {OverJPanel.getResult().setText("defeated");}else if(score1>score2){OverJPanel.getResult().setText("player 1 win");}else {OverJPanel.getResult().setText("player 2 win");}}}//玩家与炸弹碰撞判断private void playerBoom() {List<SuperElement> playerList = ElementManager.getManager().getElementList("player");List<SuperElement> explodeList = ElementManager.getManager().getElementList("explode");for(int i=0; i<playerList.size(); i++) {for(int j=0; j<explodeList.size(); j++) {if(explodeList.get(j).crash(playerList.get(i))){Player player = (Player) playerList.get(i);player.setHealthPoint(-1);//生命值-1}}}}//npc与炸弹碰撞判断private void npcBoom() {List<SuperElement> playerList = ElementManager.getManager().getElementList("player");List<SuperElement> npcList = ElementManager.getManager().getElementList("npc");List<SuperElement> explodeList = ElementManager.getManager().getElementList("explode");for(int i=0; i<npcList.size(); i++) {for(int j=0; j<explodeList.size(); j++) {if(explodeList.get(j).crash(npcList.get(i))){Npc npc = (Npc) npcList.get(i);npc.setDead(true);npc.setX(-100);npc.setY(-100);BubbleExplode e = (BubbleExplode)explodeList.get(j);if(e.getPlayerNum()<2)//目前只有玩家计分((Player)playerList.get(e.getPlayerNum())).setScore(((Player)playerList.get(e.getPlayerNum())).getScore()+50);}}}}//障碍物与炸弹碰撞判断private void fragilityBoom() {List<SuperElement> playerList = ElementManager.getManager().getElementList("player");List<SuperElement> explodes = ElementManager.getManager().getElementList("explode");List<SuperElement> fragility = ElementManager.getManager().getElementList("fragility");for(int i=0; i<fragility.size(); i++) {for(int j=0; j<explodes.size(); j++) {if(explodes.get(j).crash(fragility.get(i))) {MapFragility mapFragility = (MapFragility)fragility.get(i);mapFragility.setDestoried(true);BubbleExplode e = (BubbleExplode)explodes.get(j);if(e.getPlayerNum()<2)//目前只有玩家计分((Player)playerList.get(e.getPlayerNum())).setScore(((Player)playerList.get(e.getPlayerNum())).getScore()+10);}}}}//玩家与道具碰撞判断private void playerMagicBox() {List<SuperElement> playerList = ElementManager.getManager().getElementList("player");List<SuperElement> magicBoxList = ElementManager.getManager().getElementList("magicBox");for(int i=0; i<playerList.size(); i++) {for(int j=magicBoxList.size()-1; j>=0; j--) {if(magicBoxList.get(j).crash(playerList.get(i))){MagicBox magicBox = (MagicBox) magicBoxList.get(j);magicBox.setCharacterIndex(i);//谁吃方块magicBox.setEaten(true);//方块被吃((Player)playerList.get(i)).setScore(((Player)playerList.get(i)).getScore()+30);}}}}//玩家与道具碰撞判断private void npcMagicBox() {List<SuperElement> npcList = ElementManager.getManager().getElementList("npc");List<SuperElement> magicBoxList = ElementManager.getManager().getElementList("magicBox");for(int i=0; i<npcList.size(); i++) {for(int j=magicBoxList.size()-1; j>=0; j--) {if(magicBoxList.get(j).crash(npcList.get(i))){MagicBox magicBox = (MagicBox) magicBoxList.get(j);magicBox.setCharacterIndex(i+2);//谁吃方块magicBox.setEaten(true);//方块被吃}}}}//runGame调用,加入拓展public void linkGame() {}public static int getAllTime() {return allTime;}}

核心线程类

public class GameKeyListener implements KeyListener{/*** 用栈来解决按键冲突* 每个栈用来存放不同用户的按键,通过判断按键的code来设置移动方向或者攻击* */private List<?> list;private Stack<Integer> p1PressStack = new Stack<>();private Stack<Integer> p2PressStack = new Stack<>();@Overridepublic void keyPressed(KeyEvent e) {list = ElementManager.getManager().getElementList("player");Player player1 = (Player) list.get(0);int code = e.getKeyCode();switch (code) {case 10://炸弹键if(player1.isKeepAttack())//不允许一直按着炸弹键,每次只能放一个炸弹player1.setAttack(false);else {player1.setKeepAttack(true);player1.setAttack(true);}break;case 37://左右上下case 38:case 39:case 40:if(!p1PressStack.contains(code)) {p1PressStack.push(code);}player1.setMoveType(MoveTypeEnum.codeToMoveType(code));break;default://其它按键无视break;}if(GameController.isTwoPlayer()) {Player player2 = (Player) list.get(1);switch (code) {case 32:if(player2.isKeepAttack())player2.setAttack(false);else {player2.setKeepAttack(true);player2.setAttack(true);}break;case 65:case 87:case 68:case 83:if(!p2PressStack.contains(code)) {p2PressStack.push(code);}player2.setMoveType(MoveTypeEnum.codeToMoveType(code));break;default:break;}}}@Overridepublic void keyReleased(KeyEvent e) {List<?> list = ElementManager.getManager().getElementList("player");int code = e.getKeyCode();Player player1 = (Player) list.get(0);if(!player1.isDead()) {switch (code) {case 10:player1.setAttack(false);player1.setKeepAttack(false);break;case 37:case 38:case 39:case 40:if(p1PressStack.peek()!=code) {p1PressStack.remove(new Integer(code));} else {p1PressStack.pop();if(p1PressStack.size()==0) {player1.setMoveType(MoveTypeEnum.STOP);} else {player1.setMoveType(MoveTypeEnum.codeToMoveType(p1PressStack.peek()));}}break;default:break;}}if(GameController.isTwoPlayer()) {Player player2 = (Player) list.get(1);if(!player2.isDead()) {switch (code) {case 32:player2.setAttack(false);player2.setKeepAttack(false);break;case 65:case 87:case 68:case 83:if(p2PressStack.peek()!=code) {p2PressStack.remove(new Integer(code));} else {p2PressStack.pop();if(p2PressStack.size()==0) {player2.setMoveType(MoveTypeEnum.STOP);} else {player2.setMoveType(MoveTypeEnum.codeToMoveType(p2PressStack.peek()));}}break;default:break;}}}}@Overridepublic void keyTyped(KeyEvent arg0) {// TODO 自动生成的方法存根}public void clearKeyStatcks() {p1PressStack.clear();p2PressStack.clear();}}

总结

通过此次的《泡泡堂对战版》实现,让我对JAVA的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。

java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。

源码获取

涉及《泡泡堂》版权,无法托管!

点赞,关注博主后,私聊博主免费获取

今天是持续写作的第 27 / 100 天。
可以关注我,点赞我、评论我、收藏我啦。

JAVA 实现《泡泡堂对战版》游戏相关推荐

  1. 一文教你用java实现儿时的超级玛丽游戏

    导读:近年来,Java作为一种新的编程语言,以其简单性.可移植性和平台无关性等优点,得到了广泛地应用.J2SE称为Java标准版或Java标准平台.J2SE提供了标准的SDK开发平台.利用该平台可以开 ...

  2. java实现儿时的超级玛丽游戏

    导读:近年来,Java作为一种新的编程语言,以其简单性.可移植性和平台无关性等优点,得到了广泛地应用.J2SE称为Java标准版或Java标准平台.J2SE提供了标准的SDK开发平台.利用该平台可以开 ...

  3. java简单通讯录的实现02person类_用java实现简单的小游戏(你一定玩过)

    用java实现简单的小游戏(你一定玩过) 对于java初学者来说,通过一些学习小游戏来对swing学习以及对java基础的学习是一个好的方法,同时也给学习带来了很多的乐趣,接下来就给大家分享一个jav ...

  4. java实现简单窗体小游戏----球球大作战

    java实现简单窗体小游戏----球球大作战 需求分析 1.分析小球的属性: ​ 坐标.大小.颜色.方向.速度 2.抽象类:Ball ​ 设计类:BallMain-创建窗体 ​ BallJPanel- ...

  5. main java game,playgame 一个JAVA编写的飞行小游戏,有基本完整的 框架,适合初学者参照学习 Other s 其他 238万源代码下载- www.pudn.com...

    文件名称: playgame下载 收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 7050 KB 上传时间: 2013-06-06 下载次数: 3 提 供 者: Lyq ...

  6. 简易贪吃蛇小游戏java版_用GUI实现java版贪吃蛇小游戏

    本文实例为大家分享了java版贪吃蛇小游戏的具体代码,供大家参考,具体内容如下 项目结构 新建一个JFrame窗口,作为程序入口 public class GameStart{ public stat ...

  7. [Leedcode][JAVA][第45题][跳跃游戏 II][贪心算法]

    [问题描述][Leedcode][JAVA][第45题][跳跃游戏 II] 输入: [2,3,1,1,4] 输出: 2 解释: 跳到最后一个位置的最小跳跃数是 2.从下标为 0 跳到下标为 1 的位置 ...

  8. java演练 猜奇偶小游戏开发 DB游戏必输的设计

    java演练 猜奇偶小游戏开发 DB游戏必输的设计 阶段一,视频 https://www.ixigua.com/6870390946270446088?logTag=J_BVJOm_LIpQ-hWYY ...

  9. 递归走迷宫java,java递归实现的迷宫游戏

    java递归实现的迷宫游戏 public class Migong { private int gard[][]={  {1,1,1,1,0,1,1,1}, {0,0,0,1,1,1,1,1}, {1 ...

  10. 推箱子游戏的java设计思路_用JAVA实现一个推箱子游戏

    技术应用 TECHNOLOGY AND MARKET Vol. 26,No. 2,2019 用 JAVA 实现一个推箱子游戏 马寅璞1,孔阳坤2 ( 1. 南京信息工程大学计算机软件学院物联网工程 1 ...

最新文章

  1. 如何将C#对象转换为.NET中的JSON字符串?
  2. adobe reader java_使用PDF框设置的表单字段值在Adobe Reader中不可见
  3. Delphi 2010 新增功能之: 软键盘、触摸键盘(TTouchKeyboard)
  4. 通过cmd命令,杀掉占用端口号的进程
  5. php语法高亮编辑器,最新PHPCMS V9编辑器代码高亮显示亲测可用(提前格式化)
  6. Java中文件复制的一个汇总
  7. 【python】面向对象的封装、继承、多态的练习题
  8. Arcgis javascript那些事儿(十五)——影像服务的发布与使用
  9. 如何开发Web3D游戏
  10. POJ1182 食物链【并查集】
  11. [WCF] Contract
  12. 语音识别行业技术和市场横向对比
  13. 计算机程序不支持中文文件目录怎么办,电脑软件打开时提示找不到指定路径
  14. dimens文件生成器使用方法
  15. 点连通度与边连通度的求解
  16. JSP完成添加商品时的图片上传
  17. Selenium中的隐式等待和显式等待
  18. 用计算机画魔方的一个面,计算机求解魔方算法.pdf
  19. 2021年,你读了哪些不错的C++书籍?
  20. gif制作软件哪个好用?建议收藏这些软件

热门文章

  1. 分布式存储与传统存储架构
  2. eclipse导入项目出现红色感叹号?
  3. 计算数组中N个数的平均值(均为正数),将小于平均值的数放到数组前部,大于等于平均值的数放到数组后部。
  4. FAT16介绍与结构
  5. 5G来啦!!技术指标和三大应用场景
  6. 工信部前部长苗圩:5G应用场景约80%是To B,车联网或是最大应用(附关键数据)...
  7. 【PPT】数字化转型的主要任务、挑战与措施
  8. 你不是不努力,但成功的为什么不是你?
  9. 【Redash 官方文档】查询-创建和编辑查询
  10. Pymol指令大全。官方社区——海量Pymol作图的代码