前言:

本文内容:贪吃蛇小游戏制作

推荐免费JavaGUI入门视频:【狂神说Java】GUI编程入门到游戏实战_哔哩哔哩_bilibili

JavaGUI笔记代码下载地址:

蓝奏云:下载地址 密码:joker

百度云:下载地址 提取码:fxcj

贪吃蛇界面绘制

  • StartGame类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.jokerdig.snake;

    import javax.swing.*;

    /**
    * @author Joker大雄
    * @data 2021/8/19 - 11:04
    **/
    //游戏主启动类
    public class StartGame {
    public static void main(String[] args) {
    JFrame frame = new JFrame("贪吃蛇-jokerdig.com");

    frame.setResizable(false);//窗口大小不可变
    frame.setBounds(10,10,900,725);
    frame.setVisible(true);//显示界面
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //可关闭
    //内容在面板中
    frame.add(new GamePanel());
    }
    }
  • GmaePanel类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package com.jokerdig.snake;

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

    /**
    * @author Joker大雄
    * @data 2021/8/19 - 11:10
    **/
    //游戏面板
    public class GamePanel extends JPanel {

    //绘制面板,游戏中所有东西都用这支画笔
    @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);
    }
    }
  • Data类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    package com.jokerdig.snake;

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

    /**
    * @author Joker大雄
    * @data 2021/8/19 - 11:45
    **/
    //数据中心
    public class Data {
    //相对路径:xx.jpg
    //绝对路径:/
    public static URL headerURL = Data.class.getResource("static/header.png");
    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 URL bodyURL = Data.class.getResource("static/body.png");
    public static URL foodURL = Data.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);
    }

绘制静态的小蛇

  • GamePanel类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    package com.jokerdig.snake;

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

    /**
    * @author Joker大雄
    * @data 2021/8/19 - 11:10
    **/
    //游戏面板
    public class GamePanel extends JPanel {
    //定义蛇的数据结构
    int length;//🐍长度
    int[] snakeX = new int[600];//蛇的X坐标
    int[] snakeY = new int[500];//蛇的Y坐标
    //方向
    String direction;//初始方向向右
    //游戏当前的状态:开始,停止
    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;//第二个身体坐标
    direction ="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);
    //把小蛇画上去,通过方向来判断
    if(direction.equals("R")){
    Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);//头初始化向右
    }else if(direction.equals("L")){
    Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向左
    }else if(direction.equals("U")){
    Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向上
    }else if(direction.equals("D")){
    Data.down.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向下
    }
    //身体坐标
    for (int i = 1; i < length; i++) {
    Data.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,350);
    }
    }
    }

让小蛇动起来

  • GamePanel类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    package com.jokerdig.snake;

    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;

    /**
    * @author Joker大雄
    * @data 2021/8/19 - 11:10
    **/
    //游戏面板
    //实现 KeyListener 接口,重写接口方法
    //实现 ActionListener(定时器)接口,重写接口方法
    public class GamePanel extends JPanel implements KeyListener, ActionListener {
    //定义蛇的数据结构
    int length;//🐍长度
    int[] snakeX = new int[600];//蛇的X坐标
    int[] snakeY = new int[500];//蛇的Y坐标
    //方向
    String direction;//初始方向向右
    //游戏当前的状态:开始,停止
    boolean isStart = false;//默认不开始
    //定时器,300ms = 1s执行一次
    Timer timer=new Timer(300,this);

    //构造器
    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;//第二个身体坐标
    direction ="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);
    //把小蛇画上去,通过方向来判断
    if(direction.equals("R")){
    Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);//头初始化向右
    }else if(direction.equals("L")){
    Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向左
    }else if(direction.equals("U")){
    Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向上
    }else if(direction.equals("D")){
    Data.down.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向下
    }
    //身体坐标
    for (int i = 1; i < length; i++) {
    Data.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,350);
    }
    }

    //键盘监听事件
    @Override
    public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();//获得键盘按键
    if(keyCode == KeyEvent.VK_SPACE){
    isStart = !isStart;//取反
    repaint();//重新绘制
    }
    }
    //定时器监听
    @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];
    }
    snakeX[0]=snakeX[0]+25;
    //边界判断
    if(snakeX[0]>850){
    snakeX[0]=25;
    }

    repaint();//重绘
    }
    timer.start();//定时器开始
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
    }

键盘控制小蛇移动

  • GamePanel

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    package com.jokerdig.snake;

    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;

    /**
    * @author Joker大雄
    * @data 2021/8/19 - 11:10
    **/
    //游戏面板
    //实现 KeyListener 接口,重写接口方法
    //实现 ActionListener(定时器)接口,重写接口方法
    public class GamePanel extends JPanel implements KeyListener, ActionListener {
    //定义蛇的数据结构
    int length;//🐍长度
    int[] snakeX = new int[600];//蛇的X坐标
    int[] snakeY = new int[500];//蛇的Y坐标
    //方向
    String direction;//初始方向向右
    //游戏当前的状态:开始,停止
    boolean isStart = false;//默认不开始
    //定时器,300ms = 1s执行一次
    Timer timer=new Timer(300,this);

    //构造器
    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;//第二个身体坐标
    direction ="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);
    //把小蛇画上去,通过方向来判断
    if(direction.equals("R")){
    Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);//头初始化向右
    }else if(direction.equals("L")){
    Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向左
    }else if(direction.equals("U")){
    Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向上
    }else if(direction.equals("D")){
    Data.down.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向下
    }
    //身体坐标
    for (int i = 1; i < length; i++) {
    Data.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,350);
    }
    }

    //键盘监听事件
    @Override
    public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();//获得键盘按键
    if(keyCode == KeyEvent.VK_SPACE){
    isStart = !isStart;//取反
    repaint();//重新绘制
    }
    //控制小蛇上下左右移动,且小蛇不能直接回头
    if((keyCode == KeyEvent.VK_UP||keyCode == KeyEvent.VK_W)&&!direction.equals("D")){
    direction="U";
    }else if((keyCode == KeyEvent.VK_DOWN||keyCode == KeyEvent.VK_S)&&!direction.equals("U")){
    direction="D";
    }else if((keyCode == KeyEvent.VK_LEFT||keyCode == KeyEvent.VK_A)&&!direction.equals("R")){
    direction="L";
    }else if((keyCode == KeyEvent.VK_RIGHT||keyCode == KeyEvent.VK_D)&&!direction.equals("L")){
    direction="R";
    }
    }
    //定时器监听
    @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];
    }
    //头控制身体移动
    if (direction.equals("R")) {
    snakeX[0] = snakeX[0] + 25;
    //边界判断
    if (snakeX[0] > 850) {
    snakeX[0] = 25;
    }
    } else if (direction.equals("L")) {
    snakeX[0] = snakeX[0] - 25;
    //边界判断
    if (snakeX[0] < 25) {
    snakeX[0] = 850;
    }
    } else if (direction.equals("U")) {
    snakeY[0] = snakeY[0] - 25;
    //边界判断
    if (snakeY[0] < 75) {
    snakeY[0] = 650;
    }
    } else if (direction.equals("D")){
    snakeY[0] = snakeY[0] + 25;
    //边界判断
    if (snakeY[0] > 650) {
    snakeY[0] = 75;
    }
    }
    repaint();//重绘
    }
    timer.start();//定时器开始
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
    }

小蛇吃食物长大

  • GamePanel

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    package com.jokerdig.snake;

    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 Joker大雄
    * @data 2021/8/19 - 11:10
    **/
    //游戏面板
    //实现 KeyListener 接口,重写接口方法
    //实现 ActionListener(定时器)接口,重写接口方法
    public class GamePanel extends JPanel implements KeyListener, ActionListener {
    //定义蛇的数据结构
    int length;//🐍长度
    int[] snakeX = new int[600];//蛇的X坐标
    int[] snakeY = new int[500];//蛇的Y坐标
    //方向
    String direction;//初始方向向右
    //食物的坐标
    int foodX;
    int foodY;
    Random random = new Random();

    //游戏当前的状态:开始,停止
    boolean isStart = false;//默认不开始
    //定时器,200ms = 1s执行一次
    Timer timer=new Timer(200,this);

    //构造器
    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;//第二个身体坐标
    direction ="R";//初始方向向右
    //随机食物坐标
    foodX=25+25*random.nextInt(34);
    foodY=75+25*random.nextInt(24);

    }

    //绘制面板,游戏中所有东西都用这支画笔
    @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);
    //把小蛇画上去,通过方向来判断
    if(direction.equals("R")){
    Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);//头初始化向右
    }else if(direction.equals("L")){
    Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向左
    }else if(direction.equals("U")){
    Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向上
    }else if(direction.equals("D")){
    Data.down.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向下
    }
    //身体坐标
    for (int i = 1; i < length; i++) {
    Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);//身体坐标
    }
    Data.food.paintIcon(this,g,foodX,foodY);
    //游戏状态
    if(isStart==false){
    g.setColor(Color.WHITE);
    g.setFont(new Font("微软雅黑",Font.BOLD,40));//设置字体
    g.drawString("按下空格开始游戏",300,350);
    }
    }

    //键盘监听事件
    @Override
    public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();//获得键盘按键
    if(keyCode == KeyEvent.VK_SPACE){
    isStart = !isStart;//取反
    repaint();//重新绘制
    }
    //控制小蛇上下左右移动,且小蛇不能直接回头
    if((keyCode == KeyEvent.VK_UP||keyCode == KeyEvent.VK_W)&&!direction.equals("D")){
    direction="U";
    }else if((keyCode == KeyEvent.VK_DOWN||keyCode == KeyEvent.VK_S)&&!direction.equals("U")){
    direction="D";
    }else if((keyCode == KeyEvent.VK_LEFT||keyCode == KeyEvent.VK_A)&&!direction.equals("R")){
    direction="L";
    }else if((keyCode == KeyEvent.VK_RIGHT||keyCode == KeyEvent.VK_D)&&!direction.equals("L")){
    direction="R";
    }
    }
    //定时器监听
    @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];
    }
    //头控制身体移动
    if (direction.equals("R")) {
    snakeX[0] = snakeX[0] + 25;
    //边界判断
    if (snakeX[0] > 850) {
    snakeX[0] = 25;
    }
    } else if (direction.equals("L")) {
    snakeX[0] = snakeX[0] - 25;
    //边界判断
    if (snakeX[0] < 25) {
    snakeX[0] = 850;
    }
    } else if (direction.equals("U")) {
    snakeY[0] = snakeY[0] - 25;
    //边界判断
    if (snakeY[0] < 75) {
    snakeY[0] = 650;
    }
    } else if (direction.equals("D")){
    snakeY[0] = snakeY[0] + 25;
    //边界判断
    if (snakeY[0] > 650) {
    snakeY[0] = 75;
    }
    }
    //吃食物
    if(snakeX[0]==foodX && snakeY[0]==foodY){
    length++;//身体长度+1
    //再次随机生成食物
    foodX=25+25*random.nextInt(34);
    foodY=75+25*random.nextInt(24);
    }
    repaint();//重绘
    }
    timer.start();//定时器开始
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
    }

失败判定,积分系统

  • GamePanel

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    package com.jokerdig.snake;

    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 Joker大雄
    * @data 2021/8/19 - 11:10
    **/
    //游戏面板
    //实现 KeyListener 接口,重写接口方法
    //实现 ActionListener(定时器)接口,重写接口方法
    public class GamePanel extends JPanel implements KeyListener, ActionListener {
    //定义蛇的数据结构
    int length;//🐍长度
    int[] snakeX = new int[600];//蛇的X坐标
    int[] snakeY = new int[500];//蛇的Y坐标
    //方向
    String direction;//初始方向向右
    //食物的坐标
    int foodX;
    int foodY;
    Random random = new Random();

    //游戏当前的状态:开始,停止
    boolean isStart = false;//默认不开始
    //失败判定
    boolean isFall = false;
    //定时器,200ms = 1s执行一次
    Timer timer=new Timer(200,this);
    //分数定义
    int score;

    //构造器
    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;//第二个身体坐标
    direction ="R";//初始方向向右
    //随机食物坐标
    foodX=25+25*random.nextInt(34);
    foodY=75+25*random.nextInt(24);
    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);
    //把小蛇画上去,通过方向来判断
    if(direction.equals("R")){
    Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);//头初始化向右
    }else if(direction.equals("L")){
    Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向左
    }else if(direction.equals("U")){
    Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向上
    }else if(direction.equals("D")){
    Data.down.paintIcon(this,g,snakeX[0],snakeY[0]);//方向向下
    }
    //绘制身体坐标
    for (int i = 1; i < length; i++) {
    Data.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,350);
    }
    //失败绘制
    if(isFall){
    g.setColor(Color.RED);
    g.setFont(new Font("微软雅黑",Font.BOLD,60));//设置字体
    g.drawString("GAME OVER",280,350);
    }
    }

    //键盘监听事件
    @Override
    public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();//获得键盘按键
    if(keyCode == KeyEvent.VK_SPACE){
    if(isFall){
    //重新开始
    isFall=false;
    init();
    }else{
    isStart = !isStart;//取反
    }
    repaint();//重新绘制
    }
    //控制小蛇上下左右移动,且小蛇不能直接回头
    if((keyCode == KeyEvent.VK_UP||keyCode == KeyEvent.VK_W)&&!direction.equals("D")){
    direction="U";
    }else if((keyCode == KeyEvent.VK_DOWN||keyCode == KeyEvent.VK_S)&&!direction.equals("U")){
    direction="D";
    }else if((keyCode == KeyEvent.VK_LEFT||keyCode == KeyEvent.VK_A)&&!direction.equals("R")){
    direction="L";
    }else if((keyCode == KeyEvent.VK_RIGHT||keyCode == KeyEvent.VK_D)&&!direction.equals("L")){
    direction="R";
    }
    }
    //定时器监听
    @Override
    public void actionPerformed(ActionEvent e) {
    if(isStart && isFall==false) { //如果游戏开始,就让小蛇动起来
    //身体移动
    for (int i = length - 1; i > 0; i--) {
    //移动,后一截移动到前一截
    snakeX[i] = snakeX[i - 1];
    snakeY[i] = snakeY[i - 1];
    }
    //头控制身体移动
    if (direction.equals("R")) {
    snakeX[0] = snakeX[0] + 25;
    //边界判断
    if (snakeX[0] > 850) {
    snakeX[0] = 25;
    }
    } else if (direction.equals("L")) {
    snakeX[0] = snakeX[0] - 25;
    //边界判断
    if (snakeX[0] < 25) {
    snakeX[0] = 850;
    }
    } else if (direction.equals("U")) {
    snakeY[0] = snakeY[0] - 25;
    //边界判断
    if (snakeY[0] < 75) {
    snakeY[0] = 650;
    }
    } else if (direction.equals("D")){
    snakeY[0] = snakeY[0] + 25;
    //边界判断
    if (snakeY[0] > 650) {
    snakeY[0] = 75;
    }
    }
    //吃食物
    if(snakeX[0]==foodX && snakeY[0]==foodY){
    length+=1;//身体长度增加
    score+=10;//分数增加
    //再次随机生成食物
    foodX=25+25*random.nextInt(34);
    foodY=75+25*random.nextInt(24);
    }
    //失败事件,撞到身体
    for (int i = 1; i < length; i++) {
    if(snakeX[0]==snakeX[i]&&snakeY[0]==snakeY[i]){
    isFall=true;
    }
    }
    repaint();//重绘
    }
    timer.start();//定时器开始
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
    }

GUI阶段回顾与总结

贪吃蛇实现思路:

  • 定义数据

  • 画到面板上

  • 监听事件

    • 键盘监听
    • 事件监听
  • 生成jar文件

    • 在CMD中输入jar cvf 生成名称.jar 文件夹名/.
    • 保证所有.class和资源文件都在该文件夹内
  • 游戏效果图

    fbgAZd.png

总结:

fblN28.png