QT贪吃蛇
五里之南 人气:0一、新建一个Qt项目
新建Qt Widgets Application,项目名称为HappySnake,基类选择QWidget,类名默认
二、添加要用到的头文件
#include <QKeyEvent> #include <QRectF> #include <QPainter> #include <QPen> #include <QBrush> #include <QDebug> #include <QTimer> #include <QTime>
三、写类声明信息
- 贪吃蛇的本体使用小方框来代替
- 使用QList类来保存贪吃蛇的本体
- 使用定时器来设定刷新的时间
- 使用随机函数生成奖励的节点
- 使用paintEvent来进行绘图
- keyPressEvent来监测按键的按下,控制贪吃蛇的移动
class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); protected: void paintEvent(QPaintEvent *); void keyPressEvent(QKeyEvent *); private: void addTopRectF(); void addDownRectF(); void addLeftRectF(); void addRightRectF(); void deleteLastRectF(); bool snakeStrike(); enum Move{Left,Right,Up,Down}; protected slots: void timeOut(); void rewardTimeOut(); private: Ui::Widget *ui; QList<QRectF> snake;//贪吃蛇本体 int snakeNodeWidth = 10; int snakeNodeHeight = 10; QTimer *timer; QTimer *rewardTimer; int time = 100; int moveFlage = Up; bool gameOver = false; bool gameStart = false; QList<QRectF> rewardNode;//奖励节点 };
四、对类函数的实现
构造函数
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); resize(480,500); //设置窗体背景色为黑色 setStyleSheet("QWidget{background:black}"); setWindowOpacity(0.8);//设置窗口的透明度 snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight)); addTopRectF(); addTopRectF(); //首先生成一个奖励节点 rewardNode.append(QRectF(100,100,snakeNodeWidth,snakeNodeWidth)); timer = new QTimer; connect(timer, SIGNAL(timeout()),this,SLOT(timeOut())); //timer->start(time); rewardTimer = new QTimer; connect(rewardTimer,SIGNAL(timeout()),this,SLOT(rewardTimeOut())); //rewardTimer->start(time*30); } Widget::~Widget() { delete ui; }
界面刷新
void Widget::timeOut() { int flage = 1; for(int i=0; i<rewardNode.length(); i++){ if(rewardNode.at(i).contains(snake.at(0).topLeft()+QPointF(snakeNodeWidth/2,snakeNodeHeight/2))){ //if(snake.at(0).contains(rewardNode.at(i).x()+rewardNode.at(i).width()/2,rewardNode.at(i).y()+rewardNode.at(i).height()/2)){ if(rewardNode.at(i).width()>snakeNodeWidth){//额外奖励 flage += 2; } flage++;//正常奖励 rewardNode.removeAt(i); break; } } while(flage--){ switch (moveFlage) { case Up: addTopRectF(); break; case Down: addDownRectF(); break; case Right: addRightRectF(); break; case Left: addLeftRectF(); break; default: break; } } deleteLastRectF(); update(); }
随机奖励的生成
//随机奖励 void Widget::rewardTimeOut() { qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); if(rewardNode.length() > 5){ rewardNode.removeAt(qrand()%5); } rewardNode.append(QRectF(qrand()%(this->width()/20)*20,qrand()%(this->height()/20)*20,snakeNodeWidth,snakeNodeWidth)); if(qrand()%5 == 3){ rewardNode.append(QRectF(qrand()%(this->width()/20)*20-5,qrand()%(this->height()/20)*20-5,snakeNodeWidth*2,snakeNodeWidth*2)); } }
移动
//向上移动 void Widget::addTopRectF() { if(snake.at(0).y()-snakeNodeHeight < 0){ snake.insert(0,QRectF(QPointF(snake.at(0).x(),this->height()-snakeNodeHeight), QPointF(snake.at(0).x()+snakeNodeWidth,this->height()))); }else{ snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(0,-snakeNodeHeight),snake.at(0).topRight())); } } //向下移动 void Widget::addDownRectF() { if(snake.at(0).y()+snakeNodeHeight*2 > this->height()){ snake.insert(0,QRectF(QPointF(snake.at(0).x(),snakeNodeHeight), QPointF(snake.at(0).x()+snakeNodeWidth,0))); }else{ snake.insert(0,QRectF(snake.at(0).bottomLeft(),snake.at(0).bottomRight()+QPointF(0,snakeNodeHeight))); } } //向左移动 void Widget::addLeftRectF() { if(snake.at(0).x()-snakeNodeWidth < 0){ snake.insert(0,QRectF(QPointF(this->width()-snakeNodeWidth,snake.at(0).y()), QPointF(this->width(),snake.at(0).y()+snakeNodeHeight))); }else{ snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(-snakeNodeWidth,0),snake.at(0).bottomLeft())); } } //向右移动 void Widget::addRightRectF() { if(snake.at(0).x()+snakeNodeWidth*2 > this->width()){ snake.insert(0,QRectF(QPointF(0,snake.at(0).y()), QPointF(snakeNodeWidth,snake.at(0).y()+snakeNodeHeight))); }else{ snake.insert(0,QRectF(snake.at(0).topRight(),snake.at(0).bottomRight()+QPointF(snakeNodeWidth,0))); } } //删除结尾数据 void Widget::deleteLastRectF() { snake.removeLast(); }
绘图
//绘图 void Widget::paintEvent(QPaintEvent *event) { QPainter painter(this); QPen pen; QBrush brush; QFont font("方正舒体",12,QFont::ExtraLight,false); //反锯齿 painter.setRenderHint(QPainter::Antialiasing); pen.setColor(Qt::black); brush.setColor(Qt::green); brush.setStyle(Qt::SolidPattern); painter.setPen(pen); painter.setBrush(brush); for(int i=0; i<snake.length(); i++){ painter.drawRect(snake.at(i)); } brush.setColor(Qt::red); painter.setBrush(brush); for(int i=0; i<rewardNode.length(); i++){ painter.drawEllipse(rewardNode.at(i)); } pen.setColor(Qt::white); painter.setPen(pen); painter.setFont(font); painter.drawText(20,20,QString("当前得分:")+QString("%1").arg(snake.length())); if(snakeStrike()){ QFont font("方正舒体",30,QFont::ExtraLight,false); painter.setFont(font); painter.drawText((this->width()-300)/2,(this->height()-30)/2,QString("GAME OVER!")); timer->stop(); rewardTimer->stop(); gameOver = true; } QWidget::paintEvent(event); }
按键事件
void Widget::keyPressEvent(QKeyEvent *event) { switch(event->key()){ case Qt::Key_Up: if(moveFlage != Down){ moveFlage = Up; } break; case Qt::Key_Down: if(moveFlage != Up){ moveFlage = Down; } break; case Qt::Key_Right: if(moveFlage != Left){ moveFlage = Right; } break; case Qt::Key_Left: if(moveFlage != Right){ moveFlage = Left; } break; case Qt::Key_Enter: case Qt::Key_Return: if(gameOver){ snake.clear(); rewardNode.clear(); moveFlage = Up; snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight)); addTopRectF(); addTopRectF(); //首先生成一个奖励节点 rewardNode.append(QRectF(100,100,snakeNodeWidth,snakeNodeWidth)); timer->start(time); rewardTimer->start(time*30); gameOver = false; } break; case Qt::Key_Space: if(gameStart && !gameOver){ timer->start(time); rewardTimer->start(time*30); gameStart = false; }else if(!gameStart && !gameOver){ timer->stop(); rewardTimer->stop(); gameStart = true; } break; default: break; } }
判断蛇身是否相撞
//判断蛇头是否和蛇身相撞 bool Widget::snakeStrike() { for(int i=0; i<snake.length(); i++){ for(int j=i+1; j<snake.length(); j++){ if(snake.at(i) == snake.at(j)){ return true; } } } return false; }
五、结束
实现的效果:
总结:
只是简单的使用了paintevent进行绘图,基本都是简单的对Qt的一些常用类的使用,对面向对象的编程应用的不是很好,更偏向于面向过程,所以完全可以改成C语言在Linux下实现,思路都是相同的。
加载全部内容