用Qt开发小游戏《愤怒的小鸟》
文章目录
- 前言
- 本文章主要讲解我和朋友一起用Qt开发的小游戏《愤怒的小鸟》,游戏素材来源于游戏截图和网上查找。这是一款曾经在手机上风靡一时的横屏小游戏,游戏具体怎么玩想必我就不用跟大家介绍了吧。主要说说里面最不好实现的一个东西:“物理引擎”,就是小鸟的飞行轨迹和小鸟和障碍物的撞击效果。
- 一、游戏效果
- 二、代码功能模块
- 1.第一个模块(主模块) 登录界面
- 2.第二个模块 游戏开始界面
- 3.第三个模块 关卡选择界面
- 4.第四个模块 游戏界面
- 5.第五个模块 鸟对象
- 总结
前言
本文章主要讲解我和朋友一起用Qt开发的小游戏《愤怒的小鸟》,游戏素材来源于游戏截图和网上查找。这是一款曾经在手机上风靡一时的横屏小游戏,游戏具体怎么玩想必我就不用跟大家介绍了吧。主要说说里面最不好实现的一个东西:“物理引擎”,就是小鸟的飞行轨迹和小鸟和障碍物的撞击效果。
一、游戏效果
二、代码功能模块
1.第一个模块(主模块) 登录界面
核心代码如下(示例):
void Widget::regiser(bool)
{//查询用户是否已经存在QString str = QString("select * from usertable where account='%0';")\. arg(le_account->text());QSqlQuery query;query.exec(str);while(query.next()){QMessageBox msgBox;msgBox.setText("该用户已存在!请重新注册!");msgBox.exec();return ;}//不存在就注册bool ok;QString username = QInputDialog::getText(this, "Angry Birds","User name:",QLineEdit::Normal,QDir::home().dirName(),&ok);if (ok && !username.isEmpty()){//向入据库中加入一条用户信息QString str = QString("insert into usertable values('%0', '%1', '%2', '0');")\.arg(le_account->text()).arg(le_password->text()).arg(username);//插入用户 账号,密码,用名QSqlQuery query;query.exec(str);QMessageBox msgBox;msgBox.setText("恭喜你!注册成功!");msgBox.exec();}
}
void Widget::login(bool)
{//账号√ 密码√QString str = QString("select * from usertable where account='%0' and password='%1';")\.arg(le_account->text()).arg(le_password->text());QSqlQuery query;query.exec(str);while(query.next()){qDebug() << query.value(0).toString();qDebug() << query.value(1).toString();qDebug() << query.value(2).toString();qDebug() << query.value(3).toString();emit login_successed();//发射登录成功的信号hide();//隐藏当前界面return ;}//账号√密码×str = QString("select * from usertable where account='%0';")\.arg(le_account->text());query.exec(str);while(query.next()){QMessageBox msgBox;msgBox.setText("密码错误!请重新输入!");msgBox.exec();return ;}//账号xQMessageBox msgBox;msgBox.setText("该用户不存在!请先注册!");msgBox.exec();
}
2.第二个模块 游戏开始界面
核心代码如下(示例):
Start::Start(QWidget *parent) : QWidget(parent)
{setFixedSize(1800,967);setGeometry(70,50,1800,967);this->setWindowIcon(QIcon(":/img/icon.png"));this->setWindowTitle("愤怒的小鸟");//界面跳转choose = new choosepoint;connect(this, &Start::start, this, [&](){choose->setGeometry(this->geometry());choose->show();});//绑定当前界面 发射的start开始游戏的信号 给选择关卡界面choose 让它显示connect(choose, &choosepoint::choosesceneback, this, [&](){this->setGeometry(choose->geometry());this->show();});//绑定choose选择关卡界面 发射的choosesceneback返回信号 给当前界面 让它显示/*connect(choose, &choosepoint::choosesceneback, [=](){//绑定choose选择关卡界面 发射的choosesceneback返回信号 给当前界面 让它显示choose->hide();this->show();});*/
}
void Start::paintEvent(QPaintEvent *event)
{QPainter p(this);p.drawPixmap(0, 0, 1800, 967, QPixmap(":/img/start.jpg"));p.drawPixmap(1713, 10, 77, 32, QPixmap(":/img/BackButton.png"));
}
void Start::mousePressEvent(QMouseEvent *event)
{//点击密码的显示与隐藏if(event->pos().x() > 760 && event->pos().x() < 1040 && event->pos().y() > 510 && event->pos().y() < 640){emit start();hide();//隐藏当前界面}if(event->pos().x() > 1713 && event->pos().x() < 1790 && event->pos().y() > 10 && event->pos().y() < 42){emit back();hide();//隐藏当前界面}
}
3.第三个模块 关卡选择界面
choosepoint::choosepoint(QWidget *parent) : QMainWindow(parent)
{//选择关卡场景this->setFixedSize(1800, 967);setGeometry(70,50,1800,967);this->setWindowIcon(QIcon(":/img/icon.png"));this->setWindowTitle("关卡场景");//返回按钮mybushbutton * backbtn = new mybushbutton(":/img/BackButton.png",":/img/BackButtonSelected.png");backbtn->setParent(this);backbtn->move(1713, 10);//跳转到上一个界面connect(backbtn, &mybushbutton::clicked,[=](){QTimer::singleShot(300,this,[=](){emit this->choosesceneback(); //为了看到动画效果hide();});});int i;//跳转到关卡界面 创建选择关卡的按钮for( i = 0; i < 20; i++){mybushbutton * menubtn = new mybushbutton(":/img/LevelIcon.png");menubtn->setParent(this);menubtn->move( 560 + i % 5 * 160, 300 + i / 5 * 130); //一维数构造二维数组connect(menubtn, &mybushbutton::clicked,[=](){this->hide();//隐藏当前界面//界面跳转shot = new slingshot(i + 1);shot->setGeometry(this->geometry());shot->show();//设置游戏场景初始位置//监听返回connect(shot, &slingshot::back, this, [=](){this->setGeometry(shot->geometry());shot->deleteLater();this->show();});//});QLabel * label = new QLabel;label->setParent(this);label->setFixedSize(menubtn->width(),menubtn->height());label->setText(QString::number(i+1));label->move(560 + i % 5 * 160, 300 + i / 5 * 130);//设置label上的文字对齐方式label->setAlignment(Qt::AlignHCenter | Qt:: AlignVCenter);//设置鼠标穿透事件 51号label->setAttribute(Qt::WA_TransparentForMouseEvents);}}
//重写绘图事件
void choosepoint::paintEvent(QPaintEvent *)
{QPainter painter(this);QPixmap pix;//加载图片pix.load(":/img/choose.jpg");painter.drawPixmap(0,0,this->width(),this->height(),pix);
}
4.第四个模块 游戏界面
void slingshot::mouseMoveEvent(QMouseEvent *event)
{//判断拉动皮筋if(event->pos().x() > 440 && event->pos().x() < 490 && event->pos().y() > 546 && event->pos().y() < 556)pullflag = true;if(pullflag && event->pos().x() >0 && event->pos().x() < 900 && event->pos().y() > 0 && event->pos().y() < 967)posline = event->pos();update();
}
void slingshot::mouseReleaseEvent(QMouseEvent *event)
{//判断在拉动皮筋后松开皮筋if(pullflag){emit Releaseline();check->b->current_vx = check->b->current_vy = 0;vx = 465 - posline.x();vy = 551 - posline.y();resistance_const = 0.0003;accg = -30.6;qDebug() << 465 - posline.x() << 551 - posline.y() << "hhhhh";posline = QPoint(465, 551);pullflag = false;}update();
}
void slingshot::mousePressEvent(QMouseEvent *event)
{//退出游戏if(event->pos().x() > 1740 && event->pos().x() < 1790 && event->pos().y() > 10 && event->pos().y() < 60){QMessageBox msgBox;msgBox.setText("你确定要退出游戏吗?");msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);if( QMessageBox::Yes == msgBox.exec()){emit back();hide();//隐藏当前界面}}
}void slingshot::slig(QPoint p)
{//判断拉动皮筋if(p.x() > 440 && p.x() < 490 && p.y() > 546 && p.y() < 556)pullflag = true;if(pullflag && p.x() >100 && p.x() < 763 && p.y() > 240 && p.y() < 840)posline = p;update();
}
5.第五个模块 鸟对象
void bird::port(qreal vx, qreal vy, qreal resistance_const, qreal accg)
{if(current_vy == 0 && current_vx == 0 && time == 0){current_vx = vx;current_vy = vy;this->resistance_const = resistance_const;this->accg = accg;}if(time == 0){wpos = this->geometry().topLeft();track_x = track_y = 0;}resistance_ax = resistance_const * current_vx * current_vx / bird_weight;//resistance_ay = resistance_const * current_vy * current_vy / bird_weight;//qDebug() << resistance_ax << "ax";last_vx = current_vx;current_vx -= (resistance_ax + 0.4 * 0.01);if(flag == true){current_vy += (accg * 0.1 + 2);energy -= (accg * 0.1 + 2);if(energy < 0)flag = false;}else{current_vy -= (accg * 0.1 - 2);energy += (accg * 0.1 - 2);if(current_vy < 0)flag = true;}if( qAbs(current_vx + last_vx) != qAbs(qAbs(current_vx) + qAbs(last_vx)) ) //单位统一{vx_flag = false;}time += 0.1;qDebug() << current_vx << "vx";qDebug() << current_vy << "vy";if(vx_flag == true) //{track_x += current_vx * 0.1;//track_x = vx * time - 1/2.0 * resistance_ax * time * time - 0.2 * time *time * time;}//last_y = track_y;track_y += current_vy * 0.1;//track_y = vy * time - 1/2.0 * accg * time * time ;//emit bird_move(track_x, track_y);qDebug() << wpos.x() + track_x << wpos.y() + track_y;move(wpos.x() + track_x , wpos.y() + track_y );if(wpos.x() + track_x > 1800 || wpos.y() + track_y > 967 || wpos.y() + track_y < 0 ||wpos.x() + track_x < 0 || (current_vx == 0 && current_vy == 0 )){//move(wpos);move(10 , 600);timer->stop();time = 0;track_x = track_y = 0;}emit bird_move(QPoint(geometry().topLeft().x() + width()/2,geometry().topLeft().y() + height()/2));}void bird::mouseMoveEvent(QMouseEvent *event)
{//move(event->globalX() - pos.x(), event->globalY() - pos.y());pos1 = event->globalPos();
// qDebug() << "pos1" << pos1.x() << pos1.y();
// qDebug() << "pos" << pos.x() << pos.y();
// qDebug() << "wpos" << wpos.x() << wpos.y();//qDebug() << wpos.x()+pos1.x()-pos.x() << wpos.y()+pos1.y()-pos.y() << "mouse";move(wpos.x()+pos1.x()-pos.x(),wpos.y()+pos1.y()-pos.y());emit bird_move(QPoint(geometry().topLeft().x() + width()/2,geometry().topLeft().y() + height()/2));
// qDebug() << "x " << geometry().topLeft().x() + width()/2 <<
// "y" << geometry().topLeft().y() + height()/2;}void bird::mousePressEvent(QMouseEvent *event)
{pos = event->globalPos();wpos = this->geometry().topLeft();if(event->buttons() == Qt::RightButton){//emit botton_clicek(50);current_vx = current_vy = 0;}// pos = event->pos();}void bird::paintEvent(QPaintEvent *event)
{QPainter p(this);p.drawPixmap(0, 0, *pix);}
总结
`本文章尚未完成,期待作者后续补充更改。。。。