预习日志 项目二 贪吃蛇小游戏

要制作一个贪吃蛇小游戏,知识点包含:信号与槽 ,connect 定时器,QTimer 绘制事件,paintEvent ,按键事件,keyPressEvent 随机数,资源文件,应用程序图标,Qt程序发布/打包。

步骤:

①初始化。1.初始化定时器。 2.固定界面大小。3.加载图片,即蛇的头、身体和食物。 4.游戏初始化,需要为蛇设置初始长度,设置几个节点的坐标,保存于两个数组中。随机生成食物的x和y坐标,然后启动定时器。

②定时器。如果游戏正在进行中,需要检查蛇是否吃到食物,即蛇头与食物的位置坐标是否重叠,如果吃到了食物,蛇身的长度加1,然后需要重新生成食物的位置坐标。游戏中需要两个计时器去刷新,一个用来刷新蛇身,一个用来刷新食物。食物需要随机生成,被吃掉后需要删除,有一定的停留时间。keyPressEvent来监测按键的按下,控制贪吃蛇的移动,使用定时器来设定刷新的时间,使用随机函数生成食物的节点。在游戏中还需要检查蛇是否撞到蛇身,如果撞到蛇身,即游戏结束,如果游戏结束,就停止定时器,重新绘制结束的界面。

③核心算法。生成食物的位置,吃食物,检测是否碰撞,蛇的移动,按键,绘制等。

代码参考:

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    resize(600,400);
    setStyleSheet("QWidget{background:pink}");
    snake.append(QRectF(200,200,snakeNodeWidth,snakeNodeHeight));
    addTopRectF();
    addTopRectF();
 
    // 设置第一个奖励
    rewardNode.append(QRectF(400,200,snakeNodeWidth,snakeNodeWidth));
 
    timer = new QTimer;
    connect(timer, SIGNAL(timeout()),this,SLOT(timeOut()));
 
    rewardTimer = new QTimer;
    connect(rewardTimer,SIGNAL(timeout()),this,SLOT(rewardTimeOut()));
 
    this->setWindowTitle("贪吃兔小游戏");
    this->setWindowIcon(QIcon(":/1.jpeg"));
}
 
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)))
        {
            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()%3);
    }
    rewardNode.append(QRectF(qrand()%(this->width()/20)*20,qrand()%(this->height()/20)*20,snakeNodeWidth,snakeNodeWidth));
    if(qrand()%3 == 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::startTheGame()
{
    timer->start(time);
    rewardTimer->start(time2*30);
    gameStart = false;
}
 
void Widget::endTheGame()
{
    timer->stop();
    rewardTimer->stop();
    gameStart = true;
}
 
// 绘图
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPen pen;
    QBrush brush;
    QFont fontg ( "黑体", 20, 50);
 
    painter.setRenderHint(QPainter::Antialiasing);
    pen.setColor(Qt::blue);
    brush.setColor(Qt::white);
    brush.setStyle(Qt::SolidPattern);
    painter.setPen(pen);
    painter.setBrush(brush);
 
    for(int i=0; i<snake.length(); i++){
        //painter.drawRect(snake.at(i));
        painter.drawImage(snake.at(i), QImage(":/6.png"), QRectF(0,0,1076,909));
    }//画蛇
 
    brush.setColor(Qt::yellow);
    painter.setBrush(brush);
 
    for(int i=0; i<rewardNode.length(); i++){
       //painter.drawEllipse(rewardNode.at(i));
       painter.drawImage(rewardNode.at(i), QImage(":/4.png"), QRectF(0,0,750,1024));
    }//画奖励
 
    pen.setColor(Qt::black);
    painter.setPen(pen);
    painter.setFont(fontg);
//    painter.drawText(240,40,QString("得分:")+QString("%1").arg());
 
    emit changeScore(snake.length()-3);
 
    if(snakeStrike()){
        QFont font("幼圆",30,QFont::ExtraLight,false);
        painter.setFont(font);
        painter.drawText((this->width()-300)/2,(this->height()-30)/2,QString("游戏结束"));
        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(time2*30);
            gameOver = false;
        }
        break;
    case Qt::Key_Space:
        if(gameStart && !gameOver){
            timer->start(time);
            rewardTimer->start(time2*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;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值