用Java和Gui实现贪吃蛇小游戏

欧阳德运
2023-12-01

前 言

        1、,如果时间片足够小,就是动画,对于人眼来说,一秒30帧即可看为是动画,拆开就是静态的图片

        2、所用工具:键盘监听、定时器Timer

功能实现

        1、步骤

                (1)定义数据

                (2)画上去

                (3)监听事件 —— 键盘监听、事件监听

        2、代码

  • 数据导入
// 导入数据

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

/**
 * 1、导入图像素材
 * 2、添加到图片图标上
 */

public class DataTest {
    public static URL headerURL = DataTest.class.getResource("static/header.png"); // logo
    public static URL upURL = DataTest.class.getResource("static/up.png"); // 蛇头
    public static URL downURL = DataTest.class.getResource("static/down.png"); // 蛇头
    public static URL leftURL = DataTest.class.getResource("static/left.png"); // 蛇头
    public static URL rightURL = DataTest.class.getResource("static/right.png"); // 蛇头
    public static URL bodyURL = DataTest.class.getResource("static/body.png"); // 蛇身
    public static URL foodURL = DataTest.class.getResource("static/food.png"); // 食物

    public static ImageIcon header = new ImageIcon(headerURL);
    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 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;

/**
 * 总体:设置全局变量、构造器、初始化面板、paintComponent绘制面板、keyPressed键盘监听、actionPerformed事件监听
 *      继承Jpanel类、 KeyListener, ActionListener接口
 *
 * 功能:1、设置全局变量:定义蛇的数据结构、食物坐标、成绩、游戏状态(是否开始、是否失败)、定时器
 *      2、构造器:调用初始化方法、获得焦点事件、获得键盘监听事件、启动定时器
 *      3、初始化面板:蛇(长度、位置、初始方向)、食物随机分布、成绩置为0
 *      4、paintComponent绘制面板:清屏、绘制静态面板、画积分、画食物、画小蛇、游戏状态
 *      5、keyPressed键盘监听:获得键盘按键、设置提示字符、蛇头换向
 *      6、actionPerformed事件监听:检测游戏状态并行动(吃食物长大涨分、移动、转向)、失败判定、开启定时器
 */

public class GamePanelTest extends JPanel implements KeyListener, ActionListener {

    // 设置全局变量
    int length; //蛇长
    // 蛇的坐标
    int[] snakeX = new int[600];
    int[] snakeY = new int[500];
    String direction; // 蛇头方向

    //食物坐标(因为随机更换,所以不必设数组来保存上一次的值)
    int foodX;
    int foodY;
    Random random = new Random();

    //成绩
    int score;

    //游戏状态
    Boolean isStart; //游戏是否开始
    Boolean isFalse; //游戏是否失败

    //定时器
    Timer timer = new Timer(100,this);

    // 构造器
    public GamePanelTest(){
        init(); //调用初始化方法
        this.setFocusable(true); //获得焦点事件
        this.addKeyListener(this); //获得键盘监听事件
        timer.start(); //启动定时器
    }


    // 初始化面板
    public void init(){
        //蛇(长度、位置、初始方向)
        length = 3;
        snakeX[0] = 100; snakeY[0] = 100;//脑袋位置
        snakeX[1] = 75; snakeY[1] = 100;//第一个身体位置
        snakeX[2] = 50; snakeY[2] = 100;//第二个身体位置
        direction = "right"; // 初始方向向右

        //食物随机分布
        foodX = 25 + 25*random.nextInt(34); // 850 / 25 = 34
        foodY = 75 + 25*random.nextInt(24); // 650 / 25 = 24

        //成绩置为0
        score = 0;

        //游戏状态
        isStart = false;
        isFalse = false;
    }

    // paintComponent绘制面板
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); //清屏

        //绘制静态面板
        this.setBackground(Color.WHITE);
        DataTest.header.paintIcon(this, g, 25, 11); //logo
        g.fillRect(25,75,850,650); //游戏界面(黑色)

        //画积分
        g.setColor(Color.WHITE);
        g.setFont(new Font("微软雅黑", Font.BOLD, 16));
        g.drawString("长度:" + length, 750, 31);
        g.drawString("分数:" + score, 750, 53);

        //画食物
        DataTest.food.paintIcon(this, g, foodX, foodY);

        //画小蛇
        //蛇头
        if (direction.equals("right"))
            DataTest.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        else if (direction.equals("left"))
            DataTest.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        else if (direction.equals("up"))
            DataTest.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        else if (direction.equals("down"))
            DataTest.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        //蛇身
        for (int i = 1; i < length; i++) {
            DataTest.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }

        //游戏状态
        //是否开始
        if (isStart == false){
            g.setColor(Color.WHITE);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("按下空格,开始游戏" , 300, 300);
        }
        //是否失败
        if (isFalse){
            g.setColor(Color.RED);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("游戏失败,按下空格重新开始" , 300, 300);
        }
    }


    // keyPressed键盘监听
    @Override
    public void keyPressed(KeyEvent e) {
        //获得键盘按键
        int keycode = e.getKeyCode();

        //设置提示字符
        if (keycode == KeyEvent.VK_SPACE) {
            if (isFalse){
                //游戏失败,重新开始
                isFalse = false;
                init();
            }else{
                isStart = !isStart; //暂停
            }
            repaint();
        }

        //蛇头换向
        if (keycode == KeyEvent.VK_UP)
            direction = "up";
        else if (keycode == KeyEvent.VK_DOWN)
            direction = "down";
        else if (keycode == KeyEvent.VK_LEFT)
            direction = "left";
        else if (keycode == KeyEvent.VK_RIGHT)
            direction = "right";
    }

    // actionPerformed事件监听
    @Override
    public void actionPerformed(ActionEvent e) {
        //检测游戏状态并行动(吃食物长大涨分、移动、转向)
        if (isStart && isFalse == false){
            //吃食物长大涨分
            if (snakeX[0]==foodX && snakeY[0]==foodY){
                length++; //长度+1
                score += 10; //分数+10
                // 再次随机生成食物
                foodX = 25 + 25*random.nextInt(34); // 850 / 25 = 34
                foodY = 75 + 25*random.nextInt(24); // 650 / 25 = 24
            }
            //移动
            for (int i = length-1; i > 0; i--) {
                snakeX[i] = snakeX[i-1];
                snakeY[i] = snakeY[i-1];
            }
            //转向
            if (direction.equals("right")){
                snakeX[0] += 25;
                if (snakeX[0] > 850)
                    snakeX[0] = 25;
            }else if (direction.equals("left")){
                snakeX[0] -= 25;
                if (snakeX[0] < 25)
                    snakeX[0] = 850;
            }else if (direction.equals("up")){
                snakeY[0] -= 25;
                if (snakeY[0] < 75)
                    snakeY[0] = 700;
            }else if (direction.equals("down")){
                snakeY[0] += 25;
                if (snakeY[0] > 700)
                    snakeY[0] = 75;
            }
            repaint();
        }
        //失败判定
        for (int i = 1; i < length; i++) {
            if (snakeX[0]==snakeX[i] && snakeY[0]==snakeY[i])
                isFalse = true;
        }
        //开启定时器
        timer.start();
    }


// 因继承接口,必须重写的方法
    @Override
    public void keyTyped(KeyEvent e) {}
    @Override
    public void keyReleased(KeyEvent e) {}

}

  • 游戏启动

import javax.swing.*;

/**
 * 1、创建对象
 * 2、设置窗口大小等一系列操作
 * 3、将面板添加到框架中
 */

public class StartGameTest extends JFrame {
    public static void main(String[] args) {
        JFrame frame = new JFrame();

        frame.setBounds(10,10,900,780); //设置窗口大小
        frame.setResizable(false); //设置窗口大小不可变
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //窗口可关闭
        frame.setVisible(true); //设置窗口可见

        frame.add(new GamePanelTest()); //添加面板
    }
}

 类似资料: