Java GUI 贪吃蛇小游戏项目实战含图片资源

本文详细介绍了如何使用Java实现一款贪吃蛇游戏,包括界面绘制、帧的概念、键盘监听、游戏逻辑以及游戏状态管理。从静态界面到动态小蛇的绘制,再到游戏开始、暂停、移动控制,以及小蛇吃食物长大和失败判定的实现,逐步展示了游戏的核心功能。
摘要由CSDN通过智能技术生成

项目实战 - 贪吃蛇

图片资源提取地址
百度网盘

链接:https://pan.baidu.com/s/19gEhIuZrut12l5a8jcknFA?pwd=1111
提取码:1111

界面绘制

这里设计到帧的概念,即一秒钟里有多少张图片,一般电影为24帧,每一帧就是一张图片

涉及到键盘监听,以及计时器每隔一段时间进行页面刷新

先绘制静态页面
![[Pasted image 20220604102255.png]]
在这里插入图片描述

游戏整体界面

  • 里面承载广告图片以及游戏界面

游戏启动类
代码

public class StartGame {  
    public static void main(String[] args) {  
        JFrame frame = new JFrame("贪吃蛇");  
  
        //游戏界面-单独在面板上面  
        frame.add(new GamePanel());  
  
        frame.setResizable(false);//窗口大小不可变  
        frame.setBounds(200,200,905,720);  
        frame.setVisible(true);  
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);  
    }  
}

游戏面板类
代码

//游戏的面板  
public class GamePanel extends JPanel {  
    //绘制面板  
    @Override  
    protected void paintComponent(Graphics g) {  
        super.paintComponent(g);//清屏  
        this.setBackground(Color.BLACK);  
        this.setBackground(Color.WHITE);  
        Data.header.paintIcon(this,g,25,11);  
        //画出黑色游戏界面  
        g.fillRect(25,75,850,600);  
    }  
}

数据中心
![[Pasted image 20220604103103.png]]

代码

//数据中心  
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 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 URL bodyURL = Data.class.getResource("static/body.png");  
    public static ImageIcon body = new ImageIcon(bodyURL);  
  
    public static URL foodURL = Data.class.getResource("static/food.png");  
    public static ImageIcon food = new ImageIcon(foodURL);  
  
}

运行时可能会报错ClassNotFound

  1. 首先检查Data类中的url是否写对
  2. 重启Idea,再次启动即可

最后的效果
截图
![[Pasted image 20220604102827.png]]

绘制静态小蛇

游戏启动类
代码

public class StartGame {  
    public static void main(String[] args) {  
        JFrame frame = new JFrame("贪吃蛇");  
  
        //游戏界面-单独在面板上面  
        frame.add(new GamePanel());  
  
        frame.setResizable(false);//窗口大小不可变  
        frame.setBounds(200,200,905,720);  
        frame.setVisible(true);  
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);  
    }  
}

游戏面板类
代码

//游戏的面板  
public class GamePanel extends JPanel {  
  
    //定义蛇的数据结构  
    int length;//蛇的长度  
    //黑色游戏界面总共大小为850*600  
    //所以小蛇最多的节数为850*600/25*25 = 816  
    //所以只需要以下两个数组比816长即可  
    int[] snakeX = new int[850];//蛇的X坐标  
    int[] snakeY = new int[850];//蛇的Y坐标  
    String dir;//初始方向  
    //当前游戏状态:开始,停止  
    boolean isStart = false; //默认是不开始  
  
    //构造器  
    public GamePanel(){  
        init();  
    }  
  
    //初始化方法  
    public void init(){  
        length = 3;  
        snakeX[0] = 100;snakeY[0] = 100;//脑袋的坐标  
        snakeX[1] = 75;snakeY[1] = 100; //第一节身体坐标  
        snakeX[2] = 50;snakeY[2] = 100; //第二节身体坐标  
        dir = "R"; //初始方向向右  
    }  
  
  
    //绘制面板  
    @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);  
  
        //把小蛇画上去  
        //蛇头初始化向右  
        switch (dir) {  
            case "R":  
                Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "L":  
                Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "U":  
                Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "D":  
                Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;        }  
        for (int i = 1; i < length; i++) {  
            Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);  
        }  
  
        //游戏状态  
        if (!isStart)  
        {  
            g.setColor(Color.white);  
            g.setFont(new Font("微软雅黑",Font.BOLD,40));  
            g.drawString("按下空格开始游戏",300,300);  
        }  
  
    }  
}

让小蛇动起来

实现按下空格游戏开始游戏暂停
游戏面板类
代码

//游戏的面板  
public class GamePanel extends JPanel implements KeyListener {  
  
    //定义蛇的数据结构  
    int length;//蛇的长度  
    //黑色游戏界面总共大小为850*600  
    //所以小蛇最多的节数为850*600/25*25 = 816  
    //所以只需要以下两个数组比816长即可  
    int[] snakeX = new int[850];//蛇的X坐标  
    int[] snakeY = new int[850];//蛇的Y坐标  
    String dir;//初始方向  
    //当前游戏状态:开始,停止  
    boolean isStart = false; //默认是不开始  
  
    //构造器  
    public GamePanel(){  
        init();  
        //获得焦点事件  
        this.setFocusable(true);  
        //获得键盘事件  
        this.addKeyListener(this);  
    }  
  
    //初始化方法  
    public void init(){  
        length = 3;  
        snakeX[0] = 100;snakeY[0] = 100;//脑袋的坐标  
        snakeX[1] = 75;snakeY[1] = 100; //第一节身体坐标  
        snakeX[2] = 50;snakeY[2] = 100; //第二节身体坐标  
        dir = "R"; //初始方向向右  
    }  
  
  
    //绘制面板  
    @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);  
  
        //把小蛇画上去  
        //蛇头初始化向右  
        switch (dir) {  
            case "R":  
                Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "L":  
                Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "U":  
                Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "D":  
                Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;        }  
        for (int i = 1; i < length; i++) {  
            Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);  
        }  
  
        //游戏状态  
        if (!isStart)  
        {  
            g.setColor(Color.white);  
            g.setFont(new Font("微软雅黑",Font.BOLD,40));  
            g.drawString("按下空格开始游戏",300,300);  
        }  
  
    }  
  
    //键盘监听事件  
    @Override  
    public void keyPressed(KeyEvent e) {  
        int keyCode = e.getKeyCode();  
        if (keyCode == KeyEvent.VK_SPACE) {  
            isStart = !isStart;  
            repaint();  
        }  
    }  
    @Override  
    public void keyTyped(KeyEvent e) {  
  
    }  
    @Override  
    public void keyReleased(KeyEvent e) {  
  
    }  
}

键盘控制小蛇移动

游戏面板类
代码

//游戏的面板  
public class GamePanel extends JPanel implements KeyListener, ActionListener {  
  
    //定义蛇的数据结构  
    int length;//蛇的长度  
    //黑色游戏界面总共大小为850*600  
    //所以小蛇最多的节数为850*600/25*25 = 816  
    //所以只需要以下两个数组比816长即可  
    int[] snakeX = new int[850];//蛇的X坐标  
    int[] snakeY = new int[850];//蛇的Y坐标  
    String dir;//初始方向  
    //当前游戏状态:开始,停止  
    boolean isStart = false; //默认是不开始  
    Timer timer = new Timer(100,this);//监听当前对象,100ms刷新一次  
  
    //构造器  
    public GamePanel(){  
        init();  
        //获得焦点事件  
        this.setFocusable(true);  
        //获得键盘事件  
        this.addKeyListener(this);  
    }  
  
    //初始化方法  
    public void init(){  
        length = 3;  
        snakeX[0] = 100;snakeY[0] = 100;//脑袋的坐标  
        snakeX[1] = 75;snakeY[1] = 100; //第一节身体坐标  
        snakeX[2] = 50;snakeY[2] = 100; //第二节身体坐标  
        dir = "R"; //初始方向向右  
        timer.start();  
    }  
  
  
    //绘制面板  
    @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);  
  
        //把小蛇画上去  
        //蛇头图片  
        switch (dir) {  
            case "R":  
                Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "L":  
                Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "U":  
                Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "D":  
                Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;        }  
        for (int i = 1; i < length; i++) {  
            Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);  
        }  
  
        //游戏状态  
        if (!isStart)  
        {  
            g.setColor(Color.white);  
            g.setFont(new Font("微软雅黑",Font.BOLD,40));  
            g.drawString("按下空格开始游戏",300,300);  
        }  
  
    }  
  
    //键盘监听事件  
    @Override  
    public void keyPressed(KeyEvent e) {  
        int keyCode = e.getKeyCode();  
        if (keyCode == KeyEvent.VK_SPACE) {  
            isStart = !isStart;  
            repaint();  
        }  
        //小蛇移动  
        switch (keyCode) {  
            case KeyEvent.VK_UP:  
                dir = "U";  
                break;            case KeyEvent.VK_DOWN:  
                dir = "D";  
                break;            case KeyEvent.VK_LEFT:  
                dir = "L";  
                break;            case KeyEvent.VK_RIGHT:  
                dir = "R";  
                break;        }  
    }  
    @Override  
    public void keyTyped(KeyEvent e) {  
  
    }  
    @Override  
    public void keyReleased(KeyEvent e) {  
  
    }  
  
    //实现事件监听  
    //实现隔一段时间按刷新,比如说一秒10次  
    @Override  
    public void actionPerformed(ActionEvent e) {  
        //如果游戏是开始状态,小蛇就动起来  
        if (isStart)  
        {  
            //右移  
            for (int i = length - 1; i > 0; i--) {  
                snakeX[i] = snakeX[i-1];  
                snakeY[i] = snakeY[i-1];  
            }  
            //脑袋如何移动  
            switch (dir) {  
                case "U":  
                    snakeY[0] = snakeY[0] - 25;  
                    break;                case "D":  
                    snakeY[0] = snakeY[0] + 25;  
                    break;                case "L":  
                    snakeX[0] = snakeX[0] - 25;  
                    break;                case "R":  
                    snakeX[0] = snakeX[0] + 25;  
                    break;            }  
  
            //边界判断  
            if(snakeX[0] > 850)  
                snakeX[0] = 25;  
            if(snakeX[0] < 25)  
                snakeX[0] = 850;  
            if(snakeY[0] > 650)  
                snakeY[0] = 75;  
            if(snakeY[0] < 75)  
                snakeY[0] = 650;  
  
            repaint();//重画页面  
        }  
        timer.start();  
    }  
}

小蛇吃食物长大、失败判定及积分系统

游戏面板类
代码

//游戏的面板  
public class GamePanel extends JPanel implements KeyListener, ActionListener {  
  
    //定义蛇的数据结构  
    int length;//蛇的长度  
    //黑色游戏界面总共大小为850*600  
    //所以小蛇最多的节数为850*600/25*25 = 816  
    //所以只需要以下两个数组比816长即可  
    int[] snakeX = new int[850];//蛇的X坐标  
    int[] snakeY = new int[850];//蛇的Y坐标  
    String dir;//初始方向  
  
    //食物坐标  
    int foodX;  
    int foodY;  
    Random random = new Random();  
  
    int score;  
  
    //当前游戏状态:开始,停止  
    boolean isStart = false; //默认是不开始  
    boolean isFail = false; //游戏是否失败,初始化为未失败  
    Timer timer = new Timer(100,this);//监听当前对象,100ms刷新一次  
  
    //构造器  
    public GamePanel(){  
        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; //第二节身体坐标  
        dir = "R"; //初始方向向右  
        foodX = 25 + 25*random.nextInt(33);  
        foodY = 75 + 25*random.nextInt(23);  
        score = 0;  
    }  
  
  
    //绘制面板  
    @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);  
  
        //画积分  
        g.setColor(Color.white);  
        g.setFont(new Font("微软雅黑",Font.BOLD,18));  
        g.drawString("长度"+length,750,35);  
        g.drawString("分数"+score,750,50);  
  
        Data.food.paintIcon(this,g,foodX,foodY);  
  
        //把小蛇画上去  
        //蛇头图片  
        switch (dir) {  
            case "R":  
                Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "L":  
                Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "U":  
                Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;            case "D":  
                Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);  
                break;        }  
        for (int i = 1; i < length; i++) {  
            Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);  
        }  
  
  
        //游戏状态  
        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("失败,按下空格重新开始游戏",200,300);  
        }  
  
    }  
  
    //键盘监听事件  
    @Override  
    public void keyPressed(KeyEvent e) {  
        int keyCode = e.getKeyCode();  
        if (keyCode == KeyEvent.VK_SPACE) {  
            if (isFail) {  
                //重新开始  
                isFail = false;  
                init();  
            } else{  
                isStart = !isStart;  
            }  
            repaint();  
        }  
        //小蛇移动  
        switch (keyCode) {  
            case KeyEvent.VK_UP:  
                dir = "U";  
                break;            case KeyEvent.VK_DOWN:  
                dir = "D";  
                break;            case KeyEvent.VK_LEFT:  
                dir = "L";  
                break;            case KeyEvent.VK_RIGHT:  
                dir = "R";  
                break;        }  
    }  
    @Override  
    public void keyTyped(KeyEvent e) {  
  
    }  
    @Override  
    public void keyReleased(KeyEvent e) {  
  
    }  
  
    //实现事件监听  
    //实现隔一段时间按刷新,比如说一秒10次  
    @Override  
    public void actionPerformed(ActionEvent e) {  
        //如果游戏是开始状态,小蛇就动起来  
        if (isStart && !isFail)  
        {  
            //吃食物  
            if(snakeX[0] == foodX && snakeY[0] == foodY)  
            {  
                //长度+1  
                length++;  
                //分数+10  
                score+=10;  
                //再次随机事物  
                foodX = 25 + 25*random.nextInt(33);  
                foodY = 75 + 25*random.nextInt(23);  
            }  
  
            //右移  
            for (int i = length - 1; i > 0; i--) {  
                snakeX[i] = snakeX[i-1];  
                snakeY[i] = snakeY[i-1];  
            }  
            //脑袋如何移动  
            switch (dir) {  
                case "U":  
                    snakeY[0] = snakeY[0] - 25;  
                    break;                case "D":  
                    snakeY[0] = snakeY[0] + 25;  
                    break;                case "L":  
                    snakeX[0] = snakeX[0] - 25;  
                    break;                case "R":  
                    snakeX[0] = snakeX[0] + 25;  
                    break;            }  
  
            //边界判断  
            if(snakeX[0] > 850)  
                snakeX[0] = 25;  
            if(snakeX[0] < 25)  
                snakeX[0] = 850;  
            if(snakeY[0] > 650)  
                snakeY[0] = 75;  
            if(snakeY[0] < 75)  
                snakeY[0] = 650;  
  
            //失败判定,撞到自己就失败  
            for (int i = 1; i < length; i++) {  
                if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i])  
                isFail = true;  
            }  
  
            repaint();//重画页面  
        }  
        timer.start();  
    }  
}

此时,游戏启动后便可以正常运行,基础功能已经实现


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值