java gui详解贪吃蛇小游戏实现流程

根据狂神的视频做的,然后自己优化了一些bug,比如新生成食物的时候不会生成在蛇的身体上,再新增长身体的时候不会在左上角出现一个绿色的方块以及增加了难度控制功能,以及可以使用WASD进行控制,而不仅仅限于上下左右方向键
最后的游戏界面是这样的:

可以在上方的菜单栏里选择不同的难度进行游戏.难度对应的是不同的蛇移动的速度,点击退出游戏和点击右上角的X是一样的功能,都是退出游戏.然后点击重新开始就会回到最初的时候重新开始游戏.
按下空格开始游戏,随时可以再次按下空格进行暂停游戏.同时每吃到一个食物就会在右上角加10分.

游戏代码一共分成了三个类
一个是GameStart类,用来创建JFrame绘制游戏主体.
一个是GamePanel类,用来添加在JFrame中,里面加入了菜单栏以及一些键盘监听器,用来根据读入的信息操纵蛇移动.
另一个是Data类,用来读取statics文件夹中的图片素材,代码更简洁.

GameStart类代码如下:(具体代码后面都有注释)

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author Laurie
 */
public class GameStart {
    public static void main(String[] args) {
        JFrame jframe = new JFrame("贪吃蛇");
        jframe.setBounds(10, 10, 900, 720);//绘制游戏主界面的范围
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.setResizable(false);//不可扩大缩小窗口
        GamePanel gamePanel = new GamePanel();
        jframe.add(gamePanel);
        jframe.setVisible(true);//显形
        gamePanel.setLayout(new BorderLayout());
    }
}

GamePanel类代码是:

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;

/**
 * @author Laurie
 */

public class GamePanel extends JPanel implements ActionListener, KeyListener {
    int length;//蛇的长度
    int[] snakeX = new int[500];//随便定义长度,反之不出意外是不会超过的
    int[] snakeY = new int[500];
    String direction;//蛇的方向,来根据这个改变蛇头的图片
    Timer timer = new Timer(60, this);//计时器,来触发蛇移动的事件
    int score;//分数
    Boolean isFail = false;//是否失败判断
    Boolean isStart = false;//是否启动判断
    int foodX;//食物坐标
    int foodY;
    Random random = new Random();//用来产生随机数的Random类的实例化

    public void init(){
        length = 3;//一开始蛇的三节
        snakeX[0] = 100;//蛇头为下标0
        snakeY[0] = 100;
        snakeX[1] = 75;
        snakeY[1] = 100;
        snakeX[2] = 50;
        snakeY[2] = 100;
        direction = "R";//初始化方向朝右边
        score = 0;
        foodX = getFoodX();//通过方法获取食物的坐标
        foodY = getFoodY();
    }
    public GamePanel(){
        //构造函数
        init();//进行初始化
        this.setFocusable(true);//设置可以被赋予焦点
        this.setForeground(Color.pink);//设置为粉色
        this.addKeyListener(this);//添加键盘的监听
        timer.start();//开始计时器
        JMenuBar menuBar = new JMenuBar();//选项栏
        JButton jb1 = new JButton("退出游戏");
        JButton jb3 = new JButton("新手难度");
        JButton jb4 = new JButton("高手难度");
        JButton jb5 = new JButton("地狱难度");
        menuBar.add(jb1);
        menuBar.add(jb3);
        menuBar.add(jb4);
        menuBar.add(jb5);
        jb1.addActionListener(e -> {//添加jb1的监听
            System.exit(0);//退出
        });
        jb3.addActionListener(e -> {
            this.requestFocus();//不获取焦点后面操作键盘都会在菜单栏里,就无法操作蛇了
            timer.stop();//把原来的timer停止
            timer = new Timer(80, this);//使蛇的速度变慢
            timer.start();//重新开始timer
        });
        jb4.addActionListener(e -> {
            this.requestFocus();
            timer.stop();
            timer = new Timer(40, this);
            timer.start();
        });
        jb5.addActionListener(e -> {
            this.requestFocus();
            timer.stop();
            timer = new Timer(20, this);
            timer.start();
        });
        this.add(menuBar);
        JButton jb2 =  new JButton("重新开始");
        jb2.addActionListener(e -> {
            init();//重新开始所以重新初始化一下
            repaint();//重画
            this.requestFocus();
        });
        this.add(jb2);
    }
    public int getFoodX(){
        //如果没有判断的话会出现bug,也就是食物可能出现在蛇的身体里,所以要进行判断优化
        boolean flag = true;
        int x = 25 + 25 * random.nextInt(34);//因为一格为25,所以要乘一个25
        while(flag){
            for(int i = 0; i < length; i++){
                if(snakeX[i] == x) {
                    x = 25 + 25 * random.nextInt(34);//如果和身体重合就重新随机一个数
                }else{
                    flag = false;
                }
            }
        }
        return x;
    }
    public int getFoodY(){
        boolean flag = true;
        int y = 75 + 25 * random.nextInt(24);//24是计算出来的,总panel的大小除以25
        while(flag){
            for(int i = 0; i < length; i++){
                if(snakeY[i] == y) {
                    y = 75 + 25 * random.nextInt(34);
                }else{
                    flag = false;
                }
            }
        }
        return y;
    }
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponents(g);//这个不加可能会出问题
        this.setBackground(Color.white);
        g.fillRect(0,0,90,30);
        g.setColor(Color.black);
        g.drawString("贪吃蛇大挑战",10,20);

        g.setColor(Color.LIGHT_GRAY);//分数提示框
        g.fillRect( 25, 36, 850, 40);

        g.setColor(Color.pink);//游戏主界面
        g.fillRect(25,75, 850, 600);

        if ("R".equals(direction)) {//判断是什么蛇头朝向,选择不同的蛇头图片
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if ("L".equals(direction)) {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if ("U".equals(direction)) {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if ("D".equals(direction)) {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }

        for (int i = 1; i < length; i++) {//通过for循环绘制蛇的身体
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        g.setColor(Color.WHITE);
        g.setFont(new Font("微软雅黑", Font.BOLD, 18));
        g.drawString("长度:"+length,650,54);
        g.drawString("分数:"+score,750,54);//分数长度等的绘制
        Data.food.paintIcon(this, g, foodX, foodY);//绘制食物
        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 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 ("R".equals(direction)) {
                //动完了身体,这里动蛇头,根据不同的方向来动到位置
                snakeX[0] = snakeX[0] + 25;
                if (snakeX[0] > 850) {
                    snakeX[0] = 25;
                }
            } else if ("L".equals(direction)) {
                snakeX[0] = snakeX[0] - 25;
                if (snakeX[0] < 25) {
                    snakeX[0] = 850;
                }
            } else if ("U".equals(direction)) {
                snakeY[0] = snakeY[0] - 25;
                if (snakeY[0] < 75) {
                    snakeY[0] = 650;
                }
            } else if ("D".equals(direction)) {
                snakeY[0] = snakeY[0] + 25;
                if (snakeY[0] > 650) {
                    snakeY[0] = 75;
                }
            }

            if (snakeX[0] == foodX && snakeY[0] == foodY) {//判断是否吃到食物
                //如果两者的xy坐标重合了就说明吃到了
                length++;//吃到了长度加一
                snakeX[length - 1] = foodX - 1;//这里是避免出现一个bug,没有这两行就会在吃吃到以后左上角出现一个绿方块
                //这是因为新增加的身体没有赋值坐标,所以就默认在00的位置
                snakeY[length - 1] = foodY - 1;
                score = score + 10;
                foodX = getFoodX();//重新生成新的食物
                foodY = getFoodY();
            }
            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){//如果是空格的话激素hi进行判断
            if(!isFail){//如果没有失败就进行暂停与重新游戏的功能实现
                isStart = !isStart;
            }else{//如果已经死了就重新开始
                isFail = false;
                init();
            }
            repaint();//重新绘制
        }
        if (keyCode == KeyEvent.VK_LEFT && !"R".equals(direction)) {//检查获取的是上下左右的哪个进行蛇头转向
            direction = "L";
        } else if (keyCode == KeyEvent.VK_RIGHT && !"L".equals(direction)) {
            direction = "R";
        } else if (keyCode == KeyEvent.VK_UP && !"D".equals(direction)) {
            direction = "U";
        } else if (keyCode == KeyEvent.VK_DOWN && !"U".equals(direction)) {
            direction = "D";
        }
        if (keyCode == KeyEvent.VK_A && !"R".equals(direction)) {//检查获取的是wasd的哪个进行蛇头转向
            //注意当是与蛇头反方向的不可以进行转动,毕竟也不能180度转脖子把
            direction = "L";
        } else if (keyCode == KeyEvent.VK_D && !"L".equals(direction)) {
            direction = "R";
        } else if (keyCode == KeyEvent.VK_W && !"D".equals(direction)) {
            direction = "U";
        } else if (keyCode == KeyEvent.VK_S && !"U".equals(direction)) {
            direction = "D";
        }
    }

    //这两个没有用,所以不用写了
    @Override
    public void keyTyped(KeyEvent e) {

    }
    @Override
    public void keyReleased(KeyEvent e) {

    }
}

Data类代码是:

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

/**
 * @author Laurie
 */
public class Data {
    //读取statics文件夹里的图片,加载成图片
    public static URL bodyURL = Data.class.getResource("/statics/body.png");
    public static URL foodURL = Data.class.getResource("/statics/food.png");
    public static URL downURL = Data.class.getResource("/statics/down.png");
    public static URL upURL = Data.class.getResource("/statics/up.png");
    public static URL rightURL = Data.class.getResource("/statics/right.png");
    public static URL leftURL = Data.class.getResource("/statics/left.png");
    public static ImageIcon body = new ImageIcon(bodyURL);
    public static ImageIcon food = new ImageIcon(foodURL);
    public static ImageIcon down = new ImageIcon(downURL);
    public static ImageIcon up = new ImageIcon(upURL);
    public static ImageIcon right = new ImageIcon(rightURL);
    public static ImageIcon left = new ImageIcon(leftURL);
}

整个项目文件可以在github上自取,点击蓝字
github
上不去的也可以在gitee上自取,点击蓝字
gitee

💕
真的不下一个自己玩一玩吗[手动滑稽]

到此这篇关于java gui详解贪吃蛇小游戏实现流程的文章就介绍到这了,更多相关java 贪吃蛇内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java实现简单的贪吃蛇小游戏

    本文实例为大家分享了Java实现简单的贪吃蛇小游戏的具体代码,供大家参考,具体内容如下 1. 程序结构 程序结构图如图: 2. 程序设计思路 2.1 Data类 作用:连接statics文件夹,将静态资源包中的图片转化为图标 方便在面板上绘制. 实现:使用class.getResource(String path)方法. 代码如下: package com.snake; import javax.swing.*; import java.net.URL; public class Data {

  • Java实现简易GUI贪吃蛇小游戏

    本文实例为大家分享了Java实现贪吃蛇小游戏的具体代码,供大家参考,具体内容如下 主启动类 import javax.swing.*; /** * @author The Setting sun * @create 2021-09-11 15:19 */ //主启动类 public class StartGame { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setResizable(f

  • Java实现简单版贪吃蛇游戏

    本文实例为大家分享了Java实现简单版贪吃蛇游戏的具体代码,供大家参考,具体内容如下 这是一个比较简洁的小游戏,主要有三个类,一个主类,一个食物类,一个贪吃蛇类. 1.首先定义主类,主类中主要用来创建窗口 public class Main { public static final int WIDTH=600; public static final int HEIGHT=600; public static void main(String[] args) { JFrame win =new

  • 基于Java实现简单贪吃蛇游戏

    本文实例为大家分享了Java实现简单贪吃蛇游戏的具体代码,供大家参考,具体内容如下 贪吃蛇小游戏制作方法 首先需要的准备有: 1.掌握Java基础知识,即Java SE 2.了解一定的GUI知识 3.自定义的贪吃蛇图片(可以在网上找到) 如果以上三点都没有,也不要紧,完全可以看我之前的博文来进行学习!!!! 学习贪吃蛇的目的 一:了解GUI 对前端的知识进行了解 二:了解监听器的作用 熟练掌握监听器(重点) 三:为枯燥乏味的学习提高兴趣(大重点!!) 贪吃蛇小游戏运行效果 设计思路: 由Game

  • Java实战之贪吃蛇小游戏(源码+注释)

    一.工程文件 二.Main.java package com.company; import javax.swing.*; public class Main { public static void main(String[] args) { //创建窗体对象 JFrame frame = new JFrame(); //创建窗体参数() frame.setBounds(10,10,900,720); //设置不允许更改大小 //frame.setResizable(false); //设置关

  • Java 实现贪吃蛇游戏的示例

    游戏界面基本布局 贪吃蛇是基于JFrame的一款小游戏.它主要有两部分组成,一个是显示区域,一个是按钮区域.这两个区域都用JPanel来实现. 首先需要创建一个基于JFrame的类,例如创建一个MyFrame,让其继承于JFrame. 然后创建一个显示区域的类MyPanel,一个按钮区域的类Button,当然了这两个类都基于JPanel. 第三步:在MyFrame类中实例化两个JPanel类.并在MyFrame构造方法中设置窗体的logo.窗体的标题.窗体初始位置.窗体的大小.窗体的背景颜色.窗

  • Java实现简单的贪吃蛇游戏

    本文实例为大家分享了Java实现简单贪吃蛇游戏的具体代码,供大家参考,具体内容如下 代码 启动类 package snake; import javax.swing.*; //游戏的主启动类 public class StartGame { public static void main(String[] args) { JFrame frame = new JFrame("贪吃蛇"); frame.setBounds(10,10,900,720); frame.setResizabl

  • java实现简单贪吃蛇小游戏

    本文实例为大家分享了java实现贪吃蛇小游戏,供大家参考,具体内容如下 有两个类,放在同一文件下下即可,背景图片,标题,蛇尾可自行更改 import java.awt.*; import javax.swing.*; import java.awt.event.*; public class MyJFrame extends JFrame{ public MyJFrame() { int x= Toolkit.getDefaultToolkit().getScreenSize().width;

  • java gui详解贪吃蛇小游戏实现流程

    根据狂神的视频做的,然后自己优化了一些bug,比如新生成食物的时候不会生成在蛇的身体上,再新增长身体的时候不会在左上角出现一个绿色的方块以及增加了难度控制功能,以及可以使用WASD进行控制,而不仅仅限于上下左右方向键 最后的游戏界面是这样的: 可以在上方的菜单栏里选择不同的难度进行游戏.难度对应的是不同的蛇移动的速度,点击退出游戏和点击右上角的X是一样的功能,都是退出游戏.然后点击重新开始就会回到最初的时候重新开始游戏. 按下空格开始游戏,随时可以再次按下空格进行暂停游戏.同时每吃到一个食物就会

  • 利用Java编写个"不贪吃蛇"小游戏

    目录 前言 代码 蛇.药丸的抽象 游戏界面 启动类 游戏演示 最后 前言 我写的这个”贪吃蛇“和小时候玩的”贪吃蛇“有点不一样,以往的”贪吃蛇“吃了食物蛇身就会变长,而我写的这个吃了“食物”蛇身会变短,并且胜利条件就是“把蛇变没”,嘻嘻~ 这里的“食物”其实是“药丸”,初始时,蛇身很长,你要通过食用“药丸”,来让自己的身体变短,直到自己消失不见,你就获胜了. “药丸”共有三种,分别为“红色药丸.蓝色药丸.绿色药丸”,对应分值“5分.2分.1分”,蛇吃了“药丸”会减掉对应分值数量的身体,并累计分值

  • 用GUI实现java版贪吃蛇小游戏

    本文实例为大家分享了java版贪吃蛇小游戏的具体代码,供大家参考,具体内容如下 项目结构 新建一个JFrame窗口,作为程序入口 public class GameStart{ public static void main(String[] args) { JFrame jFrame = new JFrame(); jFrame.setBounds(100,100,900,720); jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON

  • JS学习笔记之贪吃蛇小游戏demo实例详解

    本文实例讲述了JS学习笔记之贪吃蛇小游戏demo实例.分享给大家供大家参考,具体如下: 最近跟着视频教程打了一个贪吃蛇, 来记录一下实现思路, 先上代码 静态页 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>贪吃蛇</title> </head> <style> *{ mar

  • Java GUI编程之贪吃蛇游戏简单实现方法【附demo源码下载】

    本文实例讲述了Java GUI编程之贪吃蛇游戏简单实现方法.分享给大家供大家参考,具体如下: 例子简单,界面简陋 请见谅 项目结构如下 Constant.jvava 代码如下: package snake; /** * * @author hjn * */ public class Constant { /** * 蛇方移动方向:左边 */ public static final int LEFT = 0; /** * 蛇方移动方向:右边 */ public static final int R

  • java实现贪吃蛇小游戏

    本文实例为大家分享了java实现贪吃蛇小游戏的具体代码,供大家参考,具体内容如下 这是MVC模式的完整Java项目,编译运行SnakeApp.java即可开始游戏. 可扩展功能: 1.积分功能:可以创建得分规则的类(模型类的一部分), 在GameController的run()方法中计算得分 2.变速功能:比如加速功能,减速功能,可以在GameController的keyPressed()方法中针对特定的按键设置每一次移动之间的时间间隔,将Thread.sleep(Settings.DEFAUL

随机推荐