源代码链接
链接:https://pan.baidu.com/s/1IrxgId0mN7WnNEX3WS-9KQ
提取码:hfcb
B站演示视频
https://www.bilibili.com/video/BV15B4y1k777/?vd_source=c3ed93afd505b51bdbde94d2ba5c28f6
代码分析
游戏开始界面
游戏的初始登陆界面,是由数据库与弹窗口实例化的界面、数据库和qt弹窗的相关功能和具体实现代码我会在后续的博客中补上
代码设计如下
#include "widget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPainter>
#include <QMouseEvent>
#include <QSqlQuery>
#include <QInputDialog>
#include <QMessageBox>
#include <QDir>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//界面主题设置
setFixedSize(960,600);
this->setWindowIcon(QIcon(":/img/red_bird.png"));
this->setWindowTitle("欢迎登陆");
//创建控件
le_account = new QLineEdit ;
le_account->setPlaceholderText("账号");
le_password = new QLineEdit ;
le_password->setPlaceholderText("密码");
bt_rgt = new QPushButton("注册") ;
bt_log = new QPushButton("登录") ;
//布局
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addWidget(bt_rgt);
hbox->addWidget(bt_log);
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(le_account);
vbox->addWidget(le_password);
vbox->addLayout(hbox);
box = new QWidget;
box->setLayout(vbox);
box->setParent(this);
box->setGeometry(710, 270,220,120);
//将按钮信号与对应信号与槽函数绑定
connect(bt_rgt, SIGNAL(clicked(bool)), this, SLOT(regiser(bool)));//绑定按钮bt_rgt 发射的clicked点击信号 给当前界面 的槽函数regiser
connect(bt_log, SIGNAL(clicked(bool)), this, SLOT(login(bool)));// 绑定按钮bt_log 发射的clicked点击信号 给当前界面 的槽函数login
//创建数据库
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("userdb");
db.open();
//创建用户名注册表
QString str("create table usertable(account text, password text, username text, level text);");
QSqlQuery query;
query.exec(str);
//界面跳转
start_ui = new Start;
connect(this, SIGNAL(login_successed()), start_ui, SLOT(show()));//绑定当前界面 发射的login_successed登录成功的信号 给游戏开始界面start_ui 让它显示
connect(start_ui, &Start::back, this, [&](){
//this->setGeometry(start_ui->geometry());
this->show();
});//绑定游戏开始界面start_ui 发射的back返回信号 给当前界面 让它显示
}
void Widget::paintEvent(QPaintEvent *event)
{
//画 界面 和 图标
QPainter p(this);
p.drawPixmap(0, 0, 960, 600, QPixmap(":/img/log.jpeg"));
if(show_key)
p.drawPixmap(920, 310, 32, 32, QPixmap(":/img/show.png"));
else
p.drawPixmap(920, 310, 32, 32, QPixmap(":/img/hide.png"));
}
void Widget::mousePressEvent(QMouseEvent *event)
{
//点击密码的显示与隐藏
if(event->pos().x() > 920 && event->pos().x() < 952 && event->pos().y() > 310 && event->pos().y() < 342)
{
show_key = !show_key;
if(show_key)
le_password->setEchoMode(QLineEdit::Normal);
else
le_password->setEchoMode(QLineEdit::Password);
}
update();
}
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.setWindowIcon(QIcon(":/img/red_bird.png"));
msgBox.setIconPixmap(QPixmap(":/img/icon.png"));
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.setWindowIcon(QIcon(":/img/red_bird.png"));
msgBox.setIconPixmap(QPixmap(":/img/icon.png"));
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.setWindowIcon(QIcon(":/img/red_bird.png"));
msgBox.setIconPixmap(QPixmap(":/img/icon.png"));
msgBox.setText("密码错误!请重新输入!");
msgBox.exec();
return ;
}
//账号x
QMessageBox msgBox;
msgBox.setWindowIcon(QIcon(":/img/red_bird.png"));
msgBox.setIconPixmap(QPixmap(":/img/icon.png"));
msgBox.setText("该用户不存在!请先注册!");
msgBox.exec();
}
Widget::~Widget()
{
}
游戏开始中转界面
登陆成功后将跳转到第二个界面,这个界面只是个普通的中转界面,可以点击back跳转回去,也可以点击“开始游戏”进入关卡选择
在这儿可以拓展添加一些类使该变的更加的优美
#include "start.h"
#include <QPainter>
#include <QMouseEvent>
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();//隐藏当前界面
}
}
开始游戏后进入关卡选择场景,
再该场景中可以选择进入哪一个关卡游戏
在该场景中使用了一个用一位数构造出二维数组的算法,而且该场景中选择的游戏,会在选择后再构造,在退出游戏后摧毁该场景类,清理内存空间
#include "choosepoint.h"
#include <QMenuBar>
#include <QPainter>
#include <QDebug>
#include "mybushbutton.h"
#include <QTimer>
#include <QLabel>
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);
}
游戏场景中的猪类
猪死亡时的爆炸特效砍了,因为会出现一些bug,具体改的方法我想的是需要重新改下这个猪类的设计方案,至少不能这么构造
#include "pig.h"
#include <QPainter>
#include <QTimer>
#include <QPixmap>
pig::pig()
{
setFixedSize(64, 64);
mid_pos = new QPoint(32, 32);
}
void pig::paintEvent(QPaintEvent *event)
{
QPainter p1(this);
// if(isboom)
// {
// QPainter p(pp);
// p.drawPixmap(0, 0, 64,64, QPixmap(":/img/boom.png"));
// }
// else
p1.drawPixmap(0, 0, 64,64, QPixmap(":/img/pig.png"));
}
void pig::boom( pig *p)
{
isboom = true;
//pp = p;
update();
QTimer::singleShot(200,this,[=](){
p->hide();
});
}
障碍物类
记录障碍物的中心点,方便后续中碰撞做算法
#include "obstacles.h"
#include <QPixmap>
#include <QDebug>
#include <QBitmap>
#include <QPainter>
#include <QTimer>
ObstAcles::ObstAcles(QString normalImg)
{
ImagPath = normalImg;
pix = new QPixmap;
bool ret = pix->load(normalImg);
if(!ret){
qDebug() << "图片加载失败";
return;
}
setFixedSize(pix->width(), pix->height());
*pix = pix->scaled(pix->width() , pix->height() );
setMask( pix->mask() );
setMinimumHeight(pix->height());
setMinimumWidth(pix->width());
mid_width = pix->width();
mid_height = pix->width();
qDebug() << "obsacles " << "w " << mid_width << "h " << mid_height;
mid_pos = new QPoint(pix->width() / 2, pix->height() / 2);
//mid_pos = QPoint(pix->width() / 2, pix->height() / 2);
}
void ObstAcles::paintEvent(QPaintEvent *event)
{
QPainter p(this);
p.drawPixmap(0, 0, *pix);
}
鸟类
主要是对鸟的运动状态的算法,port槽函数中 传参分别是 x方向初速度、y方向初速度、空气阻力常数、重力加速度
让小鸟动起来的主要思想是,给一个信号触发定时器,让定时器超时检测的信号去触发这个槽,只有第一次的时候才会给当前速度赋值,其他状态都是当前速度的积分来提供运动轨迹。
#include "bird.h"
#include <QPixmap>
#include <QDebug>
#include <QBitmap>
#include <QPainter>
#include <QTimer>
bird::bird(QString normalImg)
{
ImagPath = normalImg;
pix = new QPixmap;
bool ret = pix->load(normalImg);
if(!ret){
qDebug() << "图片加载失败";
return;
}
*pix = pix->scaled(pix->width() * 0.08, pix->height() * 0.08);
setFixedSize(pix->width() * 0.08, pix->height() * 0.08);
setMask( pix->mask() );
setMinimumHeight(pix->height());
setMinimumWidth(pix->width());
mid_width = pix->width() * 0.08;
mid_height = pix->height() * 0.08;
qDebug() << "brid " << "w " << mid_width << "h " << mid_height;
mid_pos = new QPoint(pix->width() * 0.08 / 2, pix->height() * 0.08 / 2);
//mid_pos = QPoint(pix->width() * 0.08 / 2, pix->height() * 0.08 / 2);
time = 0;
bird_weight = 3;
vx_flag = true;
flag_move = false;
timer = new QTimer(this);
}
void bird::port(qreal vx, qreal vy, qreal resistance_const, qreal accg) //自己模拟的控器环境
{
if(current_vy == 0 && current_vx == 0 && time == 0) //速度为和时间都为0时重新获取当前速度
{
current_vx = vx;
current_vy = vy;
if(vy > 0)
{
flag = true;
}else {
flag = false;
}
this->resistance_const = resistance_const;
this->accg = accg;
}
if(time == 0) //时间为0时重置获取当前左上角位置
{
wpos = this->geometry().topLeft();
track_x = track_y = 0;
}
resistance_ax = resistance_const * current_vx * current_vx / bird_weight; //模拟空气阻力
last_vx = current_vx;
if(current_vx > 0)
{
current_vx -= (resistance_ax + 0.4 * 0.01);
}else if(current_vx < 0)
{
current_vx += (resistance_ax + 0.4 * 0.01);
}
if(flag == true) //y方向上的运动
{
current_vy += (accg * 0.1 - 0.9);
energy -= (accg * 0.1 + 0.9);
if(energy < 0)
flag = false;
}else
{
current_vy += (accg * 0.1 + 0.9);
energy += (accg * 0.1);
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) // x方向上的运动
{
track_x += current_vx * 0.1;
}
track_y += current_vy * 0.1;
qDebug() << wpos.x() + track_x << wpos.y() + track_y;
qDebug() << "time :" << time;
if(time > 25.0) //超过25个时钟点重置小鸟
{
current_vx = 0;
current_vy = 0;
}
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 )) //超过界面范围、速度为0重置小鸟
{
//move(wpos);
move(70 , 620);
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) //重写鼠标事件,时小鸟可拖动
{
pos1 = event->globalPos();
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));
}
void bird::mousePressEvent(QMouseEvent *event)
{
flag_move = true;
pos = event->globalPos();
wpos = this->geometry().topLeft();
if(event->buttons() == Qt::RightButton)
{
current_vx = current_vy = 0;
}
}
//void bird::mouseReleaseEvent(QMouseEvent *event)
//{
// flag_move = false;
//}
void bird::paintEvent(QPaintEvent *event)
{
QPainter p(this);
p.drawPixmap(0, 0, *pix);
}
游戏场景物体的构建
目前只为前四关写了障碍物和猪的布局分布效果,在该类中,有小鸟对障碍物碰撞后小鸟运动轨迹改变的算法,在该类中碰撞穿模的bug是因为我是对单个方块分析的,在取模上可能有一些误差,总而言之就是算法问题,会出现穿模的bug,这个bug的触发几率也不是特别大。
#include "datacheck.h"
#include <QDebug>
#include <QTimer>
#include <QtGlobal>
datacheck::datacheck(int c, QWidget * shot) //c为关卡 shot为关卡界面
{
QVector< QPoint > v1;
b = new bird(":/img/red_bird.png");
b->setParent(shot);
b->move(70 , 620);
flag = true;
if(c == 1)
{
for(int i = 0; i < 10; i++)
{
acl_1 = new ObstAcles(":/img/obstacles_1.png");
acl_1->setParent(shot);
acl_1->move(340 + i%10 * acl_1->width(), 140 + i/10 * acl_1->height());
v1.push_back(QPoint(acl_1->mid_pos->x() + acl_1->geometry().topLeft().x() ,
acl_1->mid_pos->y() + acl_1->geometry().topLeft().y()));
}
for(int i = 0; i < 10; i++)
{
acl_2 = new ObstAcles(":/img/obstacles_2.png");
acl_2->setParent(shot);
acl_2->move(0 + i%10 * acl_2->width(), 340 + i/10 * acl_2->height());
v1.push_back(QPoint(acl_2->mid_pos->x() + acl_2->geometry().topLeft().x() ,
acl_2->mid_pos->y() + acl_2->geometry().topLeft().y()));
}
for(int i = 0; i < 10; i++)
{
acl_3 = new ObstAcles(":/img/obstacles_3.png");
acl_3->setParent(shot);
acl_3->move(680 + i%10 * acl_3->width(), 340 + i/10 * acl_3->height());
v1.push_back(QPoint(acl_3->mid_pos->x() + acl_3->geometry().topLeft().x() ,
acl_3->mid_pos->y() + acl_3->geometry().topLeft().y()));
}
for(int i = 0; i < 5; i ++)
{
p = new pig;
p->setParent(shot);
p->move(650 + i%10 * p->width(), 650 + i/10 * p->height());
ppoint.push_back(QPoint(p->mid_pos->x() + p->geometry().topLeft().x() ,
p->mid_pos->y() + p->geometry().topLeft().y()));
ppig.push_back(p);
}
}
if(c == 2)
{
for(int i = 0; i < 10; i++)
{
acl_1 = new ObstAcles(":/img/obstacles_1.png");
acl_1->setParent(shot);
acl_1->move(340 + i%10 * acl_1->width(), 440 + i/10 * acl_1->height());
v1.push_back(QPoint(acl_1->mid_pos->x() + acl_1->geometry().topLeft().x() ,
acl_1->mid_pos->y() + acl_1->geometry().topLeft().y()));
}
for(int i = 0; i < 10; i++)
{
acl_2 = new ObstAcles(":/img/obstacles_2.png");
acl_2->setParent(shot);
acl_2->move(0 + i%10 * acl_2->width(), 740 + i/10 * acl_2->height());
v1.push_back(QPoint(acl_2->mid_pos->x() + acl_2->geometry().topLeft().x() ,
acl_2->mid_pos->y() + acl_2->geometry().topLeft().y()));
}
for(int i = 0; i < 10; i++)
{
acl_3 = new ObstAcles(":/img/obstacles_3.png");
acl_3->setParent(shot);
acl_3->move(680 + i%10 * acl_3->width(), 740 + i/10 * acl_3->height());
v1.push_back(QPoint(acl_3->mid_pos->x() + acl_3->geometry().topLeft().x() ,
acl_3->mid_pos->y() + acl_3->geometry().topLeft().y()));
}
for(int i = 0; i < 5; i ++)
{
p = new pig;
p->setParent(shot);
p->move(650 + i%10 * p->width(), 650 + i/10 * p->height());
ppoint.push_back(QPoint(p->mid_pos->x() + p->geometry().topLeft().x() ,
p->mid_pos->y() + p->geometry().topLeft().y()));
ppig.push_back(p);
}
}
if(c == 3)
{
for(int i = 0; i < 20; i++)
{
acl_1 = new ObstAcles(":/img/obstacles_1.png");
acl_1->setParent(shot);
acl_1->move(0 + i%1 * acl_1->width(), 0 + i/1 * acl_1->height());
v1.push_back(QPoint(acl_1->mid_pos->x() + acl_1->geometry().topLeft().x() ,
acl_1->mid_pos->y() + acl_1->geometry().topLeft().y()));
}
for(int i = 0; i < 20; i++)
{
acl_2 = new ObstAcles(":/img/obstacles_2.png");
acl_2->setParent(shot);
acl_2->move(1700 + i%1 * acl_2->width(), 0 + i/1 * acl_2->height());
v1.push_back(QPoint(acl_2->mid_pos->x() + acl_2->geometry().topLeft().x() ,
acl_2->mid_pos->y() + acl_2->geometry().topLeft().y()));
}
for(int i = 0; i < 30; i++)
{
acl_3 = new ObstAcles(":/img/obstacles_3.png");
acl_3->setParent(shot);
acl_3->move(0 + i%30 * acl_3->width(), 740 + i/30 * acl_3->height());
v1.push_back(QPoint(acl_3->mid_pos->x() + acl_3->geometry().topLeft().x() ,
acl_3->mid_pos->y() + acl_3->geometry().topLeft().y()));
}
for(int i = 0; i < 9; i ++)
{
p = new pig;
p->setParent(shot);
p->move(650 + i%3 * p->width(), 650 + i/3 * p->height());
ppoint.push_back(QPoint(p->mid_pos->x() + p->geometry().topLeft().x() ,
p->mid_pos->y() + p->geometry().topLeft().y()));
ppig.push_back(p);
}
}
if(c == 4)
{
for(int i = 0; i < 20; i++)
{
acl_1 = new ObstAcles(":/img/obstacles_1.png");
acl_1->setParent(shot);
acl_1->move(0 + i%1 * acl_1->width(), 0 + i/1 * acl_1->height());
v1.push_back(QPoint(acl_1->mid_pos->x() + acl_1->geometry().topLeft().x() ,
acl_1->mid_pos->y() + acl_1->geometry().topLeft().y()));
}
for(int i = 0; i < 20; i++)
{
acl_2 = new ObstAcles(":/img/obstacles_2.png");
acl_2->setParent(shot);
acl_2->move(1700 + i%1 * acl_2->width(), 0 + i/1 * acl_2->height());
v1.push_back(QPoint(acl_2->mid_pos->x() + acl_2->geometry().topLeft().x() ,
acl_2->mid_pos->y() + acl_2->geometry().topLeft().y()));
}
for(int i = 0; i < 30; i++)
{
acl_3 = new ObstAcles(":/img/obstacles_3.png");
acl_3->setParent(shot);
acl_3->move(0 + i%30 * acl_3->width(), 740 + i/30 * acl_3->height());
v1.push_back(QPoint(acl_3->mid_pos->x() + acl_3->geometry().topLeft().x() ,
acl_3->mid_pos->y() + acl_3->geometry().topLeft().y()));
}
for(int i = 0; i < 30; i++)
{
acl_3 = new ObstAcles(":/img/obstacles_3.png");
acl_3->setParent(shot);
acl_3->move(0 + i%30 * acl_3->width(), 0 + i/30 * acl_3->height());
v1.push_back(QPoint(acl_3->mid_pos->x() + acl_3->geometry().topLeft().x() ,
acl_3->mid_pos->y() + acl_3->geometry().topLeft().y()));
}
for(int i = 0; i < 3; i ++)
{
p = new pig;
p->setParent(shot);
p->move(650 + i%3 * p->width(), 650 + i/3 * p->height());
ppoint.push_back(QPoint(p->mid_pos->x() + p->geometry().topLeft().x() ,
p->mid_pos->y() + p->geometry().topLeft().y()));
ppig.push_back(p);
}
for(int i = 0; i < 5; i ++)
{
p = new pig;
p->setParent(shot);
p->move(100 + i%3 * p->width()*2, 70 + i/3 * p->height()*2);
ppoint.push_back(QPoint(p->mid_pos->x() + p->geometry().topLeft().x() ,
p->mid_pos->y() + p->geometry().topLeft().y()));
ppig.push_back(p);
}
for(int i = 0; i < 6; i ++)
{
p = new pig;
p->setParent(shot);
p->move(360 + i%2 * p->width(), 200 + i/2 * p->height());
ppoint.push_back(QPoint(p->mid_pos->x() + p->geometry().topLeft().x() ,
p->mid_pos->y() + p->geometry().topLeft().y()));
ppig.push_back(p);
}
}
mpoint.insert(1, v1);
v1.clear();
//测试数据
for( QMap<int, QVector< QPoint > >::iterator it = mpoint.begin();it != mpoint.end();it++ )
{
for(QVector<QPoint>::iterator it2 = (*it).begin(); it2!= (*it).end();it2++)
{
qDebug() << it2->x() << it2->y();
}
qDebug() << endl;
}
connect(b, SIGNAL(bird_move(QPoint)), this, SLOT(Pig_Crash(QPoint))); //小鸟与猪碰撞
connect(b, SIGNAL(bird_move(QPoint)), this, SLOT(Crash(QPoint))); //小鸟与墙碰撞
connect(this, &datacheck::Crash_sign, [&](int direc){
if(direc == 0)
{
qDebug() << "sss";
b->current_vy *= (-1);
}
//下碰撞
else if(direc == 1)
{
qDebug() << "sss";
b->current_vy *= (-1);
}
//左碰撞
else if(direc == 2)
{
b->current_vx *= (-1);
}
//右碰撞
else if(direc == 3)
{
b->current_vx *= (-1);
}
//对角碰撞
else
{
b->current_vx *= (-1);
b->current_vy *= (-1);
}
});
}
void datacheck::Pig_Crash(QPoint pos)
{
QVector<pig *>::iterator it1 = ppig.begin();
for(QVector<QPoint>::iterator it2 = ppoint.begin(); it2!= ppoint.end();it2++)
{
if(flag == true)
{
if(qAbs(it2->x() - pos.x()) <= qAbs(70) && qAbs(it2->y() - pos.y()) <= qAbs(70) )
{
//碰撞
p->boom(*it1);
qDebug() << "碰撞" << it2->x() << it2->y();
}
}else
{
QTimer::singleShot(400, this, [=](){
flag = true;
});
}
it1++;
}
}
void datacheck::Crash(QPoint pos)
{
int count = 0;
for( QMap<int, QVector< QPoint > >::iterator it = mpoint.begin();it != mpoint.end();it++ )
{
for(QVector<QPoint>::iterator it2 = (*it).begin(); it2!= (*it).end();it2++)
{
if(flag == true)
{
if(qAbs(it2->x() - pos.x()) <= qAbs(70) && qAbs(it2->y() - pos.y()) <= qAbs(70) )
{
//碰撞
qDebug() << "碰撞" << it2->x() << it2->y();
if( (it2->x() - pos.x()) > 0 && (it2->y() - pos.y()) > 0)
{
if(qAbs(it2->x() - pos.x()) - qAbs(it2->y() - pos.y()) > qAbs(0))
{
if((it2+1) != nullptr)
{
if(qAbs((it2+1)->x() - it2->x()) <= qAbs(70) && qAbs((it2+1)->x() - it2->x()) >= qAbs(60))
continue;
}
if((it2-1) != nullptr)
{
if(qAbs((it2-1)->x() - it2->x()) <= qAbs(70) && qAbs((it2+1)->x() - it2->x()) >= qAbs(60))
continue;
}
qDebug() << "左边";
emit Crash_sign(2);
}else if(qAbs(it2->y() - pos.y()) - qAbs(it2->x() - pos.x()) > qAbs(0))
{
if((it2+1) != nullptr)
{
if(qAbs((it2+1)->y() - it2->y()) <= qAbs(70) && qAbs((it2+1)->y() - it2->y()) >= qAbs(60))
continue;
}
if((it2-1) != nullptr)
{
if(qAbs((it2-1)->y() - it2->y()) <= qAbs(70) && qAbs((it2+1)->y() - it2->y()) >= qAbs(60))
continue;
}
qDebug() << "上边";
emit Crash_sign(0);
}else
{
emit Crash_sign(4);
//对角撞
}
//第二象限
qDebug() << "第二象限";
}else if( (it2->x() - pos.x()) > 0 && (it2->y() - pos.y()) < 0)
{
if( qAbs(it2->x() - pos.x()) - qAbs(it2->y() - pos.y()) > qAbs(0))
{
if((it2+1) != nullptr)
{
if(qAbs((it2+1)->x() - it2->x()) <= qAbs(70) && qAbs((it2+1)->x() - it2->x()) >= qAbs(60))
continue;
}
if((it2-1) != nullptr)
{
if(qAbs((it2-1)->x() - it2->x()) <= qAbs(70) && qAbs((it2+1)->x() - it2->x()) >= qAbs(60))
continue;
}
qDebug() << "左边";
emit Crash_sign(2);
}else if(qAbs(it2->y() - pos.y()) - qAbs(it2->x() - pos.x()) > qAbs(0))
{
if((it2+1) != nullptr)
{
if(qAbs((it2+1)->y() - it2->y()) <= qAbs(70) && qAbs((it2+1)->y() - it2->y()) >= qAbs(60))
continue;
}
if((it2-1) != nullptr)
{
if(qAbs((it2-1)->y() - it2->y()) <= qAbs(70) && qAbs((it2+1)->y() - it2->y()) >= qAbs(60))
continue;
}
qDebug() << "下边";
emit Crash_sign(1);
}else
{
//对角撞
emit Crash_sign(5);
}
//第三象限
qDebug() << "第三象限";
}else if( (it2->x() - pos.x()) < 0 && (it2->y() - pos.y()) > 0)
{
if(qAbs(it2->x() - pos.x()) > qAbs(it2->y() - pos.y()) > qAbs(0))
{
if((it2+1) != nullptr)
{
if(qAbs((it2+1)->x() - it2->x()) <= qAbs(70) && qAbs((it2+1)->x() - it2->x()) >= qAbs(60))
continue;
}
if((it2-1) != nullptr)
{
if(qAbs((it2-1)->x() - it2->x()) <= qAbs(70) && qAbs((it2+1)->x() - it2->x()) >= qAbs(60))
continue;
}
qDebug() << "右边";
emit Crash_sign(3);
}else if(qAbs(it2->y() - pos.y()) - qAbs(it2->x() - pos.x()) > qAbs(0))
{
if((it2+1) != nullptr)
{
if(qAbs((it2+1)->y() - it2->y()) <= qAbs(70) && qAbs((it2+1)->y() - it2->y()) >= qAbs(60))
continue;
}
if((it2-1) != nullptr)
{
if(qAbs((it2-1)->y() - it2->y()) <= qAbs(70) && qAbs((it2+1)->y() - it2->y()) >= qAbs(60))
continue;
}
qDebug() << "上边";
emit Crash_sign(0);
}else
{
//对角撞
emit Crash_sign(6);
}
//第一象限
//qDebug() << "第一象限";
}else if( (it2->x() - pos.x()) < 0 && (it2->y() - pos.y()) < 0)
{
if(qAbs(it2->x() - pos.x()) - qAbs(it2->y() - pos.y()) > qAbs(0))
{
if((it2+1) != nullptr)
{
if(qAbs((it2+1)->x() - it2->x()) <= qAbs(70) && qAbs((it2+1)->x() - it2->x()) >= qAbs(60))
continue;
}
if((it2-1) != nullptr)
{
if(qAbs((it2-1)->x() - it2->x()) <= qAbs(70) && qAbs((it2+1)->x() - it2->x()) >= qAbs(60))
continue;
}
qDebug() << "右边";
emit Crash_sign(3);
}else if(qAbs(it2->y() - pos.y()) - qAbs(it2->x() - pos.x()) > qAbs(0))
{
if((it2+1) != nullptr)
{
if(qAbs((it2+1)->y() - it2->y()) <= qAbs(70) && qAbs((it2+1)->y() - it2->y()) >= qAbs(60))
continue;
}
if((it2-1) != nullptr)
{
if(qAbs((it2-1)->y() - it2->y()) <= qAbs(70) && qAbs((it2+1)->y() - it2->y()) >= qAbs(60))
continue;
}
qDebug() << "下边";
emit Crash_sign(1);
}else
{
//对角撞
emit Crash_sign(7);
}
//第四象限
qDebug() << "第四象限";
}
flag = false;
}
}else
{
QTimer::singleShot(200, this, [=](){
flag = true;
});
}
count++;
}
//qDebug() << endl;
}
}
void datacheck::paintEvent(QPaintEvent *event)
{
}
void datacheck::mouseMoveEvent(QMouseEvent *event)
{
qDebug() << b->x() << b->y();
}
void datacheck::mousePressEvent(QMouseEvent *event)
{
}
感谢大家的支持。