<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
建立一個遊戲視窗類 GameWin,建立一個 launch() 啟動方法,在其中設定視窗相關屬性:
import javax.swing.*; public class GameWin extends JFrame { int width = 1440; int height = 900; //建立一個啟動方法,設定視窗資訊 public void launch() { this.setVisible(true); //設定視窗可見 this.setSize(width, height); //設定視窗大小 this.setLocationRelativeTo(null); //設定視窗居中 this.setResizable(false); //設定視窗大小不可改變 this.setTitle("大魚吃小魚"); //設定視窗標題 this.setDefaultCloseOperation(EXIT_ON_CLOSE); //設定視窗按鈕 } }
建立一個遊戲視窗測試類 GameWinDemo,進行視窗物件的建立和啟動方法的呼叫:
public class GameWinDemo { public static void main(String[] args) { //建立一個遊戲視窗物件 GameWin gameWin = new GameWin(); //啟動視窗 gameWin.launch(); } }
將下載的背景圖片的資料夾複製到專案資料夾中:
建立一個工具類 GameUtils,在其中新增背景圖片:
import java.awt.*; public class GameUtils { public static Image bgimg = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\sea.jpg"); }
在 GameWin 類中新增 paint 方法,在其中繪製背景圖片:
@Override public void paint(Graphics g) { //用畫筆繪製背景圖片 g.drawImage(GameUtils.bgimg, 0, 0, null); }
如果發現背景圖片載入不出來,先檢查一下路徑有沒有寫錯,相對路徑不行的話就試試絕對路徑;有時候載入背景圖片會較慢,可以試著將執行出來的視窗最小化後再恢復
定義預設遊戲狀態,同時在 paint 方法中對遊戲狀態進行判斷進而顯示對應的遊戲介面:
import javax.swing.*; import java.awt.*; public class GameWin extends JFrame { int width = 1440; int height = 900; //定義遊戲預設狀態 static int state = 0; //建立一個啟動方法,設定視窗資訊 public void launch() { this.setVisible(true); //設定視窗可見 this.setSize(width, height); //設定視窗大小 this.setLocationRelativeTo(null); //設定視窗居中 this.setResizable(false); //設定視窗大小不可改變 this.setTitle("大魚吃小魚"); //設定視窗標題 this.setDefaultCloseOperation(EXIT_ON_CLOSE); //設定視窗按鈕 } @Override public void paint(Graphics g) { //用畫筆繪製背景圖片 g.drawImage(GameUtils.bgimg, 0, 0, null); //遊戲狀態:0未開始,1遊戲中,2遊戲失敗,3遊戲勝利,4遊戲暫停,5重新開始 switch (state) { case 0: g.drawImage(GameUtils.bgimg, 0, 0, null); //為啟動頁面新增文字 g.setColor(Color.pink); g.setFont(new Font("仿宋", Font.BOLD, 60)); g.drawString("請點選開始遊戲", 600, 500); break; case 1: break; case 2: break; case 3: break; case 4: break; default: break; } } }
在啟動方法中新增滑鼠監聽器,當點選啟動頁面時遊戲開始
//建立一個啟動方法,設定視窗資訊 public void launch() { this.setVisible(true); //設定視窗可見 this.setSize(width, height); //設定視窗大小 this.setLocationRelativeTo(null); //設定視窗居中 this.setResizable(false); //設定視窗大小不可改變 this.setTitle("大魚吃小魚"); //設定視窗標題 this.setDefaultCloseOperation(EXIT_ON_CLOSE); //設定視窗按鈕 //新增滑鼠監聽事件 this.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getButton() == 1 && state == 0) { state = 1; repaint(); } } }); }
新建一個背景圖的實體類 Bg,在 GameWin 類裡建立其物件,並在 case 1 中呼叫繪製背景圖的方法
import java.awt.*; public class Bg { void paintSelf(Graphics g) { g.drawImage(GameUtils.bgimg, 0, 0, null); } }
由於遊戲中需要不斷繪製背景圖片,所以我們在啟動方法中新增一個 while 迴圈,在其中每隔 40 毫秒重繪背景圖
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class GameWin extends JFrame { int width = 1440; int height = 900; //定義遊戲預設狀態 static int state = 0; //獲取背景圖類的物件 Bg bg = new Bg(); //建立一個啟動視窗,設定視窗資訊 public void launch() throws InterruptedException { this.setVisible(true); //設定視窗可見 this.setSize(width, height); //設定視窗大小 this.setLocationRelativeTo(null); //設定視窗居中 this.setResizable(false); //設定視窗大小不可改變 this.setTitle("大魚吃小魚"); //設定視窗標題 this.setDefaultCloseOperation(EXIT_ON_CLOSE); //設定視窗按鈕 //新增滑鼠監聽事件 this.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getButton() == 1 && state == 0) { state = 1; repaint(); } } }); //背景圖片重複使用,需要重複呼叫repaint方法 while(true) { repaint(); Thread.sleep(40); } } @Override public void paint(Graphics g) { //用畫筆繪製背景圖片 g.drawImage(GameUtils.bgimg, 0, 0, null); switch (state) { case 0: g.drawImage(GameUtils.bgimg, 0, 0, null); //為啟動頁面新增文字 g.setColor(Color.pink); g.setFont(new Font("仿宋", Font.BOLD, 60)); g.drawString("請點選開始遊戲", 500, 500); break; case 1: bg.paintSelf(g); break; case 2: break; case 3: break; case 4: break; default: break; } } }
如果此時你的螢幕出現閃爍的情況,可以用下面的方法解決
整體思路為:
重新建立一個空的圖片,將所有的元件先繪製到空的圖片上,然後把繪製好的圖片一次性地繪製到主視窗上
建立一個空圖片物件,在 paint 方法中將所有元件繪製到空圖片上,再一次性繪製到主視窗上
public class GameWin extends JFrame { int width = 1440; int height = 900; //定義遊戲預設狀態 static int state = 0; //獲取背景圖類的物件 Bg bg = new Bg(); //建立一個空圖片物件 Image offScreenImage; //建立一個啟動視窗,設定視窗資訊 public void launch() throws InterruptedException { this.setVisible(true); //設定視窗可見 this.setSize(width, height); //設定視窗大小 this.setLocationRelativeTo(null); //設定視窗居中 this.setResizable(false); //設定視窗大小不可改變 this.setTitle("大魚吃小魚"); //設定視窗標題 this.setDefaultCloseOperation(EXIT_ON_CLOSE); //設定視窗按鈕 //新增滑鼠監聽事件 this.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getButton() == 1 && state == 0) { state = 1; repaint(); } } }); //背景圖片重複使用,需要重複呼叫repaint方法 while (true) { repaint(); Thread.sleep(40); } } @Override public void paint(Graphics g) { //懶載入模式初始化物件 offScreenImage = createImage(width, height); Graphics gImage = offScreenImage.getGraphics(); //獲取圖片對應的畫筆物件 switch (state) { case 0: //把元件重新繪製到主視窗中 gImage.drawImage(GameUtils.bgimg, 0, 0, null); //為啟動頁面新增文字 gImage.setColor(Color.pink); gImage.setFont(new Font("仿宋", Font.BOLD, 60)); gImage.drawString("請點選開始遊戲", 500, 500); break; case 1: bg.paintSelf(gImage); break; case 2: break; case 3: break; case 4: break; default: break; } //將繪製好的圖片一次性繪製到主視窗中 g.drawImage(offScreenImage, 0, 0, null); } }
新建敵方魚的父類別 Enamy,編寫左敵方魚類 Enamy_1_L 繼承父類別
import java.awt.*; public class Enamy { //定義圖片 Image img; //定義物體座標 int x; int y; int width; int height; //移動速度 int speed; //方向 int dir = 1; //敵方魚的型別、分值 int type; int count; //繪製自身方法 public void paintSelf(Graphics g) { g.drawImage(img, x, y, width, height, null); } //獲取自身矩形用於碰撞檢測 public Rectangle getRec() { return new Rectangle(x, y, width, height); } } //左敵方魚類 class Enamy_1_L extends Enamy { Enamy_1_L() { this.x = -45; this.y = (int) (Math.random() * 700 + 100); this.width = 45; this.height = 69; this.speed = 10; this.count = 1; this.img = GameUtils.enamy_l_img; } }
在 GameUtils 類中新增左敵方魚類的圖片
public class GameUtils { //背景圖 public static Image bgimg = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\sea.jpg"); //敵方魚類 public static Image enamy_l_img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\fish1_r.gif"); }
在 GameWin 類中建立左敵方魚類物件並在 case 1 的情況下繪製左敵方魚類
public class GameWin extends JFrame { //...... //敵方魚類 Enamy enamy = new Enamy_1_L(); //建立一個啟動視窗,設定視窗資訊 public void launch() throws InterruptedException { //...... } @Override public void paint(Graphics g) { //懶載入模式初始化物件 offScreenImage = createImage(width, height); Graphics gImage = offScreenImage.getGraphics(); //獲取圖片對應的畫筆物件 switch (state) { case 0: //把元件重新繪製到主視窗中 gImage.drawImage(GameUtils.bgimg, 0, 0, null); //為啟動頁面新增文字 gImage.setColor(Color.pink); gImage.setFont(new Font("仿宋", Font.BOLD, 60)); gImage.drawString("請點選開始遊戲", 500, 500); break; case 1: bg.paintSelf(gImage); enamy.paintSelf(gImage); enamy.x += enamy.speed; break; case 2: break; case 3: break; case 4: break; default: break; } //將繪製好的圖片一次性繪製到主視窗中 g.drawImage(offScreenImage, 0, 0, null); } }
在工具類中建立一個所有敵方魚物體的集合
public class GameUtils { //敵方魚類集合 public static List<Enamy> EnamyList = new ArrayList<>(); //...... }
在視窗類中新增一個方法,用於批次新增敵方魚類
public class GameWin extends JFrame { //...... //敵方魚類 Enamy enamy; //計數器,用來記錄遊戲的重繪次數,也是魚生成的數量 int time = 0; //建立一個啟動視窗,設定視窗資訊 public void launch() throws InterruptedException { //...... }); //背景圖片重複使用,需要重複呼叫repaint方法 while (true) { repaint(); time++; Thread.sleep(40); } } @Override public void paint(Graphics g) { //懶載入模式初始化物件 offScreenImage = createImage(width, height); Graphics gImage = offScreenImage.getGraphics(); //獲取圖片對應的畫筆物件 switch (state) { case 0: //...... case 1: bg.paintSelf(gImage); logic(); //不斷新增敵方魚類 //遍歷敵方魚類集合,繪製敵方魚類 for (Enamy enamy : GameUtils.EnamyList) { enamy.paintSelf(gImage); } break; case 2: break; case 3: break; case 4: break; default: break; } //將繪製好的圖片一次性繪製到主視窗中 g.drawImage(offScreenImage, 0, 0, null); } //批次新增魚類 void logic() { //每重繪10次生成一條敵方魚類 if (time % 10 == 0) { enamy = new Enamy_1_L(); GameUtils.EnamyList.add(enamy); } //移動方向 for (Enamy enamy : GameUtils.EnamyList) { enamy.x = enamy.x + enamy.dir * enamy.speed; } } }
在工具類中新增我方魚類的圖片
public class GameUtils { //...... //我方魚類 public static Image myFishImg_L = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\myFish\myfish_left.gif"); public static Image myFishImg_R = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\myFish\myfish_right.gif"); }
建立我方魚類
import java.awt.*; public class MyFish { //圖片 Image img = GameUtils.myFishImg_L; //座標 int x = 700; int y = 500; int width = 50; int height = 50; //移動速度 int speed = 20; //等級 int level = 1; //繪製自身的方法 public void paintSelf(Graphics g) { g.drawImage(img, x, y, width, height, null); } //獲取自身矩形的方法 public Rectangle getRec() { return new Rectangle(x, y, width, height); } }
在視窗類中獲取我方魚的物件
//我方魚類 MyFish myFish = new MyFish();
在工具類中新增方向判定,用來控制我方魚的方向
public class GameUtils { //方向 static boolean UP = false; static boolean DOWN = false; static boolean LEFT = false; static boolean RIGHT = false; //...... }
在我方魚類新增一個方法,實現對鍵盤的控制
public class MyFish { //...... //繪製自身的方法 public void paintSelf(Graphics g) { //呼叫方法 logic(); g.drawImage(img, x, y, width, height, null); } //...... void logic() { if (GameUtils.UP) { y = y - speed; } if (GameUtils.DOWN) { y = y + speed; } if (GameUtils.LEFT) { x = x - speed; img = GameUtils.myFishImg_L; } if (GameUtils.RIGHT) { x = x + speed; img = GameUtils.myFishImg_R; } } }
在視窗類的 paint 方法的 case 1 中,新增我方魚類所創造的方法
import javax.swing.*; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class GameWin extends JFrame { //...... //我方魚類 MyFish myFish = new MyFish(); //建立一個啟動視窗,設定視窗資訊 public void launch() throws InterruptedException { //...... }); //鍵盤移動 this.addKeyListener(new KeyAdapter() { @Override//按壓 public void keyPressed(KeyEvent e) { //上下左右四個鍵的ASCII值為 上 ↑:38下 ↓: 40左 ←: 37右 →: 39 if (e.getKeyCode() == 38) { GameUtils.UP = true; } if (e.getKeyCode() == 40) { GameUtils.DOWN = true; } if (e.getKeyCode() == 37) { GameUtils.LEFT = true; } if (e.getKeyCode() == 39) { GameUtils.RIGHT = true; } } @Override//擡起 public void keyReleased(KeyEvent e) { if (e.getKeyCode() == 38) { GameUtils.UP = false; } if (e.getKeyCode() == 40) { GameUtils.DOWN = false; } if (e.getKeyCode() == 37) { GameUtils.LEFT = false; } if (e.getKeyCode() == 39) { GameUtils.RIGHT = false; } } }); //...... } @Override public void paint(Graphics g) { //懶載入模式初始化物件 offScreenImage = createImage(width, height); Graphics gImage = offScreenImage.getGraphics(); //獲取圖片對應的畫筆物件 switch (state) { case 0: //...... break; case 1: bg.paintSelf(gImage); myFish.paintSelf(gImage); logic(); //不斷新增敵方魚類 for (Enamy enamy : GameUtils.EnamyList) { enamy.paintSelf(gImage); } break; case 2: break; case 3: break; case 4: break; default: break; } //將繪製好的圖片一次性繪製到主視窗中 g.drawImage(offScreenImage, 0, 0, null); } //批次新增魚類 void logic() { //...... } }
在遊戲中所有物體被視為矩形,兩個物體是否碰撞,即檢測兩個物體的所在矩形是否有重疊部分
具體檢測,就是讓我方魚與敵方魚的矩形進行一一檢測,在視窗類的 logic() 方法中實現
//批次新增魚類 void logic() { //每重繪10次生成一條敵方魚類 if (time % 10 == 0) { enamy = new Enamy_1_L(); GameUtils.EnamyList.add(enamy); } //移動方向 for (Enamy enamy : GameUtils.EnamyList) { enamy.x = enamy.x + enamy.dir * enamy.speed; //我方魚與敵方魚的碰撞檢測 if (myFish.getRec().intersects(enamy.getRec())) { enamy.x = -200; enamy.y = -200; } } }
在工具類中定義分數
//分數 static int count = 0;
在視窗類中實現我方魚吃掉敵方魚增加分數,同時在頁面上列印分數
public class GameWin extends JFrame { //...... @Override public void paint(Graphics g) { //懶載入模式初始化物件 offScreenImage = createImage(width, height); Graphics gImage = offScreenImage.getGraphics(); //獲取圖片對應的畫筆物件 switch (state) { case 0: //...... case 1: bg.paintSelf(gImage); //*******列印所得積分******** gImage.setColor(Color.ORANGE); gImage.setFont(new Font("仿宋", Font.BOLD, 50)); gImage.drawString("積分:" + GameUtils.count, 200, 120); myFish.paintSelf(gImage); logic(); //不斷新增敵方魚類 for (Enamy enamy : GameUtils.EnamyList) { enamy.paintSelf(gImage); } break; case 2: break; case 3: break; case 4: break; default: break; } //...... //批次新增魚類 void logic() { //...... //移動方向 for (Enamy enamy : GameUtils.EnamyList) { enamy.x = enamy.x + enamy.dir * enamy.speed; //我方魚與敵方魚的碰撞檢測 if (myFish.getRec().intersects(enamy.getRec())) { enamy.x = -200; enamy.y = -200; //********得分******** GameUtils.count += enamy.count; } } } }
在我方魚類中實現吃掉敵方魚後,我方魚體積增加
public class MyFish { //...... //繪製自身的方法 public void paintSelf(Graphics g) { logic(); g.drawImage(img, x, y, width + GameUtils.count, height + GameUtils.count, null); } //獲取自身矩形的方法 public Rectangle getRec() { return new Rectangle(x, y, width + GameUtils.count, height + GameUtils.count); } //...... }
根據積分來實現關卡的設定,如果達到目標積分則過關,並增加我方魚的等級
在工具類中定義關卡等級
//關卡等級 static int level = 0;
在視窗類的 logic() 方法中設定關卡
public class GameWin extends JFrame { //...... @Override public void paint(Graphics g) { //懶載入模式初始化物件 offScreenImage = createImage(width, height); Graphics gImage = offScreenImage.getGraphics(); //獲取圖片對應的畫筆物件 switch (state) { case 0: //...... break; case 1: //...... break; case 2: break; case 3: //玩家勝利 bg.paintSelf(gImage); myFish.paintSelf(gImage); gImage.setColor(Color.ORANGE); gImage.setFont(new Font("仿宋", Font.BOLD, 80)); gImage.drawString("積分: " + GameUtils.count, 200, 120); gImage.drawString("勝利", 400, 500); break; case 4: break; default: break; } //將繪製好的圖片一次性繪製到主視窗中 g.drawImage(offScreenImage, 0, 0, null); } //批次新增魚類 void logic() { //關卡難度 if (GameUtils.count < 5) { GameUtils.level = 0; myFish.level = 1; } else if (GameUtils.count <= 15) { GameUtils.level = 1; } else if (GameUtils.count <= 50) { GameUtils.level = 2; myFish.level = 2; } else if (GameUtils.count <= 150) { GameUtils.level = 3; myFish.level = 3; } else if (GameUtils.count <= 300) { GameUtils.level = 4; myFish.level = 3; } else { //分數大於300,玩家勝利 state = 3; } //...... } }
實現遊戲介面積分、難度、關卡的視覺化編寫
在工具類中定義繪製文字的方法
//繪製文字的方法 public static void drawWord(Graphics g, String str, Color color, int size, int x, int y) { g.setColor(color); g.setFont(new Font("仿宋", Font.BOLD, size)); g.drawString(str, x, y); }
在背景類中讓積分、難度、我方魚等級視覺化
public class Bg { void paintSelf(Graphics g, int fishLevel) { g.drawImage(GameUtils.bgimg, 0, 0, null); switch (GameWin.state) { case 0: GameUtils.drawWord(g, "請點選開始遊戲", Color.RED, 80, 500, 500); break; case 1: GameUtils.drawWord(g, "積分:" + GameUtils.count, Color.ORANGE, 50, 200, 120); GameUtils.drawWord(g, "難度:" + GameUtils.level, Color.ORANGE, 50, 600, 120); GameUtils.drawWord(g, "等級:" + fishLevel, Color.ORANGE, 50, 1000, 120); break; case 2: break; case 3: GameUtils.drawWord(g, "積分:" + GameUtils.count, Color.ORANGE, 50, 200, 120); GameUtils.drawWord(g, "難度:" + GameUtils.level, Color.ORANGE, 50, 600, 120); GameUtils.drawWord(g, "等級:" + fishLevel, Color.ORANGE, 50, 1000, 120); GameUtils.drawWord(g, "勝利", Color.RED, 80, 700, 500); break; default: break; } } }
對視窗類的 paint 方法進行優化
@Override public void paint(Graphics g) { //懶載入模式初始化物件 offScreenImage = createImage(width, height); Graphics gImage = offScreenImage.getGraphics(); //獲取圖片對應的畫筆物件 bg.paintSelf(gImage, myFish.level); //*********************** //遊戲狀態:0未開始,1遊戲中,2遊戲失敗,3遊戲勝利,4遊戲暫停,5重新開始 switch (state) { case 0: break; case 1: myFish.paintSelf(gImage); logic(); //不斷新增敵方魚類 for (Enamy enamy : GameUtils.EnamyList) { enamy.paintSelf(gImage); } break; case 2: break; case 3: //玩家勝利 myFish.paintSelf(gImage); break; case 4: break; default: break; } //將繪製好的圖片一次性繪製到主視窗中 g.drawImage(offScreenImage, 0, 0, null); }
首先實現右側敵方小魚的生成,在工具類中新增右側敵方小魚的圖
//敵方魚類 public static Image enamy_l_img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\fish1_r.gif"); public static Image enamy_r_img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\fish1_l.gif");
在敵方魚類中建立敵方小魚右類繼承敵方小魚左類
//右敵方魚類 class Enamy_1_R extends Enamy_1_L { Enamy_1_R() { this.x = 1400; dir = -1; this.img = GameUtils.enamy_r_img; } }
在視窗類中定義亂數,使左右敵方小魚隨機出現
public class GameWin extends JFrame { //...... //定義一個亂數,以此讓左右魚的數量隨機 double random; //...... random = Math.random(); //每重繪10次生成一條敵方魚類 if (time % 10 == 0) { if (random > 0.5) { enamy = new Enamy_1_L(); } else { enamy = new Enamy_1_R(); } GameUtils.EnamyList.add(enamy); } //...... }
接下來是其他敵方魚類的生成,其原理與敵方小魚的生成原理一致
在視窗類新增敵方魚圖
//敵方魚類 public static Image enamy_l_img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\fish1_r.gif"); public static Image enamy_r_img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\fish1_l.gif"); public static Image enamy_l_2img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\fish2_r.png"); public static Image enamy_r_2img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\fish2_l.png"); public static Image enamy_l_3img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\fish3_r.png"); public static Image enamy_r_3img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\fish3_l.png");
建立剩下的敵方魚類並寫入引數
class Enamy_2_L extends Enamy { Enamy_2_L() { this.x = -100; this.y = (int) (Math.random() * 700 + 100); this.width = 100; this.height = 100; this.speed = 5; this.count = 2; this.type = 2; this.img = GameUtils.enamy_l_2img; } } class Enamy_2_R extends Enamy_2_L { Enamy_2_R() { this.x = 1400; dir = -1; this.img = GameUtils.enamy_r_2img; } } class Enamy_3_L extends Enamy { Enamy_3_L() { this.x = -300; this.y = (int) (Math.random() * 700 + 100); this.width = 300; this.height = 150; this.speed = 15; this.count = 5; this.type = 3; this.img = GameUtils.enamy_l_3img; } //由於第3種魚的體積過大,我們需要將其修改一下 public Rectangle getRec() { return new Rectangle(x + 40, y + 30, width - 80, height - 60); } } class Enamy_3_R extends Enamy_3_L { Enamy_3_R() { this.x = 1400; dir = -1; this.img = GameUtils.enamy_r_3img; } }
在視窗類種新增敵方魚的生成,新增我方魚和敵方魚的等級比較來判斷遊戲是否失敗,同時遊戲失敗介面只剩下敵方魚類
public class GameWin extends JFrame { //...... @Override public void paint(Graphics g) { //懶載入模式初始化物件 offScreenImage = createImage(width, height); Graphics gImage = offScreenImage.getGraphics(); //獲取圖片對應的畫筆物件 bg.paintSelf(gImage, myFish.level); //遊戲狀態:0未開始,1遊戲中,2遊戲失敗,3遊戲勝利,4遊戲暫停,5重新開始 switch (state) { case 0: break; case 1: myFish.paintSelf(gImage); logic(); //不斷新增敵方魚類 for (Enamy enamy : GameUtils.EnamyList) { enamy.paintSelf(gImage); } break; case 2: //*********遊戲失敗介面********* logic(); //不斷新增敵方魚類 for (Enamy enamy : GameUtils.EnamyList) { enamy.paintSelf(gImage); } break; case 3: //玩家勝利 myFish.paintSelf(gImage); break; case 4: break; default: break; } //將繪製好的圖片一次性繪製到主視窗中 g.drawImage(offScreenImage, 0, 0, null); } //批次新增魚類 void logic() { //...... random = Math.random(); //********根據遊戲等級生成魚類******** switch (GameUtils.level) { case 4: case 3: case 2: if (time % 30 == 0) { if (random > 0.5) { enamy = new Enamy_3_L(); } else { enamy = new Enamy_3_R(); } GameUtils.EnamyList.add(enamy); } case 1: if (time % 20 == 0) { if (random > 0.5) { enamy = new Enamy_2_L(); } else { enamy = new Enamy_2_R(); } GameUtils.EnamyList.add(enamy); } case 0: //每重繪10次生成一條敵方魚類 if (time % 10 == 0) { if (random > 0.5) { enamy = new Enamy_1_L(); } else { enamy = new Enamy_1_R(); } GameUtils.EnamyList.add(enamy); } break; default: break; } //移動方向 for (Enamy enamy : GameUtils.EnamyList) { enamy.x = enamy.x + enamy.dir * enamy.speed; //我方魚與敵方魚的碰撞檢測 if (myFish.getRec().intersects(enamy.getRec())) { //********如果我方魚的等級大於等於敵方魚******* if (myFish.level >= enamy.type) { enamy.x = -200; enamy.y = -200; //得分 GameUtils.count += enamy.count; } else { state = 2; } } } } }
背景類優化:
public class Bg { void paintSelf(Graphics g, int fishLevel) { g.drawImage(GameUtils.bgimg, 0, 0, null); switch (GameWin.state) { case 0 -> GameUtils.drawWord(g, "請點選開始遊戲", Color.RED, 80, 500, 500); case 1 -> { GameUtils.drawWord(g, "積分:" + GameUtils.count, Color.ORANGE, 50, 200, 120); GameUtils.drawWord(g, "難度:" + GameUtils.level, Color.ORANGE, 50, 600, 120); GameUtils.drawWord(g, "等級:" + fishLevel, Color.ORANGE, 50, 1000, 120); } case 2 -> { GameUtils.drawWord(g, "積分:" + GameUtils.count, Color.ORANGE, 50, 200, 120); GameUtils.drawWord(g, "難度:" + GameUtils.level, Color.ORANGE, 50, 600, 120); GameUtils.drawWord(g, "等級:" + fishLevel, Color.ORANGE, 50, 1000, 120); GameUtils.drawWord(g, "失敗", Color.RED, 80, 600, 500); } case 3 -> { GameUtils.drawWord(g, "積分:" + GameUtils.count, Color.ORANGE, 50, 200, 120); GameUtils.drawWord(g, "難度:" + GameUtils.level, Color.ORANGE, 50, 600, 120); GameUtils.drawWord(g, "等級:" + fishLevel, Color.ORANGE, 50, 1000, 120); GameUtils.drawWord(g, "勝利", Color.RED, 80, 700, 500); } default -> { } } } }
在工具類中新增敵方 boss 魚
public static Image boss_img = Toolkit.getDefaultToolkit().createImage("D:\IDEA\idea_Demo\FishGame\images\enemyFish\boss.gif");
建立敵方 boss 魚類繼承父類別
class Enamy_Boss extends Enamy { Enamy_Boss() { this.x = -1000; this.y = (int) (Math.random()*700 + 100); this.width = 340; this.height = 340; this.speed = 100; this.count = 0; this.type = 10; this.img = GameUtils.boss_img; } }
在視窗類中獲取敵方 boss 魚類,在遊戲等級為 4 的程式碼塊中,新增 boss 生成的條件,同時對 boss 和我方魚類及其他魚類碰撞的情況做出處理
public class GameWin extends JFrame { //...... //敵方boss類 Enamy boss; //是否生成boss boolean isboss = false; //建立一個啟動視窗,設定視窗資訊 public void launch() throws InterruptedException { //...... } @Override public void paint(Graphics g) { //懶載入模式初始化物件 offScreenImage = createImage(width, height); Graphics gImage = offScreenImage.getGraphics(); //獲取圖片對應的畫筆物件 bg.paintSelf(gImage, myFish.level); //遊戲狀態:0未開始,1遊戲中,2遊戲失敗,3遊戲勝利,4遊戲暫停,5重新開始 switch (state) { case 0: break; case 1: myFish.paintSelf(gImage); logic(); //不斷新增敵方魚類 for (Enamy enamy : GameUtils.EnamyList) { enamy.paintSelf(gImage); } //********boss魚的生成******** if (isboss) { boss.x += boss.dir * boss.speed; boss.paintSelf(gImage); if (boss.x < 0) { gImage.setColor(Color.RED); gImage.fillRect(boss.x, boss.y, 2400, boss.height / 30); } } break; case 2: logic(); //不斷新增敵方魚類 for (Enamy enamy : GameUtils.EnamyList) { enamy.paintSelf(gImage); } //********新增敵方boss******** if (isboss) { boss.paintSelf(gImage); } break; case 3: //玩家勝利 myFish.paintSelf(gImage); break; case 4: break; default: break; } //將繪製好的圖片一次性繪製到主視窗中 g.drawImage(offScreenImage, 0, 0, null); } //批次新增魚類 void logic() { //關卡難度 if (GameUtils.count < 5) { GameUtils.level = 0; myFish.level = 1; } else if (GameUtils.count <= 15) { GameUtils.level = 1; } else if (GameUtils.count <= 50) { GameUtils.level = 2; myFish.level = 2; } else if (GameUtils.count <= 150) { GameUtils.level = 3; myFish.level = 3; } else if (GameUtils.count <= 300) { GameUtils.level = 4; myFish.level = 3; } else { //分數大於300,玩家勝利 state = 3; } random = Math.random(); switch (GameUtils.level) { case 4: //********判斷是否生成boss******** if (time % 60 == 0) { if (random > 0) { boss = new Enamy_Boss(); isboss = true; } } case 3: case 2: //...... case 1: //...... case 0: //...... default: break; } //移動方向 for (Enamy enamy : GameUtils.EnamyList) { enamy.x = enamy.x + enamy.dir * enamy.speed; //********boss魚的碰撞處理******** if (isboss) { if (boss.getRec().intersects(enamy.getRec())) { enamy.x = -200; enamy.y = -200; } if (boss.getRec().intersects(myFish.getRec())) { state = 2; } } //...... } } }
首先實現暫停功能,如果遊戲狀態為 4,則遊戲暫停,我們使用空格鍵來實現遊戲暫停功能
在 launch 方法中新增鍵盤的監聽事件
public class GameWin extends JFrame { //...... //建立一個啟動視窗,設定視窗資訊 public void launch() throws InterruptedException { //...... //鍵盤移動 this.addKeyListener(new KeyAdapter() { @Override//按壓 public void keyPressed(KeyEvent e) { //上下左右四個鍵的ASCII值為 上 ↑:38下 ↓: 40左 ←: 37右 →: 39 if (e.getKeyCode() == 38) { GameUtils.UP = true; } if (e.getKeyCode() == 40) { GameUtils.DOWN = true; } if (e.getKeyCode() == 37) { GameUtils.LEFT = true; } if (e.getKeyCode() == 39) { GameUtils.RIGHT = true; } //********空格鍵******** if (e.getKeyCode() == 32) { //如果遊戲狀態為執行中,則暫停,反之 switch (state) { case 1: state = 4; GameUtils.drawWord(getGraphics(), "遊戲暫停!!!", Color.RED, 50, 600, 400); break; case 4: state = 1; break; } } } @Override//擡起 public void keyReleased(KeyEvent e) { if (e.getKeyCode() == 38) { GameUtils.UP = false; } if (e.getKeyCode() == 40) { GameUtils.DOWN = false; } if (e.getKeyCode() == 37) { GameUtils.LEFT = false; } if (e.getKeyCode() == 39) { GameUtils.RIGHT = false; } } }); //背景圖片重複使用,需要重複呼叫repaint方法 while (true) { repaint(); time++; Thread.sleep(40); } } @Override public void paint(Graphics g) { //...... case 4: //******** return; default: break; } //將繪製好的圖片一次性繪製到主視窗中 g.drawImage(offScreenImage, 0, 0, null); } //批次新增魚類 ...... }
接下來是重新開始功能,在視窗類中建立一個新的方法,將遊戲狀態恢復到初始,然後定義在遊戲狀態為結束或勝利的情況下,點選滑鼠左鍵進入重新開始介面
//重新開始 void reGame() { GameUtils.EnamyList.clear(); time =0; myFish.level = 0; GameUtils.count = 0; myFish.x = 700; myFish.y = 500; myFish.width = 50; myFish.height = 50; boss = null; isboss = false; }
//建立一個啟動視窗,設定視窗資訊 public void launch() throws InterruptedException { //...... //新增滑鼠監聽事件 this.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getButton() == 1 && state == 0) { state = 1; repaint(); } //重新開始 if (e.getButton() == 1 && (state == 2 || state == 3)) { reGame(); state = 1; } } }); //鍵盤移動 //...... }
以上就是Java實現經典遊戲之大魚吃小魚的詳細內容,更多關於Java大魚吃小魚的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45