【经典项目】Java实现多人对战 泡泡堂小游戏(附带源码)

26 篇文章 ¥29.90 ¥99.00
本文详细介绍了使用Java开发的经典泡泡堂小游戏,包括需求分析、游戏实现的各个模块,如地图生成、玩家移动、NPC控制和平滑碰撞处理。文章通过多种设计模式构建项目,提供了丰富的界面展示和资源获取途径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、需求分析

经典游戏使用Java实现快乐泡泡堂小游戏资源-CSDN文库

泡泡堂(Bubble Trouble)是一款经典的在线闯关小游戏,最初由Kresimir Cvitanovic开发。在这款游戏中,玩家控制一个小人,通过射击气泡来消灭敌人。游戏的目标是在每个关卡中消灭所有敌人,避免被气泡碰到或被敌人攻击。游戏的关卡设计相对简单,但随着关卡的深入,敌人的数量和难度会逐渐增加。

泡泡堂的玩法非常简单,但却具有一定的挑战性,玩家需要在尽可能短的时间内消灭所有敌人,同时避免受到伤害。游戏中的气泡可以分裂成更小的气泡,使得玩家需要更加灵活地躲避和射击。

这款游戏在网络上非常受欢迎,因其简单直观的操作和有趣的玩法而备受喜爱。泡泡堂的游戏机制吸引了许多玩家,成为了经典的在线闯关游戏之一。

【预期实现效果】:

二、分析实现

1、前期准备

CrazyArcade泡泡堂游戏,一款用Java编写的JavaSwing游戏程序。 使用了MVC模式,分离了模型、视图和控制器。同时,使用配置文件来设置游戏基本配置,扩展地图人物道具等。同时,该程序编写期间用了单例模式、工厂模式、模板模式等设计模式。

项目架构:

  • frame:包含如游戏开始、游戏中、结束的(界面(JFrame)
  • main:包含主程序开始入口和其它游戏控制
  • model:
    • loader:包含资源加载器用于读取配置文件等信息,使用了单例设计模式
    • manager:包含元素管理器、工厂等,用于控制游戏各元素
    • vo:各种实体类,包括玩家、NPC、炸弹、方块等等
  • pro:配置文件目录,包含人物、道具、地图、方块、游戏设置等配置文件
  • thread:配合游戏一起执行的各种线程,如音乐、键盘监听、游戏控制等
  • utiil:工具包
2、地图生成

地图主要是生成游戏的场景,然后在画布上显示该场景。在开发很多类型的游戏中,地图系统都需要良好的设计,直观的说,需要的地图系统仅仅是一个2D数组,然后用最快的方式将数组影射到屏幕上。

本游戏设计的这个地图是用一些0,1等数组表示一种物体。然后在用流对该文件进行读取,把内容读取到一个数组里面。不同的数字就会在场景中显示出不同的物体。

#0:障碍物方块,1:道路方块,2:可摧毁方块,61:玩家1,73:玩家2(若是单人模式则表示为电脑),8:电脑
#00:空气墙,01:树,02:草垛,03:蓝色小房子,04:黄色小房子
#11:绿色方块,12:灰色地板
#21:橙色方块,22:红色方块,23:木头方块,24:深蓝色铁方块,25:浅蓝色铁方块,
#26:红色路障方块,27:警示牌方块,28:纸箱子方

【墙体素材】

3、玩家移动

该对战过程处理主要是对键盘的监听。当按下键盘的方向键的时候,监听器将捕获该动作,然后将该动作的信息封装为一个消息,在服务器端再对消息进行转发给所有玩家。玩家收到消息,对消息进行解析,得用户的操作,然后改变玩家对应单元格的代码,然后去刷新整个画布,玩家的位置将做出变化。其中在移动玩家的时候,要先判断前方是否有障碍物或者是否已经到达了边界,是的话将不能进行移动。

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

在每次泡泡爆炸后,都要进行一次判断,是否有玩家被炸到。如果有就将该玩家的状态设置为’DEAD’,然后判断整个小组是否所有成员都已经淘汰

有以下三种情况:

  • 玩家被其他玩家淘汰;
  • 当前玩家淘汰所有人赢得游戏;
  • 游戏对局还存在多人未被淘汰,游戏超时;
		//玩家失败
		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");
			}
		}
4、机器人NPC

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

控制npc放炸弹:

设计了一个简单拿的寻路算法,主要是遍历上下左右四个方向。指导原则是前方有炸弹不能走,靠经其他npc不走;主动靠近真人玩家;死路也不走。

判断是否可以打通的路,有路就放个炸弹,炸掉障碍物,开辟道路。

	private void autoAddBubble() {
		GameMap gameMap = ElementManager.getManager().getGameMap();
		List<Integer> loc = GameMap.getIJ(getX(), getY());
		Vector<MoveTypeEnum> oldPath = new Vector<>();
		oldPath.addAll(path);
		gameMap.setBlockSquareType(loc, GameMap.SquareType.BUBBLE);
		boolean find = findSafePath();
		gameMap.setBlockSquareType(loc, GameMap.SquareType.FLOOR);
		if(find&&getBubbleLargest()-getBubbleNum()>0&&Math.random()<0.1) {
			addBubble();
		} else {
			path.clear();
			path.addAll(oldPath);
		}
		return;
	}

5、平滑碰撞

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

	//判断前面是否能走过去
	public boolean judgeForward(MoveTypeEnum m) {
		GameMap gameMap = ElementManager.getManager().getGameMap();
		boolean go = false;
		List<Integer> ijList = GameMap.getIJ(getX(), getY());
		//暂时判断前面是地板即可前进,TODO判断前面是Bubble
		switch(m) {
		case LEFT: if(gameMap.blockIsWalkable(ijList.get(0), ijList.get(1)-1)) go = true;
			break;  
		case RIGHT: if(gameMap.blockIsWalkable(ijList.get(0), ijList.get(1)+1)) go = true;
			break;
		case TOP: if(gameMap.blockIsWalkable(ijList.get(0)-1, ijList.get(1))) go = true;
			break;  
		case DOWN: if(gameMap.blockIsWalkable(ijList.get(0)+1, ijList.get(1))) go = true;
			break;
		case STOP: go=true;
			break;
		}
		return go;
	}

地板暂时相对滑动,保证玩家不会被固定的坐标束缚,导致很难进入一个路口,提高体验感。 

三、界面展示

1、主界面

2、游戏过程

3、游戏支持

【道具类型】

【爆炸效果】

【道具说明】

四、资源获取

经典游戏使用Java实现快乐泡泡堂小游戏资源-CSDN文库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫蜜柚子茶

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值