Java GUI 贪吃蛇项目教程

一、实现效果

1.空格暂停,
2.上下左右控制方向
3.长度会随着食物的吃下而增加
4.定时刷新
5.累计长度和分数等等。

具体视频演示效果和教程点击跳转

二、实现思路:

1.定义所一个功能的数据

2.绘制这个功能的需要的图形

3.添加监听这个功能需要的事件(帧率事件)

键盘,鼠标,

实现代码

在这里插入图片描述

1.Data 初始化需要的图片

2.StartGame 主要实现窗口的加载,和添加GamePanel面板到窗口。

3.GamePanel 最重要的实现部分,包括:

3.1 定义需要的数据
3.2 绘制图像
3.3 实现事件监听

Data.java (加载图片使用)

package GUI.Swing.贪吃蛇;

import javax.swing.*;

//数据中心,图片
public class Data {
    //此处用来初始话图片
    public static String headerUrl = "D:/Program Files/JetBrains/test1/Lab/static/贪吃蛇/header.png";
    public static String bodyUrl = "D:/Program Files/JetBrains/test1/Lab/static/贪吃蛇/body.png";
    public static String downUrl = "D:/Program Files/JetBrains/test1/Lab/static/贪吃蛇/down.png";
    public static String foodUrl = "D:/Program Files/JetBrains/test1/Lab/static/贪吃蛇/food.png";
    public static String leftUrl = "D:/Program Files/JetBrains/test1/Lab/static/贪吃蛇/left.png";
    public static String rightUrl = "D:/Program Files/JetBrains/test1/Lab/static/贪吃蛇/right.png";
    public static String upUrl = "D:/Program Files/JetBrains/test1/Lab/static/贪吃蛇/up.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 header = new ImageIcon(headerUrl);
    public static ImageIcon body = new ImageIcon(bodyUrl);
    public static ImageIcon food = new ImageIcon(foodUrl);

}

StartGame.java (加载窗口和添加游戏面板)

package GUI.Swing.贪吃蛇;

import javax.swing.*;

/**
 * 游戏的主要启动类:
 */
public class StartGame {
    public StartGame() {
        //simple Frame
        JFrame frame = new JFrame("开始界面");
        frame.setBounds(100, 100, 900, 720);
        frame.setResizable(false);//窗口大小不能改变,不然游戏变形
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
        //一般的游戏都会放到面板上,
        frame.add(new GamePanel());
    }

    public static void main(String[] args) {
        new StartGame();
    }
}

GamePanel.java (主要的实现类,数据,画图,事件帧)

在这里插入图片描述

package GUI.Swing.贪吃蛇;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

/**
 * 游戏的面板
 * //绘制面板,游戏中所有的东西都可用这个东西来画
 */
public class GamePanel extends JPanel implements ActionListener {
    /**
     * 一、定义数据:
     */

    int length;
    int[] snakeX = new int[600];//定义snake的x坐标
    int[] snakeY = new int[600];//定义蛇的Y坐标
    String direction;//方向
    boolean isStart;//暂停效果
    //定时器 100ms
    Timer timmer = new Timer(100, this);
    //食物的坐标
    int foodX;
    int foodY;
    /*
    问题:有2个 ,random 使用 util 包下的Random
     */
    Random random = new Random();
    boolean isFail = false; //判断死亡
    int score;//累计分数

    /**
     * 构造方法.
     * 三、事件监听和键盘监听
     * 的键盘监听.
     */
    public GamePanel() {
        init();//构造器里面调用init()方法。
        //给Panel添加键盘监听=====================问题,添加失败,试试 设置是否获取焦点
        this.setFocusable(true);
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {

                System.out.println(e.getKeyChar());
                if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                    isStart = !isStart;//暂停效果,取反
                    if (isFail) {
                        isFail = false;
                    }
                    repaint();//刷新
                }
                //小蛇头的图片的转化
                if (e.getKeyCode() == KeyEvent.VK_UP) {
                    direction = "up";
                } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                    direction = "down";
                } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                    direction = "left";
                } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                    direction = "right";
                }


            }
        });
        //给panel 添加定时器,
        /*
        新建一个线程,然后让他在while里循环,通过Thread.sleep(100)的方法来休眠线程。

         */
        timmer.start();//游戏一开始定时器就启动


    }

    //初始化数据
    public void init() {
        length = 3;
        snakeX[0] = 100;
        snakeY[0] = 100;//第一个头header的坐标
        snakeX[1] = 75;
        snakeY[1] = 100;//第2 body的坐标
        snakeX[2] = 50;
        snakeY[2] = 100;//第3 body的坐标
        direction = "right";
        isStart = false;
        foodX = 25 + random.nextInt(34) * 25;
        foodY = 75 + random.nextInt(24) * 25;


    }

    /**
     * 二、绘制图形
     *
     * @param g
     */
    @Override
    public void paint(Graphics g) {

        Data.header.paintIcon(this, g, 25, 11);//广告栏
        g.fillRect(25, 75, 850, 600);//矩形面板。
        this.setVisible(true);
        this.setBackground(new Color(139, 168, 20));

        //小蛇的头图片转化
        if (direction == "right") {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (direction == "left") {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (direction == "up") {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (direction == "down") {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }

        //把小蛇body画上去,使用的组件,画笔,x,y 位置。
        for (int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        if (isStart == false) {
            g.setColor(new Color(255, 255, 255));
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("按下空格开始游戏", 300, 300);

        }
        //把食物画上去
        Data.food.paintIcon(this, g, foodX, foodY);
        //把 isFail的面板画上去,并得出分数
        if (isFail) {
            g.setColor(new Color(195, 68, 106));
            g.setFont(new Font("微软雅黑", Font.BOLD, 80));
            g.drawString("GAME OVER ", 200, 180);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("YOUR SCORE IS: " + score, 260, 400);
        }
        //把积分画上去
        g.setColor(new Color(255, 255, 255));
        g.setFont(new Font("微软雅黑", Font.CENTER_BASELINE, 18));
        g.drawString("SCORE:" + score, 750, 35);
        g.drawString("LENGTH:" + length, 750, 50);

    }

    /**
     * 三、添加事件监听或者键盘监听:
     *
     * @param e
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        if (isStart) {
            //小蛇body移动到靠头的一个body
            //小蛇右移动--2,3重叠为什么?
//            for (int i = 1; i <= length; i++) {
//                middle = snakeX[i - 1];
//                snakeX[i] = middle;
//            }

            //身体跟进
            for (int i = length - 1; i > 0; i--) {
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            //头的移动
            if (direction == "right") {
                snakeX[0] += 25;
                snakeY[0] += 0;
                if (snakeX[0] > 850) {
                    snakeX[0] = 25;
                }
            } else if (direction == "left") {
                snakeX[0] -= 25;
                snakeY[0] += 0;
                if (snakeX[0] <= 25) {
                    snakeX[0] = 850;
                }
            } else if (direction == "up") {
                snakeX[0] += 0;
                snakeY[0] -= 25;
                if (snakeY[0] <= 50) {
                    snakeY[0] = 650;
                }
            } else if (direction == "down") {
                snakeX[0] += 0;
                snakeY[0] += 25;
                if (snakeY[0] >= 650) {
                    snakeY[0] = 50;
                }
            }
            //吃食物
            if (snakeX[0] == foodX && snakeY[0] == foodY) {
                length++;//长度+1
                score = length * 10 - 30;//分数改变
                //初始化 食物坐标
                foodX = 25 + random.nextInt(34) * 25;
                foodY = 75 + random.nextInt(24) * 25;
            }
            //判断是否isFail死亡
            for (int i = 1; i < length; i++) {
                if (snakeX[i] == snakeX[0] && snakeY[i] == snakeY[0]) {
                    isFail = true;
                    isStart = false;
                }
            }

            repaint();//repaint()


        }
        //定时器开始
        timmer.start();
    }
}
发布了68 篇原创文章 · 获赞 4 · 访问量 965

猜你喜欢

转载自blog.csdn.net/jarvan5/article/details/105702076
今日推荐