用Java寫一款小遊戲

2020-08-08 14:18:56

關於本次程式用到的的技能有:陣列、監聽器、適配器、定時器、本次用到的Java的swing不需要記住這已經被淘汰

效果展示
在这里插入图片描述

視窗

import javax.swing.*;
import java.awt.*;

public class DomeMain {
    public static void main(String[] args) {
        //建立一個表單
        JFrame jf = new JFrame();
        //給表單設定一個標題:
        jf.setTitle("貪吃蛇");
        //設定表單彈出座標,對應表單的寬和高
        int width = Toolkit.getDefaultToolkit().getScreenSize().width;
        int height = Toolkit.getDefaultToolkit().getScreenSize().height;
        jf.setBounds((width-800)/2,(height-800)/2,800,800);
        //設定表單大小不可調
        jf.setResizable(false);
        //關閉視窗的同時關閉程式
        jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //建立面板:
        GamePanel gp = new GamePanel();
        //將面板放入表單
        jf.add(gp);
        //預設情況下表單是隱藏效果,必須將表單進行顯現:細節-->這個顯現方法最好放在最後
        jf.setVisible(true);
    }
}

把圖片抽象化

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

//本類專門用來獲取遊戲中所涉及的圖片

public class Images {
    //物件導向的語言,物件導向的思維-->將圖片進行封裝,封裝成爲一個物件,這樣在程式中纔可以通過操作這個物件來操做圖片
    //將圖片封裝爲一個物件
    public  static URL bodyURL = Images.class.getResource("/images/body.jpg");
    //將圖片封裝爲程式的一個物件
    public static ImageIcon bodyImg = new ImageIcon(bodyURL);

    //將圖片封裝爲一個物件
    public  static URL foodURL = Images.class.getResource("/images/food.jpg");
    //將圖片封裝爲程式的一個物件
    public static ImageIcon foodImg = new ImageIcon(foodURL);//將圖片封裝爲一個物件

    public  static URL headURL = Images.class.getResource("/images/head.jpg");
    //將圖片封裝爲程式的一個物件
    public static ImageIcon headImg = new ImageIcon(headURL);//將圖片封裝爲一個物件

    public  static URL downURL = Images.class.getResource("/images/head - down.jpg");
    //將圖片封裝爲程式的一個物件
    public static ImageIcon downImg = new ImageIcon(downURL);

    //將圖片封裝爲一個物件
    public  static URL leftURL = Images.class.getResource("/images/head - left.jpg");
    //將圖片封裝爲程式的一個物件
    public static ImageIcon leftImg = new ImageIcon(leftURL);

    //將圖片封裝爲一個物件
    public  static URL rightURL = Images.class.getResource("/images/head - right.jpg");
    //將圖片封裝爲程式的一個物件
    public static ImageIcon rightImg = new ImageIcon(rightURL);

    //將圖片封裝爲一個物件
    public  static URL titleURL = Images.class.getResource("/images/title.jpg");
    //將圖片封裝爲程式的一個物件
    public static ImageIcon titleImg = new ImageIcon(titleURL);

}

程式的邏輯程式碼

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

//GamePanel繼承了JPanel以後,才具備面板的功能,才能 纔能成爲一個面板
public class GamePanel extends JPanel{//paintComponent這個方法比較特殊,這個方法就屬於圖形版的main方法,自動呼叫


    //定義兩個陣列
    //蛇的長度
    int lenght;
    //一個數組,專門儲存蛇的X軸座標
    int[] snakeX = new int[200];
    //一個數組,專門儲存蛇的Y軸座標
    int[] snakeY = new int[200];
    //遊戲只有兩個狀態:開始,結束
    boolean isStart = false;//預設是暫停
    //加入一個定時器
    Timer timer;
    //定義蛇的行走放向
    String direction;
    //定義食物的X,Y軸座標
    int foodX;
    int foodY;
    //定義一個積分
    int score;
    //加入一個變數,判斷小蛇的死亡狀態
    boolean isDie = false;//預設情況小蛇沒有死亡


    public void  init(){
        //初始化蛇的長度
        lenght = 3;
        //初始化蛇頭座標
        snakeX[0] = 175;
        snakeY[0] = 275;
        //初始化第一節身子座標
        snakeX[1] = 150;
        snakeY[1] = 275;
        //初始化第二節身子座標
        snakeX[2] = 125;
        snakeY[2] = 275;
        //初始化蛇的蛇頭方向
        direction = "R";//U D L R
        //初始化食物的座標
        foodX = 300;
        foodY = 200;
        //初始化一個積分
        score = 0;
    }



    GamePanel(){
        init();
        //將焦點定位在當前做的面板上:
        this.setFocusable(true);
        //加入監聽,監聽按鍵的按下操作
        this.addKeyListener(new KeyAdapter() {//設配器模式
            @Override
            public void keyPressed(KeyEvent e){
                super.keyPressed(e);
                int keyCode = e.getKeyCode();
                System.out.println(keyCode);
                if (keyCode == KeyEvent.VK_SPACE){//監聽空格
                    if (isDie){
                        //全部恢復初始化狀態
                        init();
                        isDie = false;
                    }else{//小蛇沒有死亡的情況下
                        System.out.println("點選了空格");
                        isStart = !isStart;
                        repaint();//重繪的動作
                    }
                }
                //監聽向上箭頭
                if(keyCode == KeyEvent.VK_UP){
                    direction = "U";
                }
                //監聽向下箭頭
                if(keyCode == KeyEvent.VK_DOWN){
                    direction = "D";
                }
                //監聽向左箭頭
                if(keyCode == KeyEvent.VK_LEFT){
                    direction = "L";
                }
                //監聽向右箭頭
                if(keyCode == KeyEvent.VK_RIGHT){
                    direction = "R";
                }
            }
        });
        //對定時器進行一個初始化操作
        timer = new Timer(100, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {//事件監聽,相當於每100ms監聽一下你是否發生了一個動作具體的動作放入actionPerformed

                if (isStart&&isDie == false){//遊戲是開始狀態的時候,蛇才動,後一節身子走到前一節身子的位置上
                    for (int i = lenght-1;i>0;i--){
                        snakeX[i] = snakeX[i-1];
                        snakeY[i] = snakeY[i-1];
                    }


                    //動頭
                    if ("R".equals(direction)){
                        snakeX[0]+=25;
                    }
                    if ("L".equals(direction)){
                        snakeX[0]-=25;
                    }
                    if ("U".equals(direction)){
                        snakeY[0]-=25;
                    }
                    if ("D".equals(direction)){
                        snakeY[0]+=25;
                    }


                    //防止蛇超出邊界
                    if (snakeX[0]>750){
                        snakeX[0] = 25;
                    }
                    if (snakeX[0]<25){
                        snakeX[0] = 750;
                    }
                    if (snakeY[0]<100){
                        snakeY[0] = 725;
                    }
                    if (snakeY[0]>750){
                        snakeY[0] = 100;
                    }


                    //檢測碰撞操作:
                    //食物的座標和蛇頭的座標一樣是,算作碰到
                    if (snakeX[0] == foodX&&snakeY[0] == foodY){
                        //蛇的長度+1
                        lenght++;
                        //食物的座標改變,隨機生成座標座標必須是25的倍數
                        /*
                        [25,750] -> [1,30]*25
                        Math.random() -> [0.0,1.0)
                        Math.random()*30 -> [0.0,30.0)
                        (int)(Math.random()*30)+1 ->[1,30]
                         */
                        /*
                        [100,725] -> [4,29]*25
                        [4,29]->[0,25]+4
                        [0,25]
                        new Random().nextInt(26) -> [0,26) ->[0,25]
                         */
                        foodX = ((int)(Math.random()*30)+1)*25;//【25,750】
                        foodY = (new Random().nextInt(26)+4)*25;//【100,725】


                        //吃上食物以後 積分加十分
                        score += 10;
                    }

                    //死亡判定
                    for (int i = 1;i<lenght;i++){
                        if (snakeX[i] == snakeX[0]&&snakeY[i] == snakeY[0]){
                            //將死亡狀態改爲true
                            isDie = true;
                        }
                    }
                    repaint();//重繪

                }
            }
        });
        //定時器必須要啓動
        timer.start();
    }



    @Override
    protected void paintChildren(Graphics g) {
        super.paintChildren(g);
        //填充背景顏色
        this.setBackground(new Color(77,255,36));
        //paintIcon四個參數:this指的是當前面板 g:指的是當前使用的畫筆 x,y對應的座標
        Images.titleImg.paintIcon(this,g,2,10);//頭部圖片
        //調整話筆顏色
        g.setColor(new Color(240,245,117));
        //畫一個矩形
        g.fillRect(6,70,775,685);

        //畫小蛇
        //蛇頭朝向
        if("R".equals(direction)){
            Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }else if ("L".equals(direction)){
            Images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }else if ("U".equals(direction)){
            Images.headImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }else if("D".equals(direction)){
            Images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
//        //第一節身子
//        Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);
//        //第二節身子
//        Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);
        //優化爲回圈畫蛇的部分
        for (int i = 1;i<lenght;i++){
            Images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);
        }

        //如果遊戲是暫停的,介面會有一句提示語
        if (isStart == false){
            //畫一個文字
            g.setColor(new Color(114,98,255));//顏色
            //三個參數:字型,加粗,字號
            g.setFont(new Font("微軟雅黑",Font.BOLD,40));
            //畫文字:三個參數:文字內容,X軸座標,Y軸座標
            g.drawString("點選空格開始遊戲",250,300);
        }

        //畫食物:
        Images.foodImg.paintIcon(this,g,foodX,foodY);

        //畫積分
        g.setColor(new Color(255,3,9));//顏色
        //三個參數:字型,加粗,字號
        g.setFont(new Font("微軟雅黑",Font.BOLD,20));
        //畫文字:三個參數:文字內容,X軸座標,Y軸座標
        g.drawString(""+score,650,40);

        //畫入死亡狀態
        if (isDie){
            g.setColor(new Color(255,3,9));//顏色
            //三個參數:字型,加粗,字號
            g.setFont(new Font("微軟雅黑",Font.BOLD,35));
            //畫文字:三個參數:文字內容,X軸座標,Y軸座標
            g.drawString("小蛇死亡 共得分:"+score,200,200);
        }
    }
}