GUI 基於Swing製作貪吃蛇小遊戲

向陽的人生發表於2020-11-25

啟動遊戲類

public class StartGame {
    public static void main(String[] args) {
        JFrame jFrame = new JFrame("貪吃蛇遊戲");
        jFrame.setBounds(10,10,900,720);//框架大小

        jFrame.add(new GamePanel()); //建立遊戲皮膚
        jFrame.setResizable(false); //視窗大小不可變
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);  //視窗關閉監聽
        jFrame.setVisible(true);  //設定視窗可以見性,建議在測試類最後設定,以免焦點丟失,導致鍵盤監聽失效
    }
}

遊戲畫面素材類

import javax.swing.*;
import java.net.URL;

public class Data{
   public static URL headerURL= Data.class.getResource("statics/header2.png"); //獲得頭目欄資源地址
   public static ImageIcon header = new ImageIcon(headerURL); //建立頭目欄圖示

    public static URL bodyURL= Data.class.getResource("statics/body.png"); //獲得蛇身體資源地址
    public static ImageIcon body = new ImageIcon(bodyURL);  //建立蛇身體圖示

    public static URL upURL= Data.class.getResource("statics/up.png"); //獲得蛇頭向上資源地址
    public static ImageIcon up = new ImageIcon(upURL);  //建立蛇頭向上圖示

    public static URL downURL= Data.class.getResource("statics/down.png");  //獲得蛇頭向下資源地址
    public static ImageIcon down = new ImageIcon(downURL);  //建立蛇頭向下圖示

    public static URL leftURL= Data.class.getResource("statics/left.png");  //獲得蛇頭向左資源地址
    public static ImageIcon left = new ImageIcon(leftURL);   //建立蛇頭向左圖示

    public static URL rightURL= Data.class.getResource("statics/right.png");  //獲得蛇頭向右資源地址
    public static ImageIcon right = new ImageIcon(rightURL);  //建立蛇頭向右圖示

    public static URL foodURL= Data.class.getResource("statics/food.png");  //獲得食物資源地址
    public static ImageIcon food = new ImageIcon(foodURL);  //建立食物圖示

}

遊戲皮膚類

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;
/*總思路:
1.建立狀態變數
2.利用畫筆,“畫”到遊戲皮膚
3.編寫監聽事件或鍵盤監聽
 */
public class GamePanel extends JPanel implements KeyListener , ActionListener {
    int length;  //蛇的長度
    boolean isStart;  //遊戲是否開始
    int[] x = new int[100]; //頭部和身體座標
    int[] y = new int[100];
    int foodx;  //食物座標
    int foody;
    Random random = new Random(); //生成隨機數,為食物座標
    String des ;//蛇頭方向
    boolean isFail;  //遊戲是否失敗
    int score;  //分數
    Timer timer = new Timer(100,this);  //建立定時器

    public void init(){   //初始化方法
        x[0] = 100;  //蛇初始狀態
        y[0] = 100;
        x[1] = 75;
        y[1] = 100;
        x[2] = 50;
        y[2] = 100;
        length = 3;     //初始長度
        isStart = false;  //預設初始遊戲狀態關
        isFail = false;  //預設初始狀態為非失敗
        des = "R";  //預設蛇頭向右
        score = 0;  //初始分數為0
        foodx = 25 + random.nextInt(34) * 25; //食物初始位置
        foody = 75 + random.nextInt(24) * 25;
        timer.start();  //定時器記時開始
    }

    public GamePanel(){   //構造體
        init(); //呼叫初始化方法
        this.setFocusable(true);  //設定焦點
        this.addKeyListener(this); //新增鍵盤監聽
    }

    @Override
    protected void paintComponent(Graphics g) {  //畫筆
        super.paintComponent(g);    //清屏
        this.setBackground(Color.white);   //皮膚背景色
        Data.header.paintIcon(this,g,25,11); //畫頭目欄
        g.fillRect(25,75,850,600);  //建立矩形遊戲空間
        if (des.equals("R")){      //根據方向,畫蛇頭
            Data.right.paintIcon(this,g,x[0],y[0]);
        }else if (des.equals("L")){
            Data.left.paintIcon(this,g,x[0],y[0]);
        }else if (des.equals("U")){
            Data.up.paintIcon(this,g,x[0],y[0]);
        }else if (des.equals("D")){
            Data.down.paintIcon(this,g,x[0],y[0]);
        }

        for (int i = 1; i < length; i++) {  //畫身體
            Data.body.paintIcon(this,g,x[i],y[i]);
        }
        Data.food.paintIcon(this,g,foodx,foody);  //畫食物
        g.setColor(Color.white); //畫分數
        g.setFont(new Font("微軟雅黑",Font.BOLD,18)); //畫長度和分數
        g.drawString("長度"+length,750,35);
        g.drawString("分數"+score,750,50);

        if (!isStart){    //畫遊戲未開始畫面
            g.setColor(Color.white);
            g.setFont(new Font("微軟雅黑",Font.BOLD,30));
            g.drawString("按下空格開始遊戲",300,300);
        }
        if (isFail){   //畫失敗畫面
            g.setColor(Color.red);
            g.setFont(new Font("微軟雅黑",Font.BOLD,30));
            g.drawString("失敗,按下空格重新開始",300,300);
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {   //鍵盤監聽事件
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_SPACE ) {  //按下空格鍵監聽
            if (isFail){     //若遊戲失敗,遊戲重新開始
                isFail = false;   //ifFail值改變
                init();   //初始化
            }
            else {
                isStart = !isStart;  //否則,遊戲開始與暫停切換
            }
            repaint();  //重畫
        }

        if (keyCode == KeyEvent.VK_UP){  //按下方向鍵改變蛇頭方法
            des = "U";
        }else if (keyCode == KeyEvent.VK_DOWN){
            des = "D";
        }else if (keyCode == KeyEvent.VK_LEFT){
            des = "L";
        }else if (keyCode == KeyEvent.VK_RIGHT){
            des = "R";
        }
    }

    public void actionPerformed(ActionEvent e) {   //事件監聽事件
        if(isStart && !isFail) {  //如果遊戲為開始狀態且未失敗事件,讓小蛇動起來
            for (int i = length - 1; i > 0; i--) { //身體改變
                x[i] = x[i - 1];
                y[i] = y[i - 1];
            }
            if (des.equals("R")) { //根據蛇頭方向,改變蛇頭位置
                x[0] = x[0] + 25;
                if (x[0] > 850) {
                    x[0] = 0;
                }
            }else if (des.equals("L")){
                x[0] = x[0] - 25;
                if (x[0]<25){
                    x[0] = 850;
                }
            }else if (des.equals("U")){
                y[0] = y[0] - 25;
                if (y[0] < 75){
                    y[0] = 650;
                }
            }else if (des.equals("D")){
                y[0] = y[0] + 25;
                if (y[0] > 650){
                    y[0] = 75;
                }
            }

            if (foodx == x[0] && foody == y[0] ){  //吃到食物事件
                length++;
                score = score + 10;
                foodx = 25 + 25 * random.nextInt(34);
                foody = 75 + 25 * random.nextInt(24);
            }
            repaint();  //重畫
        }
        for (int i = 1; i < length; i++) {  //判斷遊戲失敗事件
            if (x[0] == x[i] && y[0] == y[i]){
                isFail = true;
            }
        }
        timer.start(); //定時器開啟
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

}

效果

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

相關文章