贪吃蛇小游戏

前言:在经历了前几篇文章的学习后,我们也是已经基本的掌握了Qt的基础语法与开发,为了巩固我们所学的知识,现在就一起动手来实现一个贪吃蛇小游戏吧。😄
游戏规则:

⭐️蛇可以在任意墙壁之间来回穿梭 ⭐️:

⭐️ 吃食物可以增加长度,同时记录分数 ⭐️:

💥当蛇的身体相撞游戏结束💥

1.渲染游戏大厅

首先第一步我们需要准备被我们的资源并创建我们的项目,加载资源并且开始渲染贪吃蛇游戏的界面,我们的游戏主页面其实就是一张背景图与一个按钮,背景图的设置有多种方式:使用绘图事件,使用stylesheet都是可以的。同时为了增强代码编写能力,我们这里都是用纯代码的方式,就不用ui界面进行绘制了。
在这里插入图片描述
这里我们使用绘图事件,需要注意的是如果想使用stylesheet,主界面是不能直接修改背景图,而是需要在此基础上添加一个frame,让两者的大小一致,再frame中stylesheet设置图片。
设置鱼鳔,标题,窗口大小,设置按钮,绑定槽函数:

#include "gameball.h"
#include "ui_gameball.h"

GameBall::GameBall(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::GameBall)
{
    //设置窗口大小
    this->setFixedSize(800,600);
    this->setWindowIcon(QIcon(":/res/ico.png"));
    this->setWindowTitle(tr("贪吃蛇小游戏"));

    //游戏开始按钮
    this->startbutton=new QPushButton("开始游戏",this);
    startbutton->setGeometry(300,450,180,50);//设置按钮位置
    //设置字体
    QFont font;
    font.setFamily("华文行楷");
    font.setPointSize(20);
    startbutton->setFont(font);
    //当然这里用样式表是一样的
    //设置一下样式
    startbutton->setStyleSheet("QPushButton{background-color:#344c93;border:0px}QPushButton:hover{background-color:rgb(0,100,100);border:1px,solida,balck}");
    //当点击开始游戏按钮,此时跳转到游戏选择界面
    connect(this->startbutton,&QPushButton::clicked,this,&GameBall::gameSelect);
}

GameBall::~GameBall()
{
    delete ui;
}

//重写绘图事件
void GameBall::paintEvent(QPaintEvent *event)
{
    //画手
    QPainter painter(this);//画手
    painter.drawPixmap(0,0,this->width(),this->height(),QPixmap(":/res/game_hall.png"));//绘制开始游戏背景图片
}

2.构建游戏选择大厅

改界面的实现,我们会新建一个类继承Qwidget,在鼠标点击信号产生时,构建新窗口,关闭就窗口,同时进行渲染,添加游戏开始的音乐。
以下是鼠标槽函数:

void GameBall::gameSelect()
{
   // 产生点击音效
    QSoundEffect soundEffect;//使用QSoundeffect对象实现
    QUrl source(QStringLiteral("qrc:/res/clicked.wav"));    //设置资源路径
    soundEffect.setSource(source);
    soundEffect.setLoopCount(1); // 只播放一次
    soundEffect.setVolume(0.6);//音量50%
    soundEffect.play();//播放
    //此时新建一个窗口作为我们游戏选择选择界面
    this->selectWindow=new GameSelect();
    //同时隐藏我们的窗口
    this->close();
    soundEffect.deleteLater();//关闭也清理音乐资源
}

接下来就是游戏选择大厅的界面实现😎,游戏选择大厅主要有背景图和四个按钮,三个按钮表示游戏难度模式,一个按钮用来展示游戏的历史记录,当点击按钮使就会弹到对应的界面,所以这里主要是按钮槽函数的实现–打开对应窗口,完整的实现还需要先把历史剧路页面与游戏页面线实现出来,所以这里我先给出基本组建的实现:

#include "gameselect.h"
#include"gameball.h"
#include<QSoundEffect>
GameSelect::GameSelect(QWidget *parent)
    : QWidget{parent}
{
    //设置窗口大小
    this->setFixedSize(800,600);
    this->setWindowIcon(QIcon(":/res/ico.png"));
    this->setWindowTitle(tr("游戏模式选择"));
    //设置按钮
    backbutton=new QPushButton(this);//设置返回按钮
    backbutton->setGeometry(700,530,50,40);
    QIcon icon(QPixmap(":/res/back.png"));
    backbutton->setIcon(icon);
    backbutton->setIconSize(QSize(40,40));//设置图标的大小
    backbutton->setStyleSheet("border-width:0px;");
   backbutton->setFlat(true);//设置边框不可见,有bug,设置了就消失了
    connect(backbutton,&QPushButton::clicked,this,[=](){
        this->close();
        GameBall * gameball=new GameBall();
        gameball->show();
        //添加音效
         playmusic();//点击音乐
    });
   //音频
   music =new QMediaPlayer(this);
   output=new QAudioOutput(this);
   //字体设置
    QFont font;
    font.setFamily("华文行楷");
    font.setPointSize(20);
    //简单模式按钮
    this->easybutton=new QPushButton(this);
    this->easybutton->setGeometry(300,100,140,40);
    this->easybutton->setText("简单模式");
    this->easybutton->setFont(font);
    //中等模式按钮
    this->midbutton=new QPushButton(this);
    this->midbutton->setGeometry(300,160,140,40);
    this->midbutton->setText("中等模式");
    this->midbutton->setFont(font);
    //困难模式按钮
    this->hardbutton=new QPushButton(this);
    this->hardbutton->setGeometry(300,220,140,40);
    this->hardbutton->setText("困难模式");
    this->hardbutton->setFont(font);

    this->historybutton=new QPushButton(this);
    this->historybutton->setGeometry(300,280,140,40);
    this->historybutton->setText("历史记录");
    this->historybutton->setFont(font);


    //历史记录信号处理
    connect(this->historybutton,&QPushButton::clicked,this,[=](){
         playmusic();
        this->historywindow=new HistoryWidget();
        this->historywindow->show();
        this->close();

    });


    //简单模式的游戏
    connect(easybutton,&QPushButton::clicked,this,[=](){
        //添加音乐
        playmusic();//点击音乐
        //创建出游戏界面
        gameWidget=new GameRoom();
        this->close();
        gameWidget->show();


    });

    //中等模式
    connect(midbutton,&QPushButton::clicked,this,[=](){
        //创建出游戏界面
        //添加音效
        playmusic();
        //创建出游戏界面
        gameWidget=new GameRoom();
        this->close();
        gameWidget->show();
        gameWidget->setCycle(500);

    });

    //困难模式
    connect(hardbutton,&QPushButton::clicked,this,[=](){
        //创建出游戏界面
         playmusic();//点击音乐
        //创建出游戏界面
        gameWidget=new GameRoom();
        this->close();
        gameWidget->show();
        gameWidget->setCycle(100);

    });


    this->show();
}

GameSelect::~GameSelect()
{
    this->close();
}

void GameSelect::paintEvent(QPaintEvent *event)
{
   //绘制背景图
    (void)event;
    //画手
    painter=new QPainter(this);//画手
    painter->drawPixmap(0,0,this->width(),this->height(),QPixmap(":/res/game_select.png"));//绘制开始游戏背景图片
}

void GameSelect::playmusic()
{
    //添加音效
    // 产生点击音效
    output->setVolume(0.5);//设置声音
    music->setAudioOutput(output);
    music->setSource(QUrl("qrc:/res/clicked.wav"));
    music->play();
    //该槽表示播放一次
    connect(music, &QMediaPlayer::mediaStatusChanged, this,[=](QMediaPlayer::MediaStatus status){
        if (status == QMediaPlayer::EndOfMedia) {
            music->stop();
            //播放结束就停止
        }
    });
}

3.构建历史记录界面

还是老样子,新的窗口我们重新再出创建一个类,对窗口进行设置。
主要功能就是读取文件信息,然后显示出来,添加清除历史记录的按钮,以及返回游戏的按钮。

```cpp
void GameRoom::paintEvent(QPaintEvent *event)
{
        (void)event;
    painter=new QPainter(this);
    painter->drawPixmap(0,0,800,600,QPixmap(":/res/game_room.png"));//左边多用来显示游戏
    painter->drawPixmap(800,0,200,700,QPixmap(":/res/bg1.png"));//右边少用来显示选项
    //绘制蛇,由三部分组成 蛇头 蛇身体 蛇尾巴
    //先看蛇头,分为四个方向,每个方向要进行不同的旋转
    QPixmap pixmap;
    if(!Snake.empty())
    {
        if(direction==Snake_Direct::UP)
        {
            //图片蛇头默认是向上,当前如果是向上,加载图片
            pixmap.load(":/res/up.png");
        }else if(direction==Snake_Direct::DOWN)
        {
            pixmap.load(":/res/down.png");
        }else if(direction==Snake_Direct::LEFT)
        {
            pixmap.load(":/res/left.png");
        }else if(direction==Snake_Direct::RIGHT)
        {
            pixmap.load(":/res/right.png");
        }
    }
    //根据链表中头节点位置进行绘图
    auto head=Snake.front();
     painter->drawPixmap(head.x(),head.y(),head.width(),head.height(),pixmap);
    //绘制蛇身体 加载资源文件
     pixmap.load(":/res/Bd.png");
     //其次由于蛇身有长度,根据链表的节点的个数进行绘制(除蛇头蛇尾)
     for(int i=1;i<Snake.size()-1;i++)
     {
        auto Node=Snake.at(i);
         painter->drawPixmap(Node.x(),Node.y(),Node.width(),Node.height(),pixmap);
     }
     //最后绘制蛇尾巴
     auto tail=Snake.back();//获取最后一个节点
     painter->drawPixmap(tail.x(),tail.y(),tail.width(),tail.height(),pixmap);

     //绘制食物
     painter->drawPixmap(Food.x(),Food.y(),Food.width(),Food.height(),QPixmap(":/res/food.bmp"));

     QPen pen;
     pen.setColor(Qt::red);
     QFont font;
     font.setFamily("华文行楷");
     font.setPointSize(22);
     painter->setPen(pen);
     painter->setFont(font);
     //绘制游戏失败
     if(CheckGameOver() )
     {
         music->stop();
         painter->drawText(this->width()*0.5,this->height()*0.5,"Game Over !");
         time->stop();
         music->setSource(QUrl("qrc:/res/gameover.wav"));
         music->play();
         connect(music, &QMediaPlayer::mediaStatusChanged, this,[=](QMediaPlayer::MediaStatus status){
             if (status == QMediaPlayer::EndOfMedia) {
                 music->stop();
                 //播放结束就停止
                 music->setSource(QUrl("qrc:/res/clicked.wav"));
             }
         });
         //游戏结束写入文件内
         QFile file("D:\game_history.txt");
         file.open(QIODeviceBase::NewOnly|QIODeviceBase::ReadWrite| QIODeviceBase::Append);
         QString content="第"+QString::number(count)+"次成绩为:"+QString::number(ret);
         file.write(content.toUtf8());
         file.close();
     }
}

历史记录界面

#include "historywidget.h"
#include<QPainter>
#include<QFile>
class GameSelect;
HistoryWidget::HistoryWidget(QWidget *parent)
    : QWidget{parent}
{
    this->setFixedSize(600,500);
    backbutton=new QPushButton(this);//设置返回按钮
    backbutton->setGeometry(0,0,30,30);
    QIcon icon(QPixmap(":/res/back.png"));
    backbutton->setIcon(icon);
    backbutton->setIconSize(QSize(30,30));//设置图标的大小
    backbutton->setStyleSheet("border-width:0px;");
    backbutton->setFlat(true);//设置边框不可见,有bug,设置了就消失了
    label=new QLabel(this);
    label->setGeometry(50,20,150,50);
    label->setStyleSheet("QLabel{font-size:20px;color:red;font-family:华文行楷;}");
    //显示历史记录
    QFile file("D:\game_history.txt");
    file.open(QFileDevice::ReadOnly);
    QTextStream in(&file);
    QString history;
    while (!in.atEnd()) {
        QString line = in.readLine(); // 读取一行
        //放到标签中
        history+=line;
    }
    label->setText(history);
    file.close();
    connect(backbutton,&QPushButton::clicked,this,[=](){
        this->close();
        selectWidget=new GameSelect();
        selectWidget->show();
    });
}

void HistoryWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawPixmap(0,0,this->width(),this->height(),QPixmap(QPixmap(":pixmap.png")));
}

4.游戏逻辑的实现

对于游戏界面我们分为两部分,一部分是游戏画面,一部分是操作选项,贪吃蛇的进行是在游戏画面中的。
首先,我们将贪吃蛇拟想为一个链表,它的身体由一个个节点构成,在运行过程中,分为上下左右,其次,在碰到上下左右边界时我们此时认为是穿墙,我们会让他从对立的方向穿梭过来。
蛇的表示:
在这里插入图片描述

穿墙的演示:
在这里插入图片描述
未穿墙的演示:
在这里插入图片描述

除了向上,向左移动需要我们自己去增减长度,向右和向下我们可以直接用原节点的右上坐标与左下坐标直接替换就可以了。这里的上下左右移动当前只针对头节点,每次移动更新头节点,即头节点表示蛇头的移动。

蛇的移动

为了将来实现处蛇整个移动过程的画面,我们是通过定时器去周期的执行对应移动的函数,为了使移动看起来更加真实,以向上移动为例:
我们为了不控制每一个节点的坐标,每个周期移动一次,这里在每次移动后头插新位置的头节点(此时会多一个节点),每个周期过去,我们再尾删最后一个节点,然后更新窗口。通过每次移动插入新位置节点,在删除尾巴节点,实现整个蛇的移动,而不同对每一个节点都去控制。

void GameRoom::moveUp()
{
    //每次移动头节点大小的单位
    //我们用左上角坐标与右下角坐标唯一确定一个节点位置,同时用rectf表示改节点
    QPointF leftTop;//左上角
    QPointF rightBottom;//右下角
    auto SnakeNode=Snake.front();//获取蛇的头节点
    int x=SnakeNode.x();
    int y=SnakeNode.y();

    if(y<0)
    {
        //此时蛇头和界面上边框重合,要穿墙了,从下面在进来来,减掉自身高度
        leftTop=QPointF(x,this->height()-WSnake);//左上坐标

    }else//没有穿墙
    {
          leftTop=QPointF(x,y-WSnake);//减掉自身高度即可
    }

    rightBottom=QPointF(leftTop.x()+LSnake,leftTop.y()+WSnake);//右下坐标

    Snake.push_front(QRectF(leftTop,rightBottom));//头插新节点,更新自己的位置
    
}

//蛇向下移动
void GameRoom::moveDown()
{
    //我们用左上角坐标与右下角坐标唯一确定一个节点位置,同时用rectf表示改节点
    QPointF leftTop;
    QPointF rightBottom;
    auto SnakeNode=Snake.front();//获取蛇的头节点
    int x=SnakeNode.x();
    int y=SnakeNode.y();
    //判断有没有向下
    if(y>this->height())
    {
          //此时蛇头和下界面边框重合,要穿墙了,从上面在进来,
          //构造出新的节点的右下角坐标
          leftTop=QPointF(x,0);//左上坐标
          
    }else//没有穿墙
    {
          leftTop=SnakeNode.bottomLeft();//直接获取源节点左下坐标,就是当前的左上坐标
    }
    rightBottom=QPointF(leftTop.x()+LSnake,leftTop.y()+WSnake);//右下坐标
    
    Snake.push_front(QRectF(leftTop,rightBottom));//头插新节点,更新自己的位置
    
}
//向左移动
void GameRoom::moveLeft()
{
    
    QPointF leftTop;//左上角
    QPointF rightBottom;//右下角
    auto SnakeNode=Snake.front();//获取蛇的头节点
    int x=SnakeNode.x();
    int y=SnakeNode.y();
    if(x<0)
    {
        //左边穿墙,从右边框出来,这里的右边框是 this->width-200,800
          leftTop=QPointF(800-LSnake,y);//左上坐标
    }else
    {
          leftTop=x-LSnake;//此时这里的左上坐标等于节点直接减去坐标长度
    }
    rightBottom=QPointF(leftTop.x()+LSnake,leftTop.y()+WSnake);//右下坐标
    
    Snake.push_front(QRectF(leftTop,rightBottom));//头插新节点,更新自己的位置
}
//向右移动


void GameRoom::moveRight()
{
    
    QPointF leftTop;//左上角
    QPointF rightBottom;//右下角
    auto SnakeNode=Snake.front();//获取蛇的头节点
    int x=SnakeNode.x();
    int y=SnakeNode.y();
    if(x>800)
    {
        //右边穿墙,从左边框出来,这里的左边框是0
             leftTop=QPointF(0,y);//左上坐标
    }else
    {
             leftTop=SnakeNode.topRight();//没穿墙,当前坐标为原节点的右上坐标
    }
    rightBottom=QPointF(leftTop.x()+LSnake,leftTop.y()+WSnake);//右下坐标
    
    Snake.push_front(QRectF(leftTop,rightBottom));//头插新节点,更新自己的位置 
}

判断游戏是否结束

//判读游戏是否结束
bool GameRoom::CheckGameOver()
{
    //自己撞到自己身体就游戏结束
    for(int i=0;i<Snake.size();i++)//遍历蛇本身
    {
             for(int j=i+1;j<Snake.size();j++)
             {
                 if(Snake.at(i)==Snake.at(i))//判断每个节点是否互相相等--右坐标重合
                 {
                     return true;
                 }
             }
    }
    return false;
    
}

根据链表绘制蛇

绘制的整个过程都是在绘图时间里完成的,除了蛇,首先绘制的是背景图片。

void GameRoom::paintEvent(QPaintEvent *event)
{
    (void)event;
    painter=new QPainter(this);
    painter->drawPixmap(0,0,800,600,QPixmap(":/res/game_room.png"));//左边多用来显示游戏
    painter->drawPixmap(800,0,200,700,QPixmap(":/res/bg1.png"));//右边少用来显示选项
    //绘制蛇,由三部分组成 蛇头 蛇身体 蛇尾巴
    //先看蛇头,分为四个方向,每个方向要进行不同的旋转
    QPixmap pixmap();
    if(direction==Snake_Direct::UP)
    {
        //图片蛇头默认是向上,当前如果是向上,加载图片
       pixmap.load(":/res/up.png");
    }else if(direction==Snake_Direct::DOWN)
    {
       pixmap.load(":/res/down.png");
    }else if(direction==Snake_Direct::LEFT)
    {
       pixmap.load(":/res/left.png");
    }else if(direction==Snake_Direct::RIGHT)
    {
        pixmap.load(":/res/right.png");
    }
    //根据链表中头节点位置进行绘图
    auto head=Snake.front();
     painter->drawPixmap(head.x(),head.y(),head.width(),head.height(),pixmap);
    //绘制蛇身体 加载资源文件
     pximap.load(":/res/BD.png");
     //其次由于蛇身有长度,根据链表的节点的个数进行绘制(除蛇头蛇尾)
     for(int i=0;i<Snake.size()-2;i++)
     {
        auto Node=Snake.at(i);
         painter->drawPixmap(Node.x(),Node.y(),Node.width(),Node.height(),pixmap);
     }
     //最后绘制蛇尾巴
     auto tail=Snake.back();//获取最后一个节点
     painter->drawPixmap(tail.x(),tail.y(),tail.width(),tail.height(),pixmap);
     
}

初始化蛇

初始化蛇的本质,其实就是初始化链表,在构造中调用,因为蛇由头+身子+尾巴,所以至少有三个节点。
由于移动方向都会增加链表长度,我们直接在这里moveup头插节点,作为初始化。

void GameRoom::InitSnake()
{
    //蛇从中间生成,头像上
    Snake.push_front(QRectF(this->width()/2,this->height()/2,LSnake,WSnake));//头
    moveUp();//身体
    moveUp();//尾巴

}

生成食物

//生成食物
void GameRoom::CreateFood()
{
    //定义生成食物的坐标
    double  num = QRandomGenerator::global()->generateDouble();
    double x=num*800;
   double  y=num*600;
    Food=QRectF( x/2+1, y/2+1,LSnake,WSnake);
}
//在绘图事件中绘制
  //绘制食物
     painter->drawPixmap(Food.x(),Food.y(),Food.width(),Food.height(),QPixmap(":/res/food.bmp"));


蛇的周期移动

想要蛇真正的动起来。我们通过周期性的去调用move接口,上下左右,因为我们之前实现move使会插入新节点,所以这里的在周期移动后,就去删除尾节点,更新头节点,删除尾节点,最后去绘制,刷新屏幕,就实现蛇的移动。

        //之后就去周期性的让蛇去移动,让它动起来
        time=new QTimer(this);
        time->start(cycle);
        connect(time,&QTimer::timeout,this,[=](){
            //每隔一个周期就来判断食物和链表会不会相交,相交就需要重新生成
            int cnt=1;
            if(Snake.front().intersects(Food))
            {
                CreateFood();
                cnt++;
            }
            //根据移动信息移动蛇
            while(cnt--)
            {
                switch(direction)
                {
                case::Snake_Direct::UP:
                    moveUp();
                    break;
                    case::Snake_Direct::DOWN:
                    moveDown();
                    break;
                    case::Snake_Direct::LEFT:
                    moveLeft();
                    break;
                    case::Snake_Direct::RIGHT:
                    moveRight();
                    break;
                }
            }
            //删除最后一个节点
            Snake.pop_back();//旧节点删除,看起来像移动
            update();//更新窗口
        });

游戏的暂停与继续

游戏的暂停与继续卓就是控制定时器

//布置三个按钮
        QFont font;
        font.setFamily("华文行楷");
        font.setPointSize(20);
        startgame=new QPushButton("开始游戏",this);
        startgame->setGeometry(830,100,130,40);
        startgame->setFont(font);
        connect(startgame,&QPushButton::clicked,this,[=](){
            count++;
            musicPlay();
            //启动定时器
            time->start(cycle);
        });
        stopgame=new QPushButton("暂停游戏",this);
        stopgame->setGeometry(830,150,130,40);
        stopgame->setFont(font);
        connect(stopgame,&QPushButton::clicked,this,[=](){
            //暂停音乐
            music->pause();
            //停止定时器
            time->stop();
        });
        regame=new QPushButton("重新游戏",this);
        regame->setGeometry(830,200,130,40);
        regame->setFont(font);
        connect(regame,&QPushButton::clicked,this,[=](){
            //关闭音乐
            music->stop();
            //链表置空,重新初始化
            Snake.clear();
            InitSnake();
            this->update();
            time->stop();
        });

        back=new QPushButton(this);
        back->setGeometry(802,2,30,30);
        back->setIconSize(QSize(30,30));
        back->setFlat(true);
        back->setIcon(QIcon(":/res/back.png"));
        connect(back,&QPushButton::clicked,this,[=](){
            //添加音效
            music->setSource(QUrl("qrc:/res/clicked.wav"));
            music->play();
            //该槽表示播放一次
            connect(music, &QMediaPlayer::mediaStatusChanged, this,[=](QMediaPlayer::MediaStatus status){
                if (status == QMediaPlayer::EndOfMedia) {
                    music->stop();
                    //播放结束就停止
                }
            });
            time->stop();
            //退出游戏
            QMessageBox * exitgame=new QMessageBox(this);//先创建一个messgeboxd的对象
            exitgame->setIcon(QMessageBox::Warning);//QT内部也提供了一些图标
            exitgame->setWindowTitle("这是一个对话框");
            exitgame->resize(300,300);
            exitgame->setStandardButtons(QMessageBox::Ok |  QMessageBox::Cancel );//设置基本的按钮。例如ok与保存按钮,这些都是内置的常用的按钮
            exitgame->show();
             int buttonClicked = exitgame->exec();  //获取用户点击按钮的返回值
            if(buttonClicked==QMessageBox::Ok)
            {
                this->close();
                GameSelect * selectWidget=new GameSelect();
                selectWidget->show();
            }else
            {
                 exitgame->close();
            }
        });
        //初始化媒体播放
        music=new QMediaPlayer(this);
        output=new QAudioOutput(this);
        output->setVolume(0.5);
        music->setAudioOutput(output);
        //启动音乐
        music->setSource(QUrl("qrc:/res/Trepak.wav"));

游戏中的移动按钮

通过直接改变蛇头的方向状态即可实现蛇的转向,在获取蛇头方向信息后在绘制事件里绘制出对应的蛇头。

  //初始化方向
        up=new QPushButton(this);
        up->setGeometry(880,330,40,40);
        up->setIconSize(QSize(40,40));
        up->setIcon(QIcon(":/res/moveup.png"));
        up->setFlat(true);

        connect(up,&QPushButton::clicked,this,[=](){
            //改变蛇头方向
//            if(this->direction==Snake_Direct::DOWN)
//            {
//                //向上不能向下,反之同理
//                return;
//            }else
//            {

//            }
            direction=Snake_Direct::UP;
        });
        down=new QPushButton(this);
        down->setGeometry(880,410,40,40);
        down->setIconSize(QSize(40,40));
        down->setIcon(QIcon(":/res/movedown.png"));
        down->setFlat(true);
        connect(down,&QPushButton::clicked,this,[=](){
             //direction=Snake_Direct::UP;
//            if(this->direction==Snake_Direct::UP)
//            {
//                return;
//            }else
//            {

//            }
            direction=Snake_Direct::DOWN;

        });

        left=new QPushButton(this);
        left->setGeometry(840,370,40,40);
        left->setIconSize(QSize(40,40));
        left->setIcon(QIcon(":/res/moveleft.png"));
        left->setFlat(true);
        connect(left,&QPushButton::clicked,this,[=](){
          /*  if(this->direction==Snake_Direct::RIGHT)
            {
                return;
            }else
            {

            }*/
            direction=Snake_Direct::LEFT;
        });

        right=new QPushButton(this);
        right->setGeometry(920,370,40,40);
        right->setIconSize(QSize(40,40));
        right->setIcon(QIcon(":/res/moveright.png"));
        right->setFlat(true);
        connect(right,&QPushButton::clicked,this,[=](){
//            if(this->direction==Snake_Direct::LEFT)
//            {
//                return;
//            }else
//            {

//            }
            direction=Snake_Direct::RIGHT;
        });
           //绘制分数
        label=new QLabel(this);
        label->setGeometry(830,60,90,30);
        QFont font2;
        font2.setPointSize(20);
        font2.setFamily("华文行楷");
        label->setFont(font2);
}

源码:

总结

通过该小游戏,我也基本掌握了qt基本组件的使用,同时熟练的使用信号槽与事件机制,对QSS的使用也越来越熟悉,对于游戏实现的逻辑更加清除,对于QT项目开发的框架更加清晰,基本掌握了QT的基础开发。

相关推荐

  1. 贪吃游戏

    2024-06-17 21:06:02       35 阅读
  2. 贪吃游戏

    2024-06-17 21:06:02       27 阅读
  3. 贪吃web游戏

    2024-06-17 21:06:02       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-17 21:06:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-17 21:06:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-17 21:06:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-17 21:06:02       18 阅读

热门阅读

  1. 高考选择:专业优先还是学校优先?

    2024-06-17 21:06:02       8 阅读
  2. 无限压缩存储器【著作者:汪敏飞】

    2024-06-17 21:06:02       8 阅读
  3. 架构师输出物

    2024-06-17 21:06:02       7 阅读
  4. 102. 二叉树的层序遍历

    2024-06-17 21:06:02       8 阅读
  5. 基于开源语音识别项目ChatTTS的推荐

    2024-06-17 21:06:02       7 阅读
  6. 代码随想录打卡第十二天补

    2024-06-17 21:06:02       5 阅读
  7. cocosCreator获取手机剪切板内容

    2024-06-17 21:06:02       7 阅读
  8. python 多线程

    2024-06-17 21:06:02       9 阅读
  9. C++之std::lock_guard和std::unique_lock

    2024-06-17 21:06:02       8 阅读
  10. 异常类型处理 3.0

    2024-06-17 21:06:02       7 阅读