基于Java、swing实现的贪吃蛇游戏

1.概述

        首先要了解游戏的画面--一个画面为一帧,那怎么让画面动起来还是要靠定时器进行刷新。

这个小游戏主要需要掌握的技术要点:

      首先:面板的绘制,必须是需要一个面板来展示游戏嘛;其次:键盘输入的控制(玩游戏肯定是在键盘上操作嘛),最后:定时器的操作(看多少秒刷新一帧,让游戏动起来的关键)

      那下面的代码实现就主要围绕着三个方面来进行啦

2.代码实现

     2.1  绘制面板及画面

Step1:先绘制静态窗口,再窗口上面绘制一个游戏面板,主要的操作就在游戏面板中进行,这个类就是游戏的启动类

public class StartGame {
    public static void main(String[] args) {
        //1.绘制一个静态窗口
        JFrame frame=new JFrame("贪吃蛇游戏");
        frame.setBounds(10,10,900,720);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //2.绘制一个面板  游戏面板
        frame.add(new GamePanel());

        frame.setVisible(true);

    }

Step2:绘制游戏面板

我们先看一下效果图:可以看到将这个面板分成了三个区域,其中1就是一个图标,2部分记录了当前蛇的长度和分数,第三个部分就是主要玩游戏的地方(包括蛇的绘制、一个食物,一句话语(按下空格开始游戏))

 需要明确的是:一个画面中的某一点其实可以抽象成一个坐标来表示,所以无论是食物还是蛇我们都可以通过坐标来进行表示

先定义一些变量:(这是所有的变量定义,有些变量后面才会用到,后面再进行解释)

int length;   //蛇的长度
    int[] snakeX=new int[500];  //蛇x坐标
    int[] snakeY=new int[500];   //y坐标
    String fx; //方向
    boolean isStart=false;  //游戏是否开始
    //定时器
    Timer timer;
    int delay;  //时间

    //1.定义一个食物
    int foodX;
    int foodY;
    Random random=new Random();
    //死亡判断
    boolean isFail=false;
    //积分系统
    int score;

再初始化:

 length=3;
 snakeX[0]=100;snakeY[0]=100;
 snakeX[1]=75;snakeY[1]=100;
 snakeX[2]=50;snakeY[2]=100;
 fx="R";
 foodX=25+25*random.nextInt(34);
 foodY=75+25*random.nextInt(24);
 score=0;

再将物体画在面板上:主要是重写paintComponent()方法:

        //画头部
        Data.header.paintIcon(this,g,25,11);
        g.fillRect(25,75,850,600);
        //根据方向画头部的方向
        if(fx.equals("R")){
            Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);
            }else if(fx.equals("L")) {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        }else if(fx.equals("U")) {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        }else if(fx.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]);
        }
        //画积分
        g.setColor(Color.white);
        g.setFont(new Font("微软雅黑",Font.BOLD,20));
        g.drawString("长度:"+length,750,35);
        g.drawString("分数:"+score,750,60);

        //画食物
        Data.food.paintIcon(this,g,foodX,foodY);
        //游戏提示
        if(isStart==false){
            //画一个文字
            g.setColor(Color.white);
            g.setFont(new Font("微软雅黑",Font.BOLD,40));
            g.drawString("按下空格开始游戏",300,300);
        }
        //失败提示
        if(isFail==true){
            //画一个文字
            g.setColor(Color.red);
            g.setFont(new Font("微软雅黑",Font.BOLD,40));
            g.drawString("游戏失败 按下空格重新开始",200,300);
        }

这里蛇的头部和身体都是由一张图片组成,主要需要定义一个Data类记录这些图片:

/***
 * 图片数据
 */
public class Data {
    //头部
    public static URL headerURL = Data.class.getResource("/statics/header.png");
    public static ImageIcon header = new ImageIcon(headerURL);
    //贪吃蛇 头部上下左右
    public static URL upURL =  Data.class.getResource("/statics/up.png");
    public static URL downURL =  Data.class.getResource("/statics/down.png");
    public static URL leftURL =  Data.class.getResource("/statics/left.png");
    public static URL rightURL =  Data.class.getResource("/statics/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("/statics/body.png");
    public static ImageIcon body = new ImageIcon(bodyURL);
    //食物
    public static URL foodURL =  Data.class.getResource("/statics/food.png");
    public static ImageIcon food = new ImageIcon(foodURL);
}

     2.2 键盘点击事件

这里主要是需要继承KeyListener重写方法,在keyPressed()方法中进行操作。这里的输入主要是蛇的移动上下左右、还有空格。

空格键的处理:如果游戏失败,那就按空格键重新开始,如果游戏还未失败那就是按空格键暂停或者开始:

//键盘按下,未释放
//获取按下的键盘是哪个键
 int keyCode = keyEvent.getKeyCode();
        if(keyCode==KeyEvent.VK_SPACE){
            //如果失败了就重新开始
            if(isFail){
                isFail=false;
                //重新初始化
                init();
            }else{
                //如果没有失败就是暂停或者开始
                isStart=!isStart;
            }
            repaint();//刷新页面
        }

蛇的移动:这里主要是根据键盘的输入来定义蛇的移动方向,并且不能转头

if(keyCode==KeyEvent.VK_RIGHT){
            if(fx.equals("L")){
                fx="L";
            }else{
                fx="R";
            }
        }else if(keyCode==KeyEvent.VK_LEFT){
            if(fx.equals("R")){
                fx="R";
            }else{
                fx="L";
            }
        }else if(keyCode==KeyEvent.VK_UP){
            if(fx.equals("D")){
                fx="D";
            }else{
                fx="U";
            }
        }else if(keyCode==KeyEvent.VK_DOWN){
            if(fx.equals("U")){
                fx="U";
            }else{
                fx="D";
            }
        }

     2.3 定时器刷新

主要是需要继承ActionListener重写actionPerformed()方法

初始化定时器:这里指的是多少毫秒刷新一次,也可以根据这个时间调节快慢

 delay=100;
 timer=new Timer(100,this);

这里的逻辑主要是蛇的移动的坐标:

 if(isStart && isFail==false) {
            /***
             *   3 2 1
             *   先是第3个到第2个,身体向前移动
             */
            for (int i = length-1; i >0; i--) {
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            //通过控制方向让头部移动
            if(fx.equals("R")){
                snakeX[0] = snakeX[0] + 25;
                /***
                 * 这里的边界判断是指
                 * 当头部到边界时
                 * 重新设定头部位置
                 * 但是已经不需要
                 * 当到边界时游戏结束即可
                 */
                //边界判断
//                if(snakeX[0]>850){
//                    snakeX[0]=25;
//                }
            }else  if(fx.equals("L")){
                snakeX[0] = snakeX[0] - 25;
                //边界判断
//                if(snakeX[0]<25){
//                    snakeX[0]=25;
//                }
            }else  if(fx.equals("U")){
                snakeY[0] = snakeY[0] - 25;
                //边界判断
//                if(snakeY[0]<75){
//                    snakeY[0]=650;
//                }
            }else if(fx.equals("D")){
                snakeY[0] = snakeY[0] + 25;
                //边界判断
//                if(snakeY[0]>650){
//                    snakeY[0]=75;
//                }
            }

蛇吃食物:当蛇头的坐标与食物的坐标重合时就证明吃到了食物,分数+1,蛇的长度也进行相应的加1,并且重新生成食物就可以

 if(snakeX[0]==foodX && snakeY[0]==foodY){
                //长度+1,分数+1
                length++;
                score++;
                //重新生成食物
                foodX=25+25*random.nextInt(34);
                foodY=75+25*random.nextInt(24);
            }

在进行游戏结束的判断、刷新页面:

 /***
     * 判断是否结束
     */
    private void isFailMethod() {
        for(int i=1;i<length;i++){
            //撞到身体
            if(snakeX[0]==snakeX[i]&&snakeY[0]==snakeY[i]){
                isFail=true;
            }
        }
        //碰撞检测--小蛇头和墙壁
        if ((snakeX[0]<25 || snakeX[0]>850)||(snakeY[0]<75 || snakeY[0]>650 ) ){
            isFail = true;
        }
    }

一定不要忘记最后让定时器启动!!!!

   timer.start();

 3.总结

    主要的代码逻辑这里就可以分别进行说明啦。整个运行的代码我上传在我的资源上啦

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值