欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實現(xiàn)泡泡堂對戰(zhàn)版游戲的示例代碼

 更新時間:2022年04月06日 08:51:27   作者:小虛竹and掘金  
本文將利用Java制作經(jīng)典游戲《泡泡堂》,文中使用了MVC模式,分離了模型、視圖和控制器,使得項目結(jié)構(gòu)清晰易于擴展,感興趣的可以了解一下

前言

《泡泡堂II》是一個基于java的自制游戲,使用了MVC模式,分離了模型、視圖和控制器,使得項目結(jié)構(gòu)清晰易于擴展,使用配置文件來設(shè)置游戲基本配置,擴展地圖人物道具等。同時,該程序編寫期間用了單例模式、工廠模式、模板模式等設(shè)計模式。為了游戲的可玩性,特意設(shè)計了平滑碰撞以及機器人。

主要設(shè)計

  • 設(shè)計游戲界面,用swing實現(xiàn)
  • 繪制游戲啟動界面、結(jié)束界面、地圖、主角、道具
  • 實現(xiàn)泡泡爆炸
  • 為了盡量復(fù)原泡泡堂游戲,初步實現(xiàn)了機器人功能。該機器人可以判斷障礙物釋放炸彈、規(guī)避炸彈、攻擊玩家。
  • 實現(xiàn)道具掉落和相應(yīng)屬性加成
  • 實現(xiàn)游戲音效和背景音樂
  • 平滑碰撞:人物在拐角處移動的時候經(jīng)常不是剛好對齊的狀態(tài),程序會判定玩家碰撞了障礙物所以導(dǎo)致玩家無法拐彎。所以我們在處理這種情況的時候,會讓玩家進行平滑的移動使得玩家看上去是滑進去的,增強玩家游戲體驗
  • 設(shè)計單/雙人模式

功能截圖

游戲啟動界面:

道具說明:

游戲開始:

釋放炸彈·:

炸彈爆炸效果:

代碼實現(xiàn)

游戲啟動類

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);
	
		//強制刷新,否則監(jiān)聽無效
		gameFrame.setVisible(false);
		gameFrame.setVisible(true);
	}
	
	public static void startNewGame() {
		GameController.setGameRunning(true);
		gameFrame.startGame();
		changeJPanel("game");
	}

}

核心監(jiān)聽類

public class GameThread extends Thread{
	private boolean running; //表示當前關(guān)卡是否在進行
	private boolean over = false; //表示游戲是否結(jié)束,結(jié)束返回開始菜單
	private static int sleepTime = 20; //runGame刷新時間
	//倒計時變量
	private static int allTime = 600*1000; //10分鐘

	
	@Override
	public void run() {
		while(!over) {
			running = true;//當前關(guān)卡正在進行
			//加載元素
			loadElement();
			//顯示人物,流程,自動化
			runGame();
			//結(jié)束當前關(guān)
			overGame(over);
		}
		GameStart.changeJPanel("over");
	}
	
	//加載元素
	private void loadElement() {
		ElementManager.getManager().loadMap();//加載地圖及其元素
	}
	
	/**
	 * 關(guān)卡結(jié)束
	 * 如果over為真則游戲失敗返回界面,否則進入下一關(guān)
	 * @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調(diào)用,加入拓展
	public void linkGame() {}
	

	public static int getAllTime() {
		return allTime;
	}


}

核心線程類

public class GameKeyListener implements KeyListener{
	/**
	 * 用棧來解決按鍵沖突
	 * 每個棧用來存放不同用戶的按鍵,通過判斷按鍵的code來設(shè)置移動方向或者攻擊
	 * 
	 */

	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();
	}

}

總結(jié)

通過此次的《泡泡堂對戰(zhàn)版》實現(xiàn),讓我對JAVA的相關(guān)知識有了進一步的了解,對java這門語言也有了比以前更深刻的認識。

java的一些基本語法,比如數(shù)據(jù)類型、運算符、程序流程控制和數(shù)組等,理解更加透徹。java最核心的核心就是面向?qū)ο笏枷?,對于這一個概念,終于悟到了一些。

以上就是Java實現(xiàn)泡泡堂對戰(zhàn)版游戲的示例代碼的詳細內(nèi)容,更多關(guān)于Java泡泡堂的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java中的BlockingQueue(阻塞隊列)解析

    java中的BlockingQueue(阻塞隊列)解析

    這篇文章主要介紹了java中的BlockingQueue阻塞隊列解析,阻塞隊列是一個支持兩個附加操作的隊列,這兩個附加的操作是,在隊列為空時,獲取元素的線程會等待隊列變?yōu)榉强?需要的朋友可以參考下
    2023-12-12
  • Java版本和C++版本的二叉樹序列化與反序列化

    Java版本和C++版本的二叉樹序列化與反序列化

    這篇文章主要介紹了Java版本和C++版本的二叉樹序列化與反序列化,二叉樹就是節(jié)點在內(nèi)存區(qū)域中串聯(lián)起來的,但是如果掉電,內(nèi)存上的數(shù)據(jù)就沒有了。為了保存這種結(jié)構(gòu),將二叉樹用字符串的形式保存到硬盤中,這就是序列化;從字符串形式轉(zhuǎn)換為二叉樹,這就是反序列化
    2022-06-06
  • 解決Springboot配置excludePathPatterns不生效的問題

    解決Springboot配置excludePathPatterns不生效的問題

    這篇文章主要介紹了解決Springboot配置excludePathPatterns不生效的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 詳解Spring Boot 異步執(zhí)行方法

    詳解Spring Boot 異步執(zhí)行方法

    這篇文章主要介紹了Spring Boot 異步執(zhí)行方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • java實現(xiàn)隨機森林RandomForest的示例代碼

    java實現(xiàn)隨機森林RandomForest的示例代碼

    本篇文章主要介紹了java實現(xiàn)隨機森林RandomForest的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • Spring實戰(zhàn)之使用@Resource配置依賴操作示例

    Spring實戰(zhàn)之使用@Resource配置依賴操作示例

    這篇文章主要介紹了Spring實戰(zhàn)之使用@Resource配置依賴操作,結(jié)合實例形式分析了Spring使用@Resource配置依賴具體步驟、實現(xiàn)及測試案例,需要的朋友可以參考下
    2019-12-12
  • Java中動態(tài)地改變數(shù)組長度及數(shù)組轉(zhuǎn)Map的代碼實例分享

    Java中動態(tài)地改變數(shù)組長度及數(shù)組轉(zhuǎn)Map的代碼實例分享

    這篇文章主要介紹了Java中動態(tài)地改變數(shù)組長度及數(shù)組轉(zhuǎn)map的代碼分享,其中轉(zhuǎn)Map利用到了java.util.Map接口,需要的朋友可以參考下
    2016-03-03
  • Java實現(xiàn)實時監(jiān)控目錄下文件變化的方法

    Java實現(xiàn)實時監(jiān)控目錄下文件變化的方法

    今天小編就為大家分享一篇關(guān)于Java實現(xiàn)實時監(jiān)控目錄下文件變化的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • 聊聊spring繼承的問題

    聊聊spring繼承的問題

    這篇文章主要介紹了spring繼承的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 使用@RequestBody傳對象參數(shù)時碰到的坑

    使用@RequestBody傳對象參數(shù)時碰到的坑

    這篇文章主要介紹了使用@RequestBody傳對象參數(shù)時碰到的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評論