用Java制作贪吃蛇小游戏

1.贪吃蛇小游戏详解

1.1引入

  1. 游戏效果展示:

  1. 涉及技能点:

  1. 游戏图形化界面编程---》GUI图形化界面编程

  2. GUI中的组件:

  1. GUI技术,不流行了!!!
  2. 已经被淘汰了,为什么还学?

(1)提起兴趣

(2)分层思想

(3)锻炼监听器的思想

(4)举一反三

1.2 将图片加载到程序中来

  1. 测试相对路径:

  1. 将图片封装:
public class Images {
    /*
    现在是面向对象的语言,面向对象的思维-->>将图片进行封装,封装为一个对象,这样在程序中才可以通过操纵这个对象来操纵图片。

     */
    //将图片的路径封装为一个对象:
   public static URL bodyURL = Images.class.getResource("/images/body.png");//"/"指相对路径
    //将图片封装为程序中一个对象:
   public static ImageIcon bodyImg = new ImageIcon(bodyURL);

    //将图片的路径封装为一个对象:
    public static URL downURL = Images.class.getResource("/images/down.png");//"/"指相对路径
    //将图片封装为程序中一个对象:
    public static ImageIcon downImg = new ImageIcon(downURL);

    //将图片的路径封装为一个对象:
    public static URL foodURL = Images.class.getResource("/images/food.png");//"/"指相对路径
    //将图片封装为程序中一个对象:
    public static ImageIcon foodImg = new ImageIcon(foodURL);

    //将图片的路径封装为一个对象:
    public static URL headerURL = Images.class.getResource("/images/header.png");//"/"指相对路径
    //将图片封装为程序中一个对象:
    public static ImageIcon headerImg = new ImageIcon(headerURL);

    //将图片的路径封装为一个对象:
    public static URL leftURL = Images.class.getResource("/images/left.png");//"/"指相对路径
    //将图片封装为程序中一个对象:
    public static ImageIcon leftImg = new ImageIcon(leftURL);

    //将图片的路径封装为一个对象:
    public static URL rightURL = Images.class.getResource("/images/right.png");//"/"指相对路径
    //将图片封装为程序中一个对象:
    public static ImageIcon rightImg = new ImageIcon(rightURL);

    //将图片的路径封装为一个对象:
    public static URL upURL = Images.class.getResource("/images/up.png");//"/"指相对路径
    //将图片封装为程序中一个对象:
    public static ImageIcon upImg = new ImageIcon(upURL);

}

1.3创建一个窗体

package com.msb.game;

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

public class StartGame {
   //这是一个人main方法,是程序的入口
   public static void main(String[] args) {
   //创建一个窗体:
       JFrame jf = new JFrame();
   //给窗体设置一个标题:
   jf.setTitle("小游戏 大逻辑 by ligaowei");
   //设置窗体弹出的坐标,对应窗体的宽高:
       //获取屏幕的长宽高:
       int width = Toolkit.getDefaultToolkit().getScreenSize().width;
       int height = Toolkit.getDefaultToolkit().getScreenSize().height;
   jf.setBounds((width-800)/2,(height-800)/2,800,800);
   //设置窗体大小不可调:
   jf.setResizable(false);
   //关闭窗口的同时 程序随之关闭
   jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
   //默认情况下窗体是隐藏效果,必须将窗体进行显现:细节--》这个显现
   jf.setVisible(true);

   }
}

1.4 创建一个面板

package com.msb.game;

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

/*
GamePanel继承了JPanel以后,才具有面板的功能,才能成为一个面板

 */
public class GamePanel extends JPanel {
   /*
   paintComponent这个方法比较特殊,这个方法就是属于图形版的main方法
   自动调用
    */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //填充背景颜色:
        this.setBackground(new Color(46, 72, 127, 255));
        //画头部图片:
        /*
        paintIcon四个参数:this指的是当前面板 g;指的是使用画笔 x,y对应的坐标
         */
        Images.headerImg.paintIcon(this,g,10,10);
        //调解笔的颜色:
        g.setColor(new Color(253, 253, 254));
        //画一个矩形:
        g.fillRect(10,70,770,685);

    }
}

1.5画一个静态小蛇

package com.msb.game;

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

/*
GamePanel继承了JPanel以后,才具有面板的功能,才能成为一个面板

 */
public class GamePanel extends JPanel {
    //蛇的长度:
    int length;
    //一个数组,专门储存蛇的X的坐标
    int[] snakeX = new int [200];
    //一个数组,专门储存蛇的y的坐标
    int[] snakeY = new int[200];

    public void init(){
        //初始化蛇的长度:
        length = 3;
        //初始化蛇头坐标:
        snakeX[0] = 175;
        snakeY[0] = 275;
        //初始化第一节身子坐标:
        snakeX[1] = 150;
        snakeY[1] = 275;
        //初始化第二节身子坐标:
        snakeX[2] = 125;
        snakeY[2] = 275;
    }
    public GamePanel(){
        init();
    }
    /*
   paintComponent这个方法比较特殊,这个方法就是属于图形版的main方法
   自动调用
    */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //填充背景颜色:
        this.setBackground(new Color(46, 72, 127, 255));
        //画头部图片:
        /*
        paintIcon四个参数:this指的是当前面板 g;指的是使用画笔 x,y对应的坐标
         */
        Images.headerImg.paintIcon(this,g,10,10);
        //调解笔的颜色:
        g.setColor(new Color(253, 253, 254));
        //画一个矩形:
        g.fillRect(10,70,770,685);

        //画小蛇:
        //画蛇头:
        Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        /*//画第一节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);
        //画第二节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);*/
        //优化为循环画蛇的身子:
        for (int i = 1; i<length;i++){
            Images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);
        }

    }
}

1.6 将蛇头按照行走方向改变

package com.msb.game;

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

/*
GamePanel继承了JPanel以后,才具有面板的功能,才能成为一个面板

 */
public class GamePanel extends JPanel {
    //蛇的长度:
    int length;
    //一个数组,专门储存蛇的X的坐标
    int[] snakeX = new int [200];
    //一个数组,专门储存蛇的y的坐标
    int[] snakeY = new int[200];
    //定义蛇的行走方向:
    String direction;

    public void init(){
        //初始化蛇的长度:
        length = 3;
        //初始化蛇头坐标:
        snakeX[0] = 175;
        snakeY[0] = 275;
        //初始化第一节身子坐标:
        snakeX[1] = 150;
        snakeY[1] = 275;
        //初始化第二节身子坐标:
        snakeX[2] = 125;
        snakeY[2] = 275;
        //初始化蛇头的方向:
        direction = "R";//U D L R
    }
    public GamePanel(){
        init();
    }
    /*
   paintComponent这个方法比较特殊,这个方法就是属于图形版的main方法
   自动调用
    */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //填充背景颜色:
        this.setBackground(new Color(46, 72, 127, 255));
        //画头部图片:
        /*
        paintIcon四个参数:this指的是当前面板 g;指的是使用画笔 x,y对应的坐标
         */
        Images.headerImg.paintIcon(this,g,10,10);
        //调解笔的颜色:
        g.setColor(new Color(253, 253, 254));
        //画一个矩形:
        g.fillRect(10,70,770,685);

        //画小蛇:
        //画蛇头:
        if ("R".equals(direction)){
            Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("L".equals(direction)){
            Images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("U".equals(direction)){
            Images.upImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("D".equals(direction)){
            Images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        /*//画第一节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);
        //画第二节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);*/
        //优化为循环画蛇的身子:
        for (int i = 1; i<length;i++){
            Images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);
        }

    }
}

1.7 加入监听,空格来控制游戏是否开始

package com.msb.game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

/*
GamePanel继承了JPanel以后,才具有面板的功能,才能成为一个面板

 */
public class GamePanel extends JPanel {
    //蛇的长度:
    int length;
    //一个数组,专门储存蛇的X的坐标
    int[] snakeX = new int [200];
    //一个数组,专门储存蛇的y的坐标
    int[] snakeY = new int[200];
    //游戏只有两个状态,开始,暂停:
    boolean isStart = false;//默认游戏是暂停效果
    //定义蛇的行走方向:
    String direction;

    public void init(){
        //初始化蛇的长度:
        length = 3;
        //初始化蛇头坐标:
        snakeX[0] = 175;
        snakeY[0] = 275;
        //初始化第一节身子坐标:
        snakeX[1] = 150;
        snakeY[1] = 275;
        //初始化第二节身子坐标:
        snakeX[2] = 125;
        snakeY[2] = 275;
        //初始化蛇头的方向:
        direction = "R";//U D L R
    }
    public GamePanel(){
        init();
        //将焦点定位在当前操作的面板上:
        this.setFocusable(true);
        //加入监听:
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {//监听键盘按键的按键操作
                super.keyPressed(e);
                int KeyCode = e.getKeyCode();
                System.out.println(KeyCode);
                if (KeyCode == 32){
                    isStart = !isStart;
                    repaint(); //重绘
                }
            }
        });

    }
    /*
   paintComponent这个方法比较特殊,这个方法就是属于图形版的main方法
   自动调用
    */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //填充背景颜色:
        this.setBackground(new Color(46, 72, 127, 255));
        //画头部图片:
        /*
        paintIcon四个参数:this指的是当前面板 g;指的是使用画笔 x,y对应的坐标
         */
        Images.headerImg.paintIcon(this,g,10,10);
        //调解笔的颜色:
        g.setColor(new Color(253, 253, 254));
        //画一个矩形:
        g.fillRect(10,70,770,685);

        //画小蛇:
        //画蛇头:
        if ("R".equals(direction)){
            Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("L".equals(direction)){
            Images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("U".equals(direction)){
            Images.upImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("D".equals(direction)){
            Images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        /*//画第一节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);
        //画第二节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);*/
        //优化为循环画蛇的身子:
        for (int i = 1; i<length;i++){
            Images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);
        }
        //如果游戏暂停的,界面中间就应该有一句提示语:
        if(isStart == false){
            //画一个文字:
            g.setColor(new Color(114,98,255));
            //三个参数:字体,加粗,字号
            g.setFont(new Font("微软雅黑",Font.BOLD,40));
            //画文字:三个参数:文字内容,X轴坐标,Y轴坐标
            g.drawString("点击空格开始游戏",250,330);
        }

    }
}

1.8 使小蛇向右动起来

package com.msb.game;

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

/*
GamePanel继承了JPanel以后,才具有面板的功能,才能成为一个面板

 */
public class GamePanel extends JPanel {
    //蛇的长度:
    int length;
    //一个数组,专门储存蛇的X的坐标
    int[] snakeX = new int [200];
    //一个数组,专门储存蛇的y的坐标
    int[] snakeY = new int[200];
    //游戏只有两个状态,开始,暂停:
    boolean isStart = false;//默认游戏是暂停效果
    //加入一个定时器:
    Timer timer;
    //定义蛇的行走方向:
    String direction;

    public void init(){
        //初始化蛇的长度:
        length = 3;
        //初始化蛇头坐标:
        snakeX[0] = 175;
        snakeY[0] = 275;
        //初始化第一节身子坐标:
        snakeX[1] = 150;
        snakeY[1] = 275;
        //初始化第二节身子坐标:
        snakeX[2] = 125;
        snakeY[2] = 275;
        //初始化蛇头的方向:
        direction = "R";//U D L R
    }
    public GamePanel(){
        init();
        //将焦点定位在当前操作的面板上:
        this.setFocusable(true);
        //加入监听:
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {//监听键盘按键的按键操作
                super.keyPressed(e);
                int KeyCode = e.getKeyCode();
                System.out.println(KeyCode);
                if (KeyCode == 32){
                    isStart = !isStart;
                    repaint(); //重绘
                }
            }
        });
        //对定时器进行初始化动作:
        timer = new Timer(100, new AbstractAction() {
            @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] += 25;
                    //防止蛇超出边界:
                    if(snakeX[0]>750){
                        snakeX[0] = 25;
                    }
                    repaint();//重绘

                }

            }
        });
        //定时器必须要启动:
        timer.start();


    }
    /*
   paintComponent这个方法比较特殊,这个方法就是属于图形版的main方法
   自动调用
    */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //填充背景颜色:
        this.setBackground(new Color(46, 72, 127, 255));
        //画头部图片:
        /*
        paintIcon四个参数:this指的是当前面板 g;指的是使用画笔 x,y对应的坐标
         */
        Images.headerImg.paintIcon(this,g,10,10);
        //调解笔的颜色:
        g.setColor(new Color(253, 253, 254));
        //画一个矩形:
        g.fillRect(10,70,770,685);

        //画小蛇:
        //画蛇头:
        if ("R".equals(direction)){
            Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("L".equals(direction)){
            Images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("U".equals(direction)){
            Images.upImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("D".equals(direction)){
            Images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        /*//画第一节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);
        //画第二节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);*/
        //优化为循环画蛇的身子:
        for (int i = 1; i<length;i++){
            Images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);
        }
        //如果游戏暂停的,界面中间就应该有一句提示语:
        if(isStart == false){
            //画一个文字:
            g.setColor(new Color(114,98,255));
            //三个参数:字体,加粗,字号
            g.setFont(new Font("微软雅黑",Font.BOLD,40));
            //画文字:三个参数:文字内容,X轴坐标,Y轴坐标
            g.drawString("点击空格开始游戏",250,330);
        }

    }
}

1.9小蛇上下左右移动并画豆豆,吃豆豆

package com.msb.game;

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

/*
GamePanel继承了JPanel以后,才具有面板的功能,才能成为一个面板

 */
public class GamePanel extends JPanel {
    //蛇的长度:
    int length;
    //一个数组,专门储存蛇的X的坐标
    int[] snakeX = new int [200];
    //一个数组,专门储存蛇的y的坐标
    int[] snakeY = new int[200];
    //游戏只有两个状态,开始,暂停:
    boolean isStart = false;//默认游戏是暂停效果
    //加入一个定时器:
    Timer timer;
    //定义蛇的行走方向:
    String direction;
    //定义食物的X,Y轴坐标:
    int foodX;
    int foodY;

    public void init(){
        //初始化蛇的长度:
        length = 3;
        //初始化蛇头坐标:
        snakeX[0] = 175;
        snakeY[0] = 275;
        //初始化第一节身子坐标:
        snakeX[1] = 150;
        snakeY[1] = 275;
        //初始化第二节身子坐标:
        snakeX[2] = 125;
        snakeY[2] = 275;
        //初始化蛇头的方向:
        direction = "R";//U D L R
        //初始化食物的坐标:
        foodX = 300;
        foodY = 200;
    }
    public GamePanel(){
        init();
        //将焦点定位在当前操作的面板上:
        this.setFocusable(true);
        //加入监听:
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {//监听键盘按键的按键操作
                super.keyPressed(e);
                int KeyCode = e.getKeyCode();
                System.out.println(KeyCode);
                if (KeyCode == KeyEvent.VK_SPACE){//监听空格
                    isStart = !isStart;
                    repaint(); //重绘
                }
                //监听向上箭头:
                if (KeyCode == KeyEvent.VK_UP){//监听空格
                    direction = "U";
                }
                //监听向下箭头:
                if (KeyCode == KeyEvent.VK_DOWN){//监听空格
                    direction = "D";
                }
                //监听向左箭头:
                if (KeyCode == KeyEvent.VK_LEFT){//监听空格
                    direction = "L";
                }
                //监听向右箭头:
                if (KeyCode == KeyEvent.VK_RIGHT){//监听空格
                    direction = "R";
                }
            }
        });
        //对定时器进行初始化动作:
        timer = new Timer(100, new AbstractAction() {
            @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 ("R".equals(direction)){
                        snakeX[0] += 25;
                    }
                    if ("L".equals(direction)){
                        snakeX[0] -= 25;
                    }
                    if ("U".equals(direction)){
                        snakeY[0] -= 25;
                    }
                    if ("D".equals(direction)){
                        snakeY[0] += 25;
                    }
                    //防止蛇超出边界:
                    if(snakeX[0]>750){
                        snakeX[0] = 25;
                    }
                    if(snakeX[0]<25){
                        snakeX[0] = 750;
                    }
                    if(snakeY[0]<100){
                        snakeY[0] = 725;
                    }
                    if(snakeY[0]>725){
                        snakeY[0] = 100;
                    }
                    //检测碰撞的动作:
                    if(snakeX[0] == foodX&&snakeY[0]== foodY){
                        //蛇的长度加1:
                        length++;
                        //食物坐标改变:随机生成坐标--》细节:坐标必须是25的倍数
                        /*
                        [25,750]->[1,30]*25
                        [1,30]
                        Math.random() ->[0.0,1.0)
                        Math.random()*30 -> [0.0,30.0)
                        (int)(Math.random()*30) -> [0,29]
                        (int)(Math.random()*30)+1 -> [1,29]
                         */
                        foodX =((int)(Math.random()*30)+1)*25 ;//[25,750]
                        /*
                        [100,725] -> [4,29]*25
                        [4,29] -> [0,25]+4
                        [0,25]
                        new Random().nextInt(26) -> [0,26) -> [0,25]
                         */
                        foodY = (new Random().nextInt(26)+4)*25;//[100,725]
                    }
                    repaint();//重绘

                }

            }
        });
        //定时器必须要启动:
        timer.start();


    }
    /*
   paintComponent这个方法比较特殊,这个方法就是属于图形版的main方法
   自动调用
    */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //填充背景颜色:
        this.setBackground(new Color(46, 72, 127, 255));
        //画头部图片:
        /*
        paintIcon四个参数:this指的是当前面板 g;指的是使用画笔 x,y对应的坐标
         */
        Images.headerImg.paintIcon(this,g,10,10);
        //调解笔的颜色:
        g.setColor(new Color(253, 253, 254));
        //画一个矩形:
        g.fillRect(10,70,770,685);

        //画小蛇:
        //画蛇头:
        if ("R".equals(direction)){
            Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("L".equals(direction)){
            Images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("U".equals(direction)){
            Images.upImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if ("D".equals(direction)){
            Images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        /*//画第一节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);
        //画第二节身子;
        Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);*/
        //优化为循环画蛇的身子:
        for (int i = 1; i<length;i++){
            Images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);
        }
        //如果游戏暂停的,界面中间就应该有一句提示语:
        if(isStart == false){
            //画一个文字:
            g.setColor(new Color(114,98,255));
            //三个参数:字体,加粗,字号
            g.setFont(new Font("微软雅黑",Font.BOLD,40));
            //画文字:三个参数:文字内容,X轴坐标,Y轴坐标
            g.drawString("点击空格开始游戏",250,330);
        }
        //画食物:
        Images.foodImg.paintIcon(this,g,foodX,foodY);

    }
}

1.10画积分

package com.msb.game;import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.util.Random;/*GamePanel继承了JPanel以后,才具有面板的功能,才能成为一个面板 */public class GamePanel extends JPanel {    //蛇的长度:    int length;    //一个数组,专门储存蛇的X的坐标    int[] snakeX = new int [200];    //一个数组,专门储存蛇的y的坐标    int[] snakeY = new int[200];    //游戏只有两个状态,开始,暂停:    boolean isStart = false;//默认游戏是暂停效果    //加入一个定时器:    Timer timer;    //定义蛇的行走方向:    String direction;    //定义食物的X,Y轴坐标:    int foodX;    int foodY;    //定义一个积分:    int score;    public void init(){        //初始化蛇的长度:        length = 3;        //初始化蛇头坐标:        snakeX[0] = 175;        snakeY[0] = 275;        //初始化第一节身子坐标:        snakeX[1] = 150;        snakeY[1] = 275;        //初始化第二节身子坐标:        snakeX[2] = 125;        snakeY[2] = 275;        //初始化蛇头的方向:        direction = "R";//U D L R        //初始化食物的坐标:        foodX = 300;        foodY = 200;    }    public GamePanel(){        init();        //将焦点定位在当前操作的面板上:        this.setFocusable(true);        //加入监听:        this.addKeyListener(new KeyAdapter() {            @Override            public void keyPressed(KeyEvent e) {//监听键盘按键的按键操作                super.keyPressed(e);                int KeyCode = e.getKeyCode();                System.out.println(KeyCode);                if (KeyCode == KeyEvent.VK_SPACE){//监听空格                    isStart = !isStart;                    repaint(); //重绘                }                //监听向上箭头:                if (KeyCode == KeyEvent.VK_UP){//监听空格                    direction = "U";                }                //监听向下箭头:                if (KeyCode == KeyEvent.VK_DOWN){//监听空格                    direction = "D";                }                //监听向左箭头:                if (KeyCode == KeyEvent.VK_LEFT){//监听空格                    direction = "L";                }                //监听向右箭头:                if (KeyCode == KeyEvent.VK_RIGHT){//监听空格                    direction = "R";                }            }        });        //对定时器进行初始化动作:        timer = new Timer(100, new AbstractAction() {            @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 ("R".equals(direction)){                        snakeX[0] += 25;                    }                    if ("L".equals(direction)){                        snakeX[0] -= 25;                    }                    if ("U".equals(direction)){                        snakeY[0] -= 25;                    }                    if ("D".equals(direction)){                        snakeY[0] += 25;                    }                    //防止蛇超出边界:                    if(snakeX[0]>750){                        snakeX[0] = 25;                    }                    if(snakeX[0]<25){                        snakeX[0] = 750;                    }                    if(snakeY[0]<100){                        snakeY[0] = 725;                    }                    if(snakeY[0]>725){                        snakeY[0] = 100;                    }                    //检测碰撞的动作:                    if(snakeX[0] == foodX&&snakeY[0]== foodY){                        //蛇的长度加1:                        length++;                        //食物坐标改变:随机生成坐标--》细节:坐标必须是25的倍数                        /*                        [25,750]->[1,30]*25                        [1,30]                        Math.random() ->[0.0,1.0)                        Math.random()*30 -> [0.0,30.0)                        (int)(Math.random()*30) -> [0,29]                        (int)(Math.random()*30)+1 -> [1,29]                         */                        foodX =((int)(Math.random()*30)+1)*25 ;//[25,750]                        /*                        [100,725] -> [4,29]*25                        [4,29] -> [0,25]+4                        [0,25]                        new Random().nextInt(26) -> [0,26) -> [0,25]                         */                        foodY = (new Random().nextInt(26)+4)*25;//[100,725]                        //吃上食物后 积分加10分:                        score += 10;                    }                    repaint();//重绘                }            }        });        //定时器必须要启动:        timer.start();    }    /*   paintComponent这个方法比较特殊,这个方法就是属于图形版的main方法   自动调用    */    @Override    public void paintComponent(Graphics g) {        super.paintComponent(g);        //填充背景颜色:        this.setBackground(new Color(46, 72, 127, 255));        //画头部图片:        /*        paintIcon四个参数:this指的是当前面板 g;指的是使用画笔 x,y对应的坐标         */        Images.headerImg.paintIcon(this,g,10,10);        //调解笔的颜色:        g.setColor(new Color(253, 253, 254));        //画一个矩形:        g.fillRect(10,70,770,685);        //画小蛇:        //画蛇头:        if ("R".equals(direction)){            Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);        }        if ("L".equals(direction)){            Images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);        }        if ("U".equals(direction)){            Images.upImg.paintIcon(this,g,snakeX[0],snakeY[0]);        }        if ("D".equals(direction)){            Images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]);        }        /*//画第一节身子;        Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);        //画第二节身子;        Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);*/        //优化为循环画蛇的身子:        for (int i = 1; i<length;i++){            Images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);        }        //如果游戏暂停的,界面中间就应该有一句提示语:        if(isStart == false){            //画一个文字:            g.setColor(new Color(114,98,255));            //三个参数:字体,加粗,字号            g.setFont(new Font("微软雅黑",Font.BOLD,40));            //画文字:三个参数:文字内容,X轴坐标,Y轴坐标            g.drawString("点击空格开始游戏",250,330);        }        //画食物:        Images.foodImg.paintIcon(this,g,foodX,foodY);        //画积分:        g.setColor(new Color(114,98,248));        g.setFont(new Font("微软雅黑",Font.BOLD,35));        //画文字:三个参数:文字内容,X轴坐标,Y轴坐标        g.drawString("积分"+score,670,50);    }}

1.11死亡判定

package com.msb.game;import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.util.Random;/*GamePanel继承了JPanel以后,才具有面板的功能,才能成为一个面板 */public class GamePanel extends JPanel {    //蛇的长度:    int length;    //一个数组,专门储存蛇的X的坐标    int[] snakeX = new int [200];    //一个数组,专门储存蛇的y的坐标    int[] snakeY = new int[200];    //游戏只有两个状态,开始,暂停:    boolean isStart = false;//默认游戏是暂停效果    //加入一个定时器:    Timer timer;    //定义蛇的行走方向:    String direction;    //定义食物的X,Y轴坐标:    int foodX;    int foodY;    //定义一个积分:    int score;    //加入一个变量,判断小蛇的死亡状态:    boolean isDie = false; //默认情况下小蛇没有死亡    public void init(){        //初始化蛇的长度:        length = 3;        //初始化蛇头坐标:        snakeX[0] = 175;        snakeY[0] = 275;        //初始化第一节身子坐标:        snakeX[1] = 150;        snakeY[1] = 275;        //初始化第二节身子坐标:        snakeX[2] = 125;        snakeY[2] = 275;        //初始化蛇头的方向:        direction = "R";//U D L R        //初始化食物的坐标:        foodX = 300;        foodY = 200;    }    public GamePanel(){        init();        //将焦点定位在当前操作的面板上:        this.setFocusable(true);        //加入监听:        this.addKeyListener(new KeyAdapter() {            @Override            public void keyPressed(KeyEvent e) {//监听键盘按键的按键操作                super.keyPressed(e);                int KeyCode = e.getKeyCode();                System.out.println(KeyCode);                if (KeyCode == KeyEvent.VK_SPACE){//监听空格                    if(isDie){                        //全部恢复到初始化状态                        init();                        isDie = false;                    }else {//小蛇没有死亡的情况下:                        isStart = !isStart;                        repaint(); //重绘                    }                }                //监听向上箭头:                if (KeyCode == KeyEvent.VK_UP){//监听上箭头                    direction = "U";                }                //监听向下箭头:                if (KeyCode == KeyEvent.VK_DOWN){//监听下箭头                    direction = "D";                }                //监听向左箭头:                if (KeyCode == KeyEvent.VK_LEFT){//监听左箭头                    direction = "L";                }                //监听向右箭头:                if (KeyCode == KeyEvent.VK_RIGHT){//监听右箭头                    direction = "R";                }            }        });        //对定时器进行初始化动作:        timer = new Timer(100, new AbstractAction() {            @Override            public void actionPerformed(ActionEvent e) {                if(isStart&&isDie == false){//游戏是开始状态的时候,蛇才动:                    //后一节身子走到前一节身子的位置上:                    for (int i = length-1;i>0;i--){                        snakeX[i] = snakeX[i-1];                        snakeY[i] = snakeY[i-1];                    }                    //动头                    if ("R".equals(direction)){                        snakeX[0] += 25;                    }                    if ("L".equals(direction)){                        snakeX[0] -= 25;                    }                    if ("U".equals(direction)){                        snakeY[0] -= 25;                    }                    if ("D".equals(direction)){                        snakeY[0] += 25;                    }                    //防止蛇超出边界:                    if(snakeX[0]>750){                        snakeX[0] = 25;                    }                    if(snakeX[0]<25){                        snakeX[0] = 750;                    }                    if(snakeY[0]<100){                        snakeY[0] = 725;                    }                    if(snakeY[0]>725){                        snakeY[0] = 100;                    }                    //检测碰撞的动作:                    if(snakeX[0] == foodX&&snakeY[0]== foodY){                        //蛇的长度加1:                        length++;                        //食物坐标改变:随机生成坐标--》细节:坐标必须是25的倍数                        /*                        [25,750]->[1,30]*25                        [1,30]                        Math.random() ->[0.0,1.0)                        Math.random()*30 -> [0.0,30.0)                        (int)(Math.random()*30) -> [0,29]                        (int)(Math.random()*30)+1 -> [1,29]                         */                        foodX =((int)(Math.random()*30)+1)*25 ;//[25,750]                        /*                        [100,725] -> [4,29]*25                        [4,29] -> [0,25]+4                        [0,25]                        new Random().nextInt(26) -> [0,26) -> [0,25]                         */                        foodY = (new Random().nextInt(26)+4)*25;//[100,725]                        //吃上食物后 积分加10分:                        score += 10;                    }                    //死亡判定:                    for (int i = 1;i<length;i++){                        if (snakeX[0]==snakeX[i]&&snakeY[0]==snakeY[i]){                            //将死亡 状态改为:true                            isDie = true;                        }                    }                    repaint();//重绘                }            }        });        //定时器必须要启动:        timer.start();    }    /*   paintComponent这个方法比较特殊,这个方法就是属于图形版的main方法   自动调用    */    @Override    public void paintComponent(Graphics g) {        super.paintComponent(g);        //填充背景颜色:        this.setBackground(new Color(46, 72, 127, 255));        //画头部图片:        /*        paintIcon四个参数:this指的是当前面板 g;指的是使用画笔 x,y对应的坐标         */        Images.headerImg.paintIcon(this,g,10,10);        //调解笔的颜色:        g.setColor(new Color(253, 253, 254));        //画一个矩形:        g.fillRect(10,70,770,685);        //画小蛇:        //画蛇头:        if ("R".equals(direction)){            Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);        }        if ("L".equals(direction)){            Images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);        }        if ("U".equals(direction)){            Images.upImg.paintIcon(this,g,snakeX[0],snakeY[0]);        }        if ("D".equals(direction)){            Images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]);        }        /*//画第一节身子;        Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);        //画第二节身子;        Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);*/        //优化为循环画蛇的身子:        for (int i = 1; i<length;i++){            Images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);        }        //如果游戏暂停的,界面中间就应该有一句提示语:        if(isStart == false){            //画一个文字:            g.setColor(new Color(114,98,255));            //三个参数:字体,加粗,字号            g.setFont(new Font("微软雅黑",Font.BOLD,40));            //画文字:三个参数:文字内容,X轴坐标,Y轴坐标            g.drawString("点击空格开始游戏",250,330);        }        //画食物:        Images.foodImg.paintIcon(this,g,foodX,foodY);        //画积分:        g.setColor(new Color(114,98,248));        g.setFont(new Font("微软雅黑",Font.BOLD,35));        //画文字:三个参数:文字内容,X轴坐标,Y轴坐标        g.drawString("积分"+score,670,50);        //画入死亡状态:        if(isDie){            g.setColor(new Color(114,98,255));            //三个参数:字体,加粗,字号            g.setFont(new Font("微软雅黑",Font.BOLD,20));            //画文字:三个参数:文字内容,X轴坐标,Y轴坐标            g.drawString("小蛇死亡,游戏停止,按下空格重新开始游戏",200,330);        }    }}

1.12 如何打包

posted @ 2021-09-25 20:52  憨憨伟  阅读(472)  评论(0)    收藏  举报