最終成果程式碼:
踩地雷遊戲 有加上背景音樂和踩到地雷的音效,再加上美化遊戲初始畫面。
PImage bombImage; // 儲存炸彈的圖片 PImage grassImage;//遊戲起始畫面下面的草圖片 boolean gameover = false; int gameoverTime; int[][] mine; boolean[][] open; int selectedLevel = 0;//0表示未選擇級別 1表示第一關 2.... 3... int gameState = 0; // 0表示起始畫面,1表示遊戲中,2表示Level 2 int totalMines; import ddf.minim.*; Minim minim; AudioPlayer backgroundMusic; AudioPlayer explosionSound; void openAll(int i, int j) { if (i < 0 || j < 0 || i >= rows || j >= cols || gameover) return; if (open[i][j] == true) return; open[i][j] = true; //如果是炸彈,顯示所有炸彈 if (mine[i][j] == 9) { revealAllBombs(); gameover = true;//遊戲結束 gameoverTime = millis();//紀錄遊戲結束時間 } //如果是0,則遞迴打開相鄰格子 if (mine[i][j] == 0) { openAll(i - 1, j); openAll(i, j - 1); openAll(i, j + 1); openAll(i + 1, j); } } void addOne(int i, int j) { if (i < 0 || j < 0 || i >= rows || j >= cols) return;//範圍外,不處理 if (mine[i][j] == 9) return;//地雷本身不用再+1 mine[i][j]++;//如果不是就+1 } void revealAllBombs() { //將所有炸彈顯示為已開啟,以顯示所有炸彈 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (mine[i][j] == 9) { open[i][j] = true; } } } } int rows , cols; int cellSize; void setup() { size(500, 500,P2D); rows = 16; cols = 30; cellSize = width / cols;//根據視窗大小和格子數量計算格子大小 int mineCount = 0; //載入炸彈圖片 bombImage = loadImage("bomb.png"); grassImage = loadImage("grass.png"); minim = new Minim(this); // 載入背景音樂文件(替換成你的音樂文件路徑) backgroundMusic = minim.loadFile("mixkit-feeling-happy-5.mp3"); explosionSound = minim.loadFile("mini_bomb1.mp3"); // 播放背景音樂 backgroundMusic.play(); } void draw() { background(210,233,255); image(grassImage,width / 4 -125, height / 2 + 100, width / 2 + 250, 150);//150是圖片縱向長度 前面的width/height是畫布的長寬 if (gameState == 0) { //遊戲首頁文字說明中的標題踩地雷遊戲 fill(0,0,0); textAlign(CENTER,CENTER);//字置中 PFont font = createFont("微軟正黑體 Bold",30);//改字型 textFont(font); text("踩地雷遊戲",width / 2, height / 20); textSize(20);//踩地雷遊戲第一關文字說明 fill(0,0,0); textAlign(CENTER,CENTER);//字置左 text("第一關: 10*10的格子 9 個地雷",width / 2 - 20 , height / 6);//調x軸的值 字可以到最左邊 textSize(20);//踩地雷第二關文字說明 fill(0,0,0); textAlign(CENTER,CENTER);//字置左 text("第二關: 16*16的格子 30個地雷",width / 2 - 10 , height / 4);//調x軸的值 字可以到最左邊 textSize(20);//踩地雷第三關文字說明 fill(0,0,0); textAlign(CENTER,CENTER);//字置左 text("第三關: 16*30的格子 60個地雷",width / 2 - 10, height / 3);//調x軸的值 字可以到最左邊 // 起始畫面 level1 按鈕 fill(100, 100, 200);//按鈕的顏色 rect(width / 4, height / 2 - 25, width / 2, 50); fill(255);//字的顏色 白色 textSize(20); textAlign(CENTER, CENTER); text("LEVEL1", width / 2, height / 2 - 5); // level2 按鈕 fill(100, 100, 200); rect(width / 4, height / 2 + 25, width / 2, 50); fill(255); textSize(20); textAlign(CENTER, CENTER); text("LEVEL2", width / 2, height / 2 + 45); // level3 按鈕 fill(100, 100, 200); rect(width / 4, height / 2 + 75, width / 2, 50); fill(255); textSize(20); textAlign(CENTER, CENTER); text("LEVEL3", width / 2, height / 2 + 95); } else if (gameState == 1 || gameState == 2) { // 踩地雷遊戲 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (open[i][j]) { if (mine[i][j] == 0) { fill(150);//沒有地雷也沒有數字的空白格子 顏色是深灰色 } else { fill(200);//有數字的格子 顏色是淡灰色 } rect(j * cellSize, i * cellSize, cellSize, cellSize); if (mine[i][j] == 0) continue;//如果格子為空就繼續 if (mine[i][j] == 1) //如果數字為1 { textSize(20); fill(0, 0, 255); textAlign(CENTER, CENTER); text("" + mine[i][j], j * cellSize + cellSize / 2, i * cellSize + cellSize / 2); } else if (mine[i][j] == 2) //如果數字為2 { textSize(20); fill(24, 123, 29); textAlign(CENTER, CENTER); text("" + mine[i][j], j * cellSize + cellSize / 2, i * cellSize + cellSize / 2); } else if (mine[i][j] == 3) //如果數字為3 { textSize(20); fill(255, 0, 0); textAlign(CENTER, CENTER); text("" + mine[i][j], j * cellSize + cellSize / 2, i * cellSize + cellSize / 2); } else if (mine[i][j] == 9) //如果是踩到地雷 { image(bombImage, j * cellSize, i * cellSize, cellSize, cellSize); } } else { fill(200);//沒有被打開的格子 顏色是淡灰色 rect(j * cellSize, i * cellSize, cellSize, cellSize); } } } } if (gameover && millis() - gameoverTime > 5000) {//最後遊戲結束的畫面 若遊戲結束/遊戲結束時間超過2000毫秒(2秒) background(0);//背景黑色 textSize(50); fill(255, 0, 0);//紅色的字 textAlign(CENTER, CENTER); text("Game Over", width / 2, height / 2); fill ( 100,100,200 );//restart的按鈕 rect( width/4 , height /2 +50 ,width / 2 , 50); fill( 255 ); textSize(20); textAlign(CENTER,CENTER); text("RESTART", width / 2 , height / 2 +75); } } void mousePressed() { if (gameState == 0) //在遊戲一開始的畫面檢查哪一個按鈕被按 { // level1 按鈕 if (mouseX > width / 4 && mouseX < width / 4 + width / 2 && mouseY > height / 2 - 25 && mouseY < height / 2 + 25) { selectedLevel = 1;//選擇第一關的按鈕 gameState = 1;//遊戲狀態 initializeGame();//初始化遊戲 } // level2 按鈕 else if ( mouseX > width / 4 && mouseX < width / 4 + width / 2 && mouseY > height / 2 + 25 && mouseY < height / 2 + 75 ) { selectedLevel = 2; gameState = 1;//遊戲狀態 initializeLevel2(); } // level3 按鈕 else if ( mouseX > width / 4 && mouseX < width / 4 + width / 2 && mouseY > height / 2 + 75 && mouseY < height / 2 + 125 ) { selectedLevel = 3; gameState = 1; initializeLevel3(); } } else if (gameState == 1 || gameState == 2) { // 獲取滑鼠點擊的位子 int i = mouseY / cellSize; int j = mouseX / cellSize; //格子沒有被打開 if (!open[i][j]) {//就打開 openAll(i, j); } if (mine[i][j] == 9) { // 如果點擊到炸彈,播放爆炸音效 explosionSound.rewind(); explosionSound.play(); } //遊戲結束且結束過5秒後 看有沒有點restart鍵 if (gameover && millis() - gameoverTime > 4000) { if (mouseX > width / 4 && mouseX < width / 4 + width / 2 && mouseY > height / 2 + 50 && mouseY < height / 2 + 100) { restartGame(); } } } } void initializeGame() { int mineCount = 0; if (selectedLevel == 1) { rows = 10; cols = 10; totalMines = 9; cellSize = width / cols; surface.setSize(cols * cellSize, rows * cellSize); } else if (selectedLevel == 2) { rows = 16; cols = 16; totalMines = 30; cellSize = width / cols; surface.setSize(cols * cellSize, rows * cellSize); } else if (selectedLevel == 3) { rows = 16; cols = 30; totalMines = 60; cellSize = width / cols; surface.setSize(cols * cellSize, rows * cellSize); } mine = new int[rows][cols]; open = new boolean[rows][cols]; while (mineCount < totalMines) { int i = int(random(rows)), j = int(random(cols)); if (mine[i][j] != 9) { mine[i][j] = 9; mineCount++; } } for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (mine[i][j] == 9) { addOne(i - 1, j - 1); addOne(i - 1, j); addOne(i - 1, j + 1); addOne(i, j - 1); addOne(i, j + 1); addOne(i + 1, j - 1); addOne(i + 1, j); addOne(i + 1, j + 1); } } } } void initializeLevel2() { int mineCount = 0; rows = 16; cols = 16; totalMines = 30; cellSize = width / cols; // 根據視窗大小和格子數量計算格子大小 mine = new int[rows][cols]; open = new boolean[rows][cols]; while (mineCount < totalMines) { int i = int(random(rows)), j = int(random(cols)); if (mine[i][j] != 9) { mine[i][j] = 9; mineCount++; } } surface.setSize(cols * cellSize, rows * cellSize); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (mine[i][j] == 9) { addOne(i - 1, j - 1); addOne(i - 1, j); addOne(i - 1, j + 1); addOne(i, j - 1); addOne(i, j + 1); addOne(i + 1, j - 1); addOne(i + 1, j); addOne(i + 1, j + 1); } } } } void initializeLevel3() { int mineCount = 0; rows = 16; cols = 30; totalMines = 60; cellSize = 30; mine = new int[rows][cols]; open = new boolean[rows][cols]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { open[i][j] = false; } } while (mineCount < totalMines) { int i = int(random(rows)), j = int(random(cols)); if (mine[i][j] != 9) { mine[i][j] = 9; mineCount++; } } surface.setSize(cols * cellSize, rows * cellSize); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (mine[i][j] == 9) { addOne(i - 1, j - 1); addOne(i - 1, j); addOne(i - 1, j + 1); addOne(i, j - 1); addOne(i, j + 1); addOne(i + 1, j - 1); addOne(i + 1, j); addOne(i + 1, j + 1); } } } } void restartGame() { gameState = 0;//初始化遊戲狀態 gameover = false;//重置遊戲結束為false gameoverTime = 0;//重置遊戲結束時間 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { open[i][j] = false; mine[i][j] = 0; } } } void stop() { // 在應用程式結束時關閉音樂 backgroundMusic.close(); explosionSound.close(); minim.stop(); super.stop(); }
沒有留言:
張貼留言