冒泡游戏java_消灭泡泡糖游戏java代码

冒泡游戏java_消灭泡泡糖游戏java代码对战版

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

前言

《泡泡堂对战版》是一个基于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分钟

	
	@Override
	public 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 exception
				e.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<>();
	
	@Override
	public 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;
			}
		}
	}

	
	@Override
	public 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;
				}
			}
			
		}
	}

	@Override
	public void keyTyped(KeyEvent arg0) { 
   
		// TODO 自动生成的方法存根
		
	}
	
	public void clearKeyStatcks() { 
   
		p1PressStack.clear();
		p2PressStack.clear();
	}

}

总结

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

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

源码获取

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/194115.html原文链接:https://javaforall.net

(0)
上一篇 2025年11月12日 上午10:15
下一篇 2025年11月12日 上午10:43


相关推荐

  • Pycharm Debug调试(纯干货)

    Pycharm Debug调试(纯干货)使用 Debug 调试代码 1 打断点一个断点标记了一个代码行 当 Pycharm 运行到该行代码时会将程序暂时挂起 注意断点会将对应的代码行标记为红色 取消断点的操作也很简单 在同样位置再次单击即可 如图所示 打了两个断点当你将鼠标指针悬停在断点上方时 Pycharm 会显示断点的关键信息 行号以及脚本属性 如果你希望更改该断点的属性 右击断点 可以尝试对断点属性进行个性化更改 然后观察图标

    2026年3月27日
    2
  • RHCSA_rhce考试题库

    RHCSA_rhce考试题库1、SElinux必须运行在Enforcing模式下。1、SElinux必须运行在Enforcing模式下。2、配置YUM源,使用地址http://content.example.com/rhel

    2022年8月6日
    5
  • WinRAR去除广告,亲测可用

    WinRAR去除广告,亲测可用原文地址:最新去除中文winrar压缩软件弹出广告方法-百度经验(baidu.com) 此文用作备用文,在原文看不到的情况下,参考本文。感谢原文作者!!! 安装RAR简体中文版 下载并安装Restorator2007 找到RAR安装文件夹,可以双击打开RAR.exe看是否弹出广告 打开Restorator2007 选着左上角“文件-打开”,在“C:\ProgramFiles\WinRAR”文件夹中打开“WinRAR.exe” 打开后.

    2022年6月3日
    43
  • @pytest.mark.parametrize_pytest参数化可变参数

    @pytest.mark.parametrize_pytest参数化可变参数前言当某个接口中的一个字段,里面规定的范围为1-5,你5个数字都要单独写一条测试用例,就太麻烦了,这个时候可以使用pytest.mark.parametrize装饰器可以实现测试用例参数化。官方示

    2022年7月31日
    9
  • android hybrid框架_基于android的app开发

    android hybrid框架_基于android的app开发转载请标明出处:一片枫叶的专栏本文将介绍Android中hybrid开发相关的知识点。hybrid开发实际上是混合开发的意思,这里的混合是H5开发与Native开发混合的意思。下面的文章中我们将逐个介绍一下hybrid开发的概念、hybrid开发的优势、Android中如何实现hybrid开发、简单的hybrid开发的例子,以及在产品实践中对hybrid开发的应用,希望通过本篇文章的介绍让您能够对A

    2026年2月18日
    5
  • EasyPlayer简介

    EasyPlayer简介EasyPlayer简介EasyPlayer是一款基于EasyRTSPClient实现的AndroidRTSP播放器。目前实现的功能有:播放视频视频画面放大,拖动(类似360小水滴的拖动功能)开启、关闭声音抓拍录像保存视频缩略图

    2022年6月16日
    71

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号