Java GUI | 用Java開發了一個貪喫蛇小遊戲

一個Java開發的貪喫蛇小遊戲

一、遊戲操作說明

上下左右控制貪喫蛇走位,空格鍵暫停或者開始遊戲 藍色食物得10分,黃色食物得20分,紅色食物得30分。小蛇的移動速度會隨着長度的增加而變快,最快是初始速度的兩倍,這裏可以在代碼中自定義設置。目前還有一個bug尚未解決,就是小蛇可以回頭走,理論是應該往一個方向可以掉頭但是不可以直接往相反的方向走,這樣默認就是咬到自己遊戲結束,以後會修復這個問題

二、程序代碼

1、StartGame.java(主函數類)

用於設置窗口的一些參數

package com.java.snake;

import javax.swing.*;

public class StartGame {
    public static void main(String[] args) {
        // 1.繪製一個靜態窗口並設置窗口標題
        JFrame jFrame = new JFrame("貪喫蛇小遊戲");
        jFrame.setBounds(10, 10, 900, 720); // 設置起始座標和窗口大小
        jFrame.setResizable(false); // 設置不可以調整窗口大小
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 設置可以關閉窗口
        // 2.繪製面板
        jFrame.add(new GamePanel());
        jFrame.setVisible(true); // 讓窗口可以展現出來
    }
}

2、GamePanel.java

這個類是程序的主要代碼,包括畫圖和設置幀數還有鍵盤的監聽

package com.java.snake;

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;

public class GamePanel extends JPanel implements KeyListener, ActionListener {
    int length; // 蛇的長度
    String fx; // 方向 R:右 L:左 U:上 D:下
    int[] snakeX = new int[600]; // 蛇的X軸座標
    int[] snakeY = new int[500]; // 蛇的Y軸座標
    boolean isStart; // 遊戲是否開始的表示,默認未開始
    boolean isFail; // 是否失敗標識
    int score; // 分數
    int num; // 食物顏色編號

    int foodX;
    int foodY;
    Random random = new Random();
    int seconds = 100;
    Timer timer = new Timer(seconds, this); // 設置一個定時器

    // 構造器
    public GamePanel() {
        init();
        // 獲取鍵盤監聽時間
        this.setFocusable(true);
        this.addKeyListener(this);
        timer.start(); // 讓時間動起來
    }

    public void init() {
        length = 3; // 初始化蛇長度爲3
        fx = "R"; // 初始化蛇頭方向是往右
        // 頭部座標
        snakeX[0] = 100;
        snakeY[0] = 100;
        snakeX[1] = 75;
        snakeY[1] = 100;
        snakeX[2] = 50;
        snakeY[2] = 100;
        isStart = false;
        isFail = false;
        // 隨機初始化食物
        foodX = 25 + 25 * random.nextInt(34);
        foodY = 75 + 25 * random.nextInt(24);
        score = 0; // 默認分數爲0
        seconds = 100;
    }

    // 面板:畫界面 畫蛇
    // Graphics:畫筆
    @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 ("R".equals(fx))
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        if ("L".equals(fx))
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        if ("U".equals(fx))
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        if ("D".equals(fx))
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        // 蛇的長度用length進行控制
        for (int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        if (num == 0)
            Data.foodBlue.paintIcon(this, g, foodX, foodY);
        if (num == 1)
            Data.foodYellow.paintIcon(this, g, foodX, foodY);
        if (num == 2)
            Data.foodRed.paintIcon(this, g, foodX, foodY);
        // 遊戲未開始時話一個字符串
        if (!isStart) {
            g.setColor(Color.white); // 設置畫筆顏色
            g.setFont(new Font("微軟雅黑", Font.BOLD, 40)); // 設置字體
            g.drawString("按下空格開始遊戲", 300, 300);
        }
        // 遊戲未開始時話一個字符串
        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("遊戲結束,按下空格重新開始遊戲", 150, 300);
        }
        g.setColor(Color.white);
        g.setFont(new Font("微軟雅黑", Font.BOLD, 18));
        g.drawString("長度:" + length, 750, 35);
        g.drawString("分數:" + score, 750, 55);
    }

    // 定時器,監聽時間,幀:執行定時操作
    @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 ("U".equals(fx)) {
                // 頭部移動
                snakeY[0] -= 25;
                // 邊界判斷
                if (snakeY[0] < 75) {
                    snakeY[0] = 650;
                }
            } else if ("D".equals(fx)) {
                // 頭部移動
                snakeY[0] += 25;
                // 邊界判斷
                if (snakeY[0] > 650) {
                    snakeY[0] = 75;
                }
            } else if ("R".equals(fx)) {
                // 頭部移動
                snakeX[0] += 25;
                // 邊界判斷
                if (snakeX[0] > 850) {
                    snakeX[0] = 25;
                }
            } else if ("L".equals(fx)) {
                // 頭部移動
                snakeX[0] -= 25;
                // 邊界判斷
                if (snakeX[0] < 25) {
                    snakeX[0] = 850;
                }
            }
            if (snakeX[0] == foodX && snakeY[0] == foodY) {
                // 長度加一
                length++;
                // 增加分數
                if (num == 0)
                    score += 10;
                if (num == 1)
                    score += 20;
                if (num == 2)
                    score += 30;
                // 幀數加時
                if (seconds > 50) {
                    timer.setDelay(seconds -= 1);
                }
                // 重新隨機生成一個顏色食物
                foodX = 25 + 25 * random.nextInt(34);
                foodY = 75 + 25 * random.nextInt(24);
                num = random.nextInt(3);
            }
            // 失敗判定
            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) {
            if (isFail) {
                // 重新開始遊戲
                init();
                isStart = true;
            } else {
                // 遊戲開始或者暫停
                isStart = !isStart;
            }
            // 刷新界面
            repaint();
        }
        if (keyCode == KeyEvent.VK_UP) {
            fx = "U";
        } else if (keyCode == KeyEvent.VK_DOWN) {
            fx = "D";
        } else if (keyCode == KeyEvent.VK_RIGHT) {
            fx = "R";
        } else if (keyCode == KeyEvent.VK_LEFT) {
            fx = "L";
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // 鍵盤釋放
    }

    @Override
    public void keyTyped(KeyEvent e) {
        // 鍵盤按下並釋放 敲擊
    }
}

3、Data.java

這個類寫的是一些數據。導入一些外部的圖片素材,在GamePanel.java中畫到面板上

package com.java.snake;

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

// 存放外部數據
public class Data {
    // 遊戲頭部的圖片
    public static URL headerUrl = Data.class.getResource("/static/header.png");
    public static ImageIcon header = new ImageIcon(headerUrl);
    // 導入一些圖片素材
    public static URL upUrl = Data.class.getResource("/static/up.png");
    public static URL downUrl = Data.class.getResource("/static/down.png");
    public static URL leftUrl = Data.class.getResource("/static/left.png");
    public static URL rightUrl = Data.class.getResource("/static/right.png");
    public static URL bodyUrl = Data.class.getResource("/static/body.png");
    public static ImageIcon up = new ImageIcon(upUrl); // 上
    public static ImageIcon down = new ImageIcon(downUrl); // 下
    public static ImageIcon left = new ImageIcon(leftUrl); // 左
    public static ImageIcon right = new ImageIcon(rightUrl); // 右
    public static ImageIcon body = new ImageIcon(bodyUrl); // 身體

    // 食物
    public static URL foodBlueUrl = Data.class.getResource("/static/food_blue.png");
    public static URL foodYellowUrl = Data.class.getResource("/static/food_yellow.png");
    public static URL foodRedUrl = Data.class.getResource("/static/food_red.png");
    public static ImageIcon foodBlue = new ImageIcon(foodBlueUrl); // 藍色食物,加一個長度
    public static ImageIcon foodYellow = new ImageIcon(foodYellowUrl); // 黃色食物,加兩個長度
    public static ImageIcon foodRed = new ImageIcon(foodRedUrl); // 紅色食物,加三個長度
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章