文章目录:
一:效果演示
二:实现思路
三:代码实现
widget.h
widget.cpp
main.cpp
一:效果演示
效果图◕‿◕✌✌✌
代码下载
二:实现思路
通过按键控制蛇的移动,每吃一个商品蛇身就会加长,如果蛇身头尾相碰就结束游戏
声明渲染绘图:画笔画刷进行相关的渲染背景蛇和奖品 按键处理机制:方便后面的键盘操作 定时器:到时就会触发 按下空格:代表开始 上下左右键控制蛇的移动方向:DIR_DOWN DIR_UP DIR_LEFT DIR_RIGHT 蛇: 蛇的表示:矩形的两点确定小方块,3个小方块为初始蛇身 判断蛇身蛇头:如果蛇头蛇尾接触就结束游戏 蛇身变动:相交就吃掉奖品,吃一个加一个小方块 奖品 奖品的表示:小红点 奖品的添加:蛇吃完一个奖品就马上随机添加一个奖品 蛇吃奖品: 吃一个奖品会加一个方块:上面、下面、左面、右面
三:代码实现
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> //按键 #include <QKeyEvent> //定时器 #include <QTimer> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE //定义方向 enum Dirct{DIR_LEFT,DIR_RIGHT,DIR_DOWN,DIR_UP}; class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); protected: //声明渲染绘图 void paintEvent(QPaintEvent *event); //声明按键处理 void keyPressEvent(QKeyEvent *event); //声明上面加一个函数 void addTop(); //声明下面加一个函数 void addDown(); //声明左面加一个函数 void addLeft(); //声明右面加一个函数 void addRight(); //声明减去一个模块 void deleteLast(); //声明添加奖品函数 void addNewReword(); //声明判断蛇头蛇身 bool checkContact(); private: Ui::Widget *ui; //初始化定义方向 int moveFlag = DIR_UP; //定义启动的开始 bool gameStart = false; //定义定时器 QTimer *timer; int time = 100;//超时事件间隔(毫秒) //蛇的表示 矩形两点确定(容器) QList <QRectF> snake; //小方块表示 int nodeWidth = 20; int nodeHeight = 20; //奖品的表示 QRectF rewardNode; protected slots: //定义超时函数 void timeout(); }; #endif // WIDGET_H
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <qmediaplayer.h> //画家 #include <QPainter> //文字 #include <QRandomGenerator> //背景音乐 #include <QtMultimedia/QtMultimedia> #include <QtMultimediaWidgets/QVideoWidget> #include <QApplication> #include <QMediaPlayer> #include <QUrl> #include <QFileDialog> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); //定义窗口大小 //resize(800,600); this->setFixedSize(800,600); QMediaPlayer *player = new QMediaPlayer; player->setSource(QUrl::fromLocalFile("F:/QT/Snake/images/mu.mp3")); player->play(); //实现定时器 可以让蛇动起来 //创建定时器 timer = new QTimer(); //信号槽 timeout超时 connect(timer,SIGNAL(timeout()),this,SLOT(timeout())); //初始化蛇身 QRectF rect(400,300,nodeWidth,nodeHeight); //小方块加到蛇身上去 snake.append(rect); //再加两端 addTop(); addTop(); //初始化奖品 addNewReword(); //背景音乐 // //创建一个显示视频的控件 // QVideoWidget* videowin = new QVideoWidget(this); // videowin->resize(400,300); // //添加一个播放器 // QMediaPlayer *player = new QMediaPlayer(this); // player->setVideoOutput(videowin); // //音乐 // player->setMedia(QMediaContent(QUrl::fromLocalFile("F:/QT/Snake/images/game.mp3"))); // //player->setVolume(50);//音量 // //开始播放 // player->play(); } Widget::~Widget() { delete ui; } //实现按键函数 控制方向 void Widget::keyPressEvent(QKeyEvent *event){ switch (event->key()) { case Qt::Key_Up: if(moveFlag != DIR_DOWN){moveFlag = DIR_UP;} break; case Qt::Key_Down: if(moveFlag != DIR_UP){moveFlag = DIR_DOWN;} break; case Qt::Key_Right: if(moveFlag != DIR_LEFT){moveFlag = DIR_RIGHT;} break; case Qt::Key_Left: if(moveFlag != DIR_RIGHT){moveFlag = DIR_LEFT;} break; case Qt::Key_Space: if(gameStart == false){ gameStart = true; //启动定时器 timer->start(time); } else{ gameStart = false; //停止定时器 timer->stop(); } break; default: break; } } //实现超时函数 void Widget::timeout(){//实现逻辑要么都上移,要么底部加一个,顶部取消一个 //判断有没有重合 int count = 1; if(snake[0].intersects(rewardNode)){ //相交就吃掉奖品 count++; //吃掉添加新的奖品 addNewReword(); } while (count--) { //蛇的移动 switch (moveFlag) { case DIR_UP: addTop(); break; case DIR_DOWN: addDown(); break; case DIR_LEFT: addLeft(); break; case DIR_RIGHT: addRight(); break; default: break; } } //删除一个 deleteLast(); //刷新一下 update(); } //实现上面加一个函数 void Widget::addTop(){ QPointF leftTop; QPointF rightBotom; //超出边界(顶端) 加到最下面 if(snake[0].y()-nodeHeight < 0){ //this->height窗口 leftTop = QPoint(snake[0].x(),this->height()-nodeHeight); rightBotom = QPointF(snake[0].x()+nodeWidth,this->height()); }else{ //没有超出的情况 //在蛇的上面(蛇和矩形) //左上角坐标 nodeHeight小方块矩形 leftTop = QPointF(snake[0].x(),snake[0].y()-nodeHeight); //右下角坐标 rightBotom = snake[0].topRight(); } //加一个小方块 snake.insert(0,QRectF(leftTop,rightBotom)); } //实现下面加一个函数 void Widget::addDown(){ QPointF leftTop; QPointF rightBotom; //超出边界(顶端) 加到最下面 if(snake[0].y()+nodeHeight*2 > this->height()){ leftTop = QPointF(snake[0].x(),0); rightBotom = QPointF(snake[0].x()+nodeWidth,nodeHeight); }else{ //没有超出的情况 //在蛇的上面(蛇和矩形) //左上角坐标 nodeHeight小方块矩形 leftTop = snake[0].bottomLeft(); //右下角坐标 rightBotom = snake[0].bottomRight()+QPointF(0,nodeHeight); } //加一个小方块 snake.insert(0,QRectF(leftTop,rightBotom)); } //实现左面加一个函数 void Widget::addLeft(){ QPointF leftTop; QPointF rightBotom; //超出边界(顶端) 加到最下面 if(snake[0].x()-nodeWidth < 0){ leftTop = QPointF(this->width()-nodeWidth,snake[0].y()); }else{ //没有超出的情况 //在蛇的上面(蛇和矩形) //左上角坐标 nodeHeight小方块矩形 leftTop = snake[0].topLeft()-QPointF(nodeWidth,0); } rightBotom = leftTop+QPointF(nodeWidth,nodeHeight); //右下角坐标 //加一个小方块 snake.insert(0,QRectF(leftTop,rightBotom)); } //实现右面加一个函数 void Widget::addRight(){ QPointF leftTop; QPointF rightBotom; //超出边界(顶端) 加到最下面 if(snake[0].x()-nodeWidth*2 > this->width()){ leftTop = QPointF(0,snake[0].y()); }else{ //没有超出的情况 //在蛇的上面(蛇和矩形) //左上角坐标 nodeHeight小方块矩形 leftTop = snake[0].topRight(); } rightBotom = leftTop+QPointF(nodeWidth,nodeHeight); //右下角坐标 //加一个小方块 snake.insert(0,QRectF(leftTop,rightBotom)); } //实现绘图 void Widget::paintEvent(QPaintEvent *event){ //画家 QPainter painter(this); //画笔 QPen pen; //画刷 QBrush brush; //背景图片 QPixmap pix; pix.load("F:/QT/Snake/images/bk.png"); // QPixmap pixmap(":/images/bk.png"); painter.drawPixmap(0,0,800,600,pix); //画蛇 //画笔 pen.setColor(Qt::black); //画刷 brush.setColor(Qt::darkMagenta); brush.setStyle(Qt::SolidPattern); //画家使用画笔和画刷 painter.setPen(pen); painter.setBrush(brush); //画蛇的头尾 for(int i=0;i<snake.length();i++){ painter.drawRect(snake[i]); } //画奖品 //画笔 pen.setColor(Qt::red); //画刷 brush.setColor(Qt::red); brush.setStyle(Qt::SolidPattern); //画家使用画笔和画刷 painter.setPen(pen); painter.setBrush(brush); //painter.drawRect(rewardNode);//奖品 painter.drawEllipse(rewardNode); //判断蛇头是否碰到蛇身 if(checkContact()){ QFont font("方块输出",30,QFont::ExtraLight,false); painter.setFont(font); painter.drawText( (this->width()-300)/2, (this->height()-30)/2, QString("完成") ); timer->stop(); } //调用一下父类 QWidget::paintEvent(event); } //实现减去一个方块 void Widget::deleteLast(){ snake.removeLast(); } //实现添加奖品函数 void Widget::addNewReword(){ //奖品 int width = this->width(); int a = QRandomGenerator::global()->bounded(width/20*20); int height = this->height(); int b = QRandomGenerator::global()->bounded(height/20*20); rewardNode = QRectF( //qrand()%(this->width()/20)*20, //qrand()%(this->height()/20)*20, //QT6用上面方法会报错:'qrand' was not declared in this scope; did you mean 'srand'? a, b, nodeWidth, nodeHeight ); } //实现判断蛇头是否碰到蛇身函数 bool Widget::checkContact(){ for(int i = 1; i < snake.length(); i++) for (int j = i+1; j < snake.length(); j++) { if(snake[i] == snake[j]){ return true; } } return false; }
main.cpp
#include "widget.h" #include <QApplication> #include <QLocale> #include <QTranslator> int main(int argc, char *argv[]) { QApplication a(argc, argv); QTranslator translator; const QStringList uiLanguages = QLocale::system().uiLanguages(); for (const QString &locale : uiLanguages) { const QString baseName = "Snake_" + QLocale(locale).name(); if (translator.load(":/i18n/" + baseName)) { a.installTranslator(&translator); break; } } Widget w; w.show(); return a.exec(); }