java gui詳解貪吃蛇小遊戲實現流程
根據狂神的視頻做的,然後自己優化瞭一些bug,比如新生成食物的時候不會生成在蛇的身體上,再新增長身體的時候不會在左上角出現一個綠色的方塊以及增加瞭難度控制功能,以及可以使用WASD進行控制,而不僅僅限於上下左右方向鍵
最後的遊戲界面是這樣的:
可以在上方的菜單欄裡選擇不同的難度進行遊戲.難度對應的是不同的蛇移動的速度,點擊退出遊戲和點擊右上角的X是一樣的功能,都是退出遊戲.然後點擊重新開始就會回到最初的時候重新開始遊戲.
按下空格開始遊戲,隨時可以再次按下空格進行暫停遊戲.同時每吃到一個食物就會在右上角加10分.
遊戲代碼一共分成瞭三個類
一個是GameStart類,用來創建JFrame繪制遊戲主體.
一個是GamePanel類,用來添加在JFrame中,裡面加入瞭菜單欄以及一些鍵盤監聽器,用來根據讀入的信息操縱蛇移動.
另一個是Data類,用來讀取statics文件夾中的圖片素材,代碼更簡潔.
GameStart類代碼如下:(具體代碼後面都有註釋)
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @author Laurie */ public class GameStart { public static void main(String[] args) { JFrame jframe = new JFrame("貪吃蛇"); jframe.setBounds(10, 10, 900, 720);//繪制遊戲主界面的范圍 jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jframe.setResizable(false);//不可擴大縮小窗口 GamePanel gamePanel = new GamePanel(); jframe.add(gamePanel); jframe.setVisible(true);//顯形 gamePanel.setLayout(new BorderLayout()); } }
GamePanel類代碼是:
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Random; /** * @author Laurie */ public class GamePanel extends JPanel implements ActionListener, KeyListener { int length;//蛇的長度 int[] snakeX = new int[500];//隨便定義長度,反之不出意外是不會超過的 int[] snakeY = new int[500]; String direction;//蛇的方向,來根據這個改變蛇頭的圖片 Timer timer = new Timer(60, this);//計時器,來觸發蛇移動的事件 int score;//分數 Boolean isFail = false;//是否失敗判斷 Boolean isStart = false;//是否啟動判斷 int foodX;//食物坐標 int foodY; Random random = new Random();//用來產生隨機數的Random類的實例化 public void init(){ length = 3;//一開始蛇的三節 snakeX[0] = 100;//蛇頭為下標0 snakeY[0] = 100; snakeX[1] = 75; snakeY[1] = 100; snakeX[2] = 50; snakeY[2] = 100; direction = "R";//初始化方向朝右邊 score = 0; foodX = getFoodX();//通過方法獲取食物的坐標 foodY = getFoodY(); } public GamePanel(){ //構造函數 init();//進行初始化 this.setFocusable(true);//設置可以被賦予焦點 this.setForeground(Color.pink);//設置為粉色 this.addKeyListener(this);//添加鍵盤的監聽 timer.start();//開始計時器 JMenuBar menuBar = new JMenuBar();//選項欄 JButton jb1 = new JButton("退出遊戲"); JButton jb3 = new JButton("新手難度"); JButton jb4 = new JButton("高手難度"); JButton jb5 = new JButton("地獄難度"); menuBar.add(jb1); menuBar.add(jb3); menuBar.add(jb4); menuBar.add(jb5); jb1.addActionListener(e -> {//添加jb1的監聽 System.exit(0);//退出 }); jb3.addActionListener(e -> { this.requestFocus();//不獲取焦點後面操作鍵盤都會在菜單欄裡,就無法操作蛇瞭 timer.stop();//把原來的timer停止 timer = new Timer(80, this);//使蛇的速度變慢 timer.start();//重新開始timer }); jb4.addActionListener(e -> { this.requestFocus(); timer.stop(); timer = new Timer(40, this); timer.start(); }); jb5.addActionListener(e -> { this.requestFocus(); timer.stop(); timer = new Timer(20, this); timer.start(); }); this.add(menuBar); JButton jb2 = new JButton("重新開始"); jb2.addActionListener(e -> { init();//重新開始所以重新初始化一下 repaint();//重畫 this.requestFocus(); }); this.add(jb2); } public int getFoodX(){ //如果沒有判斷的話會出現bug,也就是食物可能出現在蛇的身體裡,所以要進行判斷優化 boolean flag = true; int x = 25 + 25 * random.nextInt(34);//因為一格為25,所以要乘一個25 while(flag){ for(int i = 0; i < length; i++){ if(snakeX[i] == x) { x = 25 + 25 * random.nextInt(34);//如果和身體重合就重新隨機一個數 }else{ flag = false; } } } return x; } public int getFoodY(){ boolean flag = true; int y = 75 + 25 * random.nextInt(24);//24是計算出來的,總panel的大小除以25 while(flag){ for(int i = 0; i < length; i++){ if(snakeY[i] == y) { y = 75 + 25 * random.nextInt(34); }else{ flag = false; } } } return y; } @Override protected void paintComponent(Graphics g) { super.paintComponents(g);//這個不加可能會出問題 this.setBackground(Color.white); g.fillRect(0,0,90,30); g.setColor(Color.black); g.drawString("貪吃蛇大挑戰",10,20); g.setColor(Color.LIGHT_GRAY);//分數提示框 g.fillRect( 25, 36, 850, 40); g.setColor(Color.pink);//遊戲主界面 g.fillRect(25,75, 850, 600); if ("R".equals(direction)) {//判斷是什麼蛇頭朝向,選擇不同的蛇頭圖片 Data.right.paintIcon(this, g, snakeX[0], snakeY[0]); } else if ("L".equals(direction)) { Data.left.paintIcon(this, g, snakeX[0], snakeY[0]); } else if ("U".equals(direction)) { Data.up.paintIcon(this, g, snakeX[0], snakeY[0]); } else if ("D".equals(direction)) { Data.down.paintIcon(this, g, snakeX[0], snakeY[0]); } for (int i = 1; i < length; i++) {//通過for循環繪制蛇的身體 Data.body.paintIcon(this, g, snakeX[i], snakeY[i]); } g.setColor(Color.WHITE); g.setFont(new Font("微軟雅黑", Font.BOLD, 18)); g.drawString("長度:"+length,650,54); g.drawString("分數:"+score,750,54);//分數長度等的繪制 Data.food.paintIcon(this, g, foodX, foodY);//繪制食物 if (!isStart) {//如果還沒開始就提示按下空格開始 g.setColor(Color.WHITE); g.setFont(new Font("微軟雅黑", Font.BOLD, 40)); g.drawString("按下空格來開始遊戲", 300, 300); } if (isFail) {//如果失敗瞭就提示按下空格重新開始 g.setColor(Color.red); g.setFont(new Font("微軟雅黑", Font.BOLD, 40)); g.drawString("蛇死瞭哦,按下空格重新開始吧", 200, 300); } } @Override public void actionPerformed(ActionEvent e) { if (isStart && !isFail) {//如果已經開始並且沒有失敗 for (int i = length - 1; i > 0; i--) { snakeX[i] = snakeX[i - 1]; //就把每節身體的位置都變成上一個身體的位置來模擬移動 snakeY[i] = snakeY[i - 1]; } if ("R".equals(direction)) { //動完瞭身體,這裡動蛇頭,根據不同的方向來動到位置 snakeX[0] = snakeX[0] + 25; if (snakeX[0] > 850) { snakeX[0] = 25; } } else if ("L".equals(direction)) { snakeX[0] = snakeX[0] - 25; if (snakeX[0] < 25) { snakeX[0] = 850; } } else if ("U".equals(direction)) { snakeY[0] = snakeY[0] - 25; if (snakeY[0] < 75) { snakeY[0] = 650; } } else if ("D".equals(direction)) { snakeY[0] = snakeY[0] + 25; if (snakeY[0] > 650) { snakeY[0] = 75; } } if (snakeX[0] == foodX && snakeY[0] == foodY) {//判斷是否吃到食物 //如果兩者的xy坐標重合瞭就說明吃到瞭 length++;//吃到瞭長度加一 snakeX[length - 1] = foodX - 1;//這裡是避免出現一個bug,沒有這兩行就會在吃吃到以後左上角出現一個綠方塊 //這是因為新增加的身體沒有賦值坐標,所以就默認在00的位置 snakeY[length - 1] = foodY - 1; score = score + 10; foodX = getFoodX();//重新生成新的食物 foodY = getFoodY(); } for(int i = 1; i < length; i++){//進行判斷是否死亡,當蛇頭和身體重合就是死亡 if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) { isFail = true; break; } } repaint();//蛇移動瞭所以需要重新畫一遍 } timer.start();//計時器重新開始,蛇再進行下一步移動 } @Override public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode();//這個為接受的鍵盤的按鍵對應的代碼 if(keyCode == KeyEvent.VK_SPACE){//如果是空格的話激素hi進行判斷 if(!isFail){//如果沒有失敗就進行暫停與重新遊戲的功能實現 isStart = !isStart; }else{//如果已經死瞭就重新開始 isFail = false; init(); } repaint();//重新繪制 } if (keyCode == KeyEvent.VK_LEFT && !"R".equals(direction)) {//檢查獲取的是上下左右的哪個進行蛇頭轉向 direction = "L"; } else if (keyCode == KeyEvent.VK_RIGHT && !"L".equals(direction)) { direction = "R"; } else if (keyCode == KeyEvent.VK_UP && !"D".equals(direction)) { direction = "U"; } else if (keyCode == KeyEvent.VK_DOWN && !"U".equals(direction)) { direction = "D"; } if (keyCode == KeyEvent.VK_A && !"R".equals(direction)) {//檢查獲取的是wasd的哪個進行蛇頭轉向 //註意當是與蛇頭反方向的不可以進行轉動,畢竟也不能180度轉脖子把 direction = "L"; } else if (keyCode == KeyEvent.VK_D && !"L".equals(direction)) { direction = "R"; } else if (keyCode == KeyEvent.VK_W && !"D".equals(direction)) { direction = "U"; } else if (keyCode == KeyEvent.VK_S && !"U".equals(direction)) { direction = "D"; } } //這兩個沒有用,所以不用寫瞭 @Override public void keyTyped(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { } }
Data類代碼是:
import javax.swing.*; import java.awt.*; import java.net.URL; /** * @author Laurie */ public class Data { //讀取statics文件夾裡的圖片,加載成圖片 public static URL bodyURL = Data.class.getResource("/statics/body.png"); public static URL foodURL = Data.class.getResource("/statics/food.png"); public static URL downURL = Data.class.getResource("/statics/down.png"); public static URL upURL = Data.class.getResource("/statics/up.png"); public static URL rightURL = Data.class.getResource("/statics/right.png"); public static URL leftURL = Data.class.getResource("/statics/left.png"); public static ImageIcon body = new ImageIcon(bodyURL); public static ImageIcon food = new ImageIcon(foodURL); public static ImageIcon down = new ImageIcon(downURL); public static ImageIcon up = new ImageIcon(upURL); public static ImageIcon right = new ImageIcon(rightURL); public static ImageIcon left = new ImageIcon(leftURL); }
整個項目文件可以在github上自取,點擊藍字
github
上不去的也可以在gitee上自取,點擊藍字
gitee
💕
真的不下一個自己玩一玩嗎[手動滑稽]
到此這篇關於java gui詳解貪吃蛇小遊戲實現流程的文章就介紹到這瞭,更多相關java 貪吃蛇內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!