关于本次程序用到的的技能有:数组、监听器、适配器、定时器、本次用到的Java的swing不需要记住这已经被淘汰

效果展示

java游戏编写教程 如何用java编写游戏_java游戏编写教程

窗口

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

public class DomeMain {
    public static void main(String[] args) {
        //创建一个窗体
        JFrame jf = new JFrame();
        //给窗体设置一个标题:
        jf.setTitle("贪吃蛇");
        //设置窗体弹出坐标,对应窗体的宽和高
        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(WindowConstants.EXIT_ON_CLOSE);
        //创建面板:
        GamePanel gp = new GamePanel();
        //将面板放入窗体
        jf.add(gp);
        //默认情况下窗体是隐藏效果,必须将窗体进行显现:细节-->这个显现方法最好放在最后
        jf.setVisible(true);
    }
}

把图片抽象化

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

//本类专门用来获取游戏中所涉及的图片

public class Images {
    //面向对象的语言,面向对象的思维-->将图片进行封装,封装成为一个对象,这样在程序中才可以通过操作这个对象来操做图片
    //将图片封装为一个对象
    public  static URL bodyURL = Images.class.getResource("/images/body.jpg");
    //将图片封装为程序的一个对象
    public static ImageIcon bodyImg = new ImageIcon(bodyURL);

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

    public  static URL headURL = Images.class.getResource("/images/head.jpg");
    //将图片封装为程序的一个对象
    public static ImageIcon headImg = new ImageIcon(headURL);//将图片封装为一个对象

    public  static URL downURL = Images.class.getResource("/images/head - down.jpg");
    //将图片封装为程序的一个对象
    public static ImageIcon downImg = new ImageIcon(downURL);

    //将图片封装为一个对象
    public  static URL leftURL = Images.class.getResource("/images/head - left.jpg");
    //将图片封装为程序的一个对象
    public static ImageIcon leftImg = new ImageIcon(leftURL);

    //将图片封装为一个对象
    public  static URL rightURL = Images.class.getResource("/images/head - right.jpg");
    //将图片封装为程序的一个对象
    public static ImageIcon rightImg = new ImageIcon(rightURL);

    //将图片封装为一个对象
    public  static URL titleURL = Images.class.getResource("/images/title.jpg");
    //将图片封装为程序的一个对象
    public static ImageIcon titleImg = new ImageIcon(titleURL);

}

程序的逻辑代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

//GamePanel继承了JPanel以后,才具备面板的功能,才能成为一个面板
public class GamePanel extends JPanel{//paintComponent这个方法比较特殊,这个方法就属于图形版的main方法,自动调用


    //定义两个数组
    //蛇的长度
    int lenght;
    //一个数组,专门存储蛇的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(){
        //初始化蛇的长度
        lenght = 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;
        //初始化一个积分
        score = 0;
    }



    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{//小蛇没有死亡的情况下
                        System.out.println("点击了空格");
                        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 ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {//事件监听,相当于每100ms监听一下你是否发生了一个动作具体的动作放入actionPerformed

                if (isStart&&isDie == false){//游戏是开始状态的时候,蛇才动,后一节身子走到前一节身子的位置上
                    for (int i = lenght-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]>750){
                        snakeY[0] = 100;
                    }


                    //检测碰撞操作:
                    //食物的坐标和蛇头的坐标一样是,算作碰到
                    if (snakeX[0] == foodX&&snakeY[0] == foodY){
                        //蛇的长度+1
                        lenght++;
                        //食物的坐标改变,随机生成坐标坐标必须是25的倍数
                        /*
                        [25,750] -> [1,30]*25
                        Math.random() -> [0.0,1.0)
                        Math.random()*30 -> [0.0,30.0)
                        (int)(Math.random()*30)+1 ->[1,30]
                         */
                        /*
                        [100,725] -> [4,29]*25
                        [4,29]->[0,25]+4
                        [0,25]
                        new Random().nextInt(26) -> [0,26) ->[0,25]
                         */
                        foodX = ((int)(Math.random()*30)+1)*25;//【25,750】
                        foodY = (new Random().nextInt(26)+4)*25;//【100,725】


                        //吃上食物以后 积分加十分
                        score += 10;
                    }

                    //死亡判定
                    for (int i = 1;i<lenght;i++){
                        if (snakeX[i] == snakeX[0]&&snakeY[i] == snakeY[0]){
                            //将死亡状态改为true
                            isDie = true;
                        }
                    }
                    repaint();//重绘

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



    @Override
    protected void paintChildren(Graphics g) {
        super.paintChildren(g);
        //填充背景颜色
        this.setBackground(new Color(77,255,36));
        //paintIcon四个参数:this指的是当前面板 g:指的是当前使用的画笔 x,y对应的坐标
        Images.titleImg.paintIcon(this,g,2,10);//头部图片
        //调整话笔颜色
        g.setColor(new Color(240,245,117));
        //画一个矩形
        g.fillRect(6,70,775,685);

        //画小蛇
        //蛇头朝向
        if("R".equals(direction)){
            Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }else if ("L".equals(direction)){
            Images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }else if ("U".equals(direction)){
            Images.headImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }else 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<lenght;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,300);
        }

        //画食物:
        Images.foodImg.paintIcon(this,g,foodX,foodY);

        //画积分
        g.setColor(new Color(255,3,9));//颜色
        //三个参数:字体,加粗,字号
        g.setFont(new Font("微软雅黑",Font.BOLD,20));
        //画文字:三个参数:文字内容,X轴坐标,Y轴坐标
        g.drawString(""+score,650,40);

        //画入死亡状态
        if (isDie){
            g.setColor(new Color(255,3,9));//颜色
            //三个参数:字体,加粗,字号
            g.setFont(new Font("微软雅黑",Font.BOLD,35));
            //画文字:三个参数:文字内容,X轴坐标,Y轴坐标
            g.drawString("小蛇死亡 共得分:"+score,200,200);
        }
    }
}