前言:本文章会详细介绍难点的内容,不附带全部源码,会将关键代码进行展示。因为只有截图,这里在每一个动作和界面都添加了音效与BGM,同时附加了CG展示。
素材和音效全部放在下面了,需要可自行提取。
先来看效果:
右上角为游戏设置界面。
打中后猪类特效变化(同时猪类具有爆炸音效)
这里没有写"继续游戏",因为太简单,只需要hide界面再show就行了。
刚进去会播放一个MV...(这里随便添加了一个....)
然后会跳转至正常的客户端界面(这里没有写返回按钮,因为是拿demo给大家讲解的)
------------------------------------------------------我是分割线----------------------------------------------------------
好的,那么接下来将详细讲解困难点的思路。(game界面可直接使用,含重力引擎)
困难点:重力引擎的定制、界面切换的管理、数据库的对接与解析。
确定我们需要的界面(五个),通过信号进行切换,每一个界面有一个独特信号。每当发出信号时,在管理界面进入槽函数进行切换。
如下: 先创建【所有界面】在【管理界面】。
mange::mange(QObject *parent) : QObject(parent)
{
Mysp =new QMediaPlayer; //按钮音效
Mysp->setMedia(QUrl("D:/QTproject/MyQtProject/music/bird.wav"));
StOne= new Start;//登录界面实例化
StTwo= new zhuce;//注册界面实例化
Game =new GAME;//游戏界面
Setting=new setting;//设置界面
ClientAndServer=new clietandserver;//客户端界面
this->ClientAndServer->timer->stop();
AllSignal();//所有的连接信号公有制函数
}
void mange::AllSignal()
{
connect(StOne,SIGNAL(jumptozhuce()),this,SLOT(JumpToZhuce()));//登录跳注册
connect(StTwo,SIGNAL(jumptodenglu()),this,SLOT(JumpToDenglu()));//注册跳登录
connect(StOne,SIGNAL (jumptogame()),this,SLOT(JumpToGame()));//登录跳游戏
connect(Game,SIGNAL(jumptosetting()),this,SLOT(JumpToSetting()));//游戏跳设置
connect(Setting,SIGNAL(Setting_Back()),this,SLOT(JumpToDenglu())); //设置跳登录
connect(Setting,SIGNAL(Setting_PlayAgain()),this,SLOT(JumpToGame()));//设置跳游戏
connect(Setting,SIGNAL(Setting_Music()),this,SLOT(CloseMusic()));//设置界面里面的关闭音乐信号
connect(Setting,SIGNAL(Setting_advice()),this,SLOT(JumpToAdvice()));//设置跳客户端
}
void mange::JumpToZhuce()//槽函数 【登录跳注册】
{
Mysp->play(); //播放器 注册界面专用
this->Setting->PLAY->stop();//停止设置界面的BGM
this->Game->PLAY->stop();//停止游戏界面的BGM
this->StOne->PLAY->stop();//停止登录界面的BGM
this->StOne->close();//关闭登录界面
this->Game->close(); //关闭游戏界面
this->Setting->close();//关闭设置界面
delete this->StTwo;//释放上一个注册界面,以保证进入的界面是全新的,防止内存泄漏
this->StTwo=new zhuce;//创建新注册界面
this->StTwo->show(); //跳转至注册界面
this->StTwo->PLAY->play();//开启注册界面BGM
this->ClientAndServer->timer->stop();//关闭在客户端界面的计时器(控制视频播放的计时器,在客户端界面new的时候会走构造函数激活导致视频播放,关闭其计时器保证其不影响其他函数)
AllSignal();
}
其他的跳转和上面是一样的,删除跳转界面对象,重新创建并展示,同时停止其他的界面BGM和显示
数据库H文件
#ifndef NEWSQLITE_H
#define NEWSQLITE_H
#include "sqlite3.h"
#include
#include
#include
class NewSQLITE
{
public:
static NewSQLITE* CreateS(); //创建的数据函数
static NewSQLITE* MySql; //与创建函数进行关联使用
int Insert(char*sql);//插入数据操作(注册)
int Find();//进行确定注册人数的函数
int Select(char*NAME,char*PWD);//登录密码与账号的检测
sqlite3*db;
private:
NewSQLITE();
};
#endif // NEWSQLITE_H
#include "NewSQLITE.h"
NewSQLITE* NewSQLITE::MySql=nullptr;//初始化静态数据成员
NewSQLITE::NewSQLITE() //调取函数时,直接在构造里将其打开及建表
{
char *Message;
int res =sqlite3_open("information.db",&db);
if(res!=0){qDebug()<<"数据库打开失败";}
qDebug()<<"数据库已打开";
QByteArray sql="create table if not exists Code( ID int primary key not null,Name text,PWD text);";
int bc = sqlite3_exec(db, sql.data(),nullptr,nullptr,&Message);
if(bc<0){qDebug()<<"数据表创建失败";}
qDebug()<<"数据表已创建";
qDebug()<<"我"<
game.h文件
#ifndef GAME_H
#define GAME_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "pig.h"
#include "changebutton.h"
class GAME: public QWidget
{
Q_OBJECT
public:
explicit GAME(QWidget *parent = nullptr);
void ChangePic();
void paintEvent(QPaintEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void TreePic();
void TreePic2();
void mouseReleaseEvent(QMouseEvent*event);
void GradePic(int LEFT);
void CreatePig();
public:
int x,y; int jisuan=0; //计算
int flag= 1; int LEFT=3; //生命下标
float Q; float Z=1; float S;//物理引擎系数
QMediaPlayer * PLAY;//界面BGM
QMediaPlayer* Temp;//音效
QMediaPlayer* BOOMMUSIC;//猪爆炸音效
QMediaPlayer* DanMUSIC;//弹弓拉伸音效
changebutton *SET;//右上角的设置按钮图片
QTimer timer1;//开头直接激活,将鸟从地面飞到弹弓上
QTimer timer2;//鼠标松开后,进行鸟飞翔位置移动定时器
QTimer timer3;//分数实时计算的计时器
QTimer timer4;//碰撞检测定时器
QPixmap *pix;//鸟
QPixmap *pixtree;//右边的树
QPixmap *lpixtree;//左边的树2
QLabel* Grade;//实时生命值
QLabel *Pic;//实时刷新的图片
QLabel*bird;
QLabel* tree;
QLabel* tree2;
QLabel* Tip;
QLabel *Pig1;
QLabel *Pig2;
QLabel *Pig3;
QLabel *Pig4;
public:
pig*A1; pig*A2; pig*A3;pig*A4;//猪类指针(此类规定猪的图片大小)
signals:
void backtodenglu();
void jumptosetting();
public slots:
void ReGo();
void JumpTree();
void SHowGrade();
void BOOM();
void GOSetting();
};
#endif // GAME_H
game.cpp文件
#include "GAME.h"
GAME::GAME(QWidget *parent) : QWidget(parent)
{
setFixedSize(1500,800);
x=160; y=660;//初始化鸟的位置
timer1.start(10); //起始跳位置
setGeometry(70,50,1500,800); //建立界面最大长度和初始长度
this->setWindowIcon(QIcon(":/photo/redbird.webp"));
this->setWindowTitle("愤怒的小鸟");
SET=new changebutton(this);
Grade=new QLabel(this);//生命标签
Pic=new QLabel(this); //插图标签
Tip=new QLabel(this);//分数标签
PLAY=new QMediaPlayer;
Temp=new QMediaPlayer;
BOOMMUSIC=new QMediaPlayer;
DanMUSIC=new QMediaPlayer;
Pig2= new QLabel(this);
Pig3= new QLabel(this);Pig4= new QLabel(this);
Pig1= new QLabel(this);
PLAY->setMedia(QUrl("D:/QTproject/MyQtProject/music/BGMjiemian.mp3"));
SET->setStyleSheet("border-image:url(:/photo/设置图标.png)");
SET->setGeometry(1395,28,40,40);
TreePic();//树的右边
CreatePig();
ChangePic();//鸟类的图源定制及初始位置
TreePic2();//树的左边
connect(&timer1,SIGNAL(timeout()),this,SLOT(JumpTree()));
connect(&timer2,SIGNAL(timeout()),this,SLOT(ReGo())) ;
connect(&timer3,SIGNAL(timeout()),this,SLOT(SHowGrade()));
connect(&timer4,SIGNAL(timeout()),this,SLOT(BOOM()));
connect(SET,SIGNAL(clicked()),this,SLOT(GOSetting()));
GradePic(LEFT); //创建生命
SHowGrade(); //创建分数
}
void GAME::paintEvent(QPaintEvent *event)
{
if(event == nullptr) {qDebug()<<"event";}
QPainter A(this);
A.drawPixmap(0,0,1500,800,QPixmap(":/photo/Gamejiemian.png"));
GradePic(LEFT);
}
void GAME::ChangePic() //鸟类的图源定制及初始位置
{
bird=new QLabel(this);
pix=new QPixmap;
this->pix->load(":/photo/bird.png");//下载红鸟图片源文件
*pix = pix->scaled(pix->width() * 0.8, pix->height() * 0.8);//将图片调整为大小0.8
this->bird->setPixmap(*pix);
}
void GAME::TreePic()//右边弹弓的图元定制
{
tree=new QLabel(this);
pixtree=new QPixmap;
this->pixtree->load(":/photo/dangong1 (1).png");//下载右弹弓图片源文件
*pixtree = pixtree->scaled(pixtree->width(), pixtree->height()*0.7);//将图片调整为大小0.8
this->tree->setPixmap(*pixtree);
this->tree->move(330,556);
}
void GAME::TreePic2()
{
tree2=new QLabel(this);
lpixtree=new QPixmap;
this->lpixtree->load(":/photo/dangong2.png");//下载右弹弓图片源文件
*lpixtree = lpixtree->scaled(lpixtree->width(), lpixtree->height()*0.7);//将图片调整为大小0.8
this->tree2->setPixmap(*lpixtree);
this->tree2->move(300,551);
}
void GAME::JumpTree()
{
this->bird->move(x,y);
if(x<=318||y>=558)
{
x=x+3; y=y-2;
this->bird->move(x,y);
update();
}
else if(x>318)
{
timer1.stop();
}
}
void GAME::SHowGrade()//计算分数的内容
{
int F=this->x; int C=this->y;
QString N=QString("单次飞跃分数:")+QString::number((F*C)-105600);
Tip->setFixedSize(300,30);
Tip->setText(N);
// Tip->setScaledContents(true);
Tip->setStyleSheet("font:78 15pt Bodoni MT");
Tip->move(0,40);
int BB=this->jisuan;
QString Temp = Tip->text();
int CC=Temp.toInt();
int FF =BB+CC;
this->jisuan=FF;
}
void GAME::mouseReleaseEvent(QMouseEvent *event)//启动分数、移动定时器
{
if(event->x()>50&&event->x()<350&&event->y()<660&&event->y()>460)
{
QString W =QString::number(event->x());
QString Y=QString::number(event->y());
qDebug()<<"W=="<x =W.toFloat(); this->y=Y.toFloat();
if(x>50&&x<350&&y<660&&y>460)//第三象限
{
Temp->setMedia(QUrl("D:/QTproject/MyQtProject/music/bird.wav"));
Temp->play();
this->Q= ( (250-x)+(y-556) )/25; //初始飞行系数
this->Z =(Q/0.8);//递减飞行系数
this->S = Z-Q;
timer2.start(10);//飞行定时器
timer3.start(10);//飞行定时器
timer4.start(10);//碰撞定时器
}
}
}
void GAME::mouseMoveEvent(QMouseEvent *event)//鼠标移动并按下的事件
{
if(event->x()>50&&event->x()<350&&event->y()<660&&event->y()>460)
{
QString W =QString::number(event->x());
QString Y=QString::number(event->y());
this->x =W.toInt(); this->y=Y.toInt();
if(event->buttons()==Qt::LeftButton)
{
if(x>50&&x<350&&y<660&&y>460&&timer1.isActive()==false)
{
DanMUSIC->setMedia(QUrl("D:/QTproject/MyQtProject/music/LGMusic.wav"));
DanMUSIC->play();
this->bird->move(x,y);
qDebug()<<"x=="<=50&&y<=660&&timer1.isActive()==false)
{
qDebug()<<"Q=="<0){S +=0.1;}
if(flag>10)
{
this->x += S; //横向飞行速度
this->y -= Z; //纵向飞行速度
Z -=0.1;
}
else if(flag<=10)
{
this->x += S; //横向飞行速度
this->y -= Z; //纵向飞行速度
}
qDebug()<<"X=="<bird->move(x,y);
update();
if(this->y>=661)
{
if(this->LEFT ==1)
{
QMessageBox Grade;
Grade.information(this,"游戏结束","您的手法和蔡徐坤一样菜",QMessageBox::Yes);
emit jumptosetting();
}
else
{
qDebug()<<"timer111";
Sleep(1500);
this->x=160;
this->y=660;//重置
this->LEFT--;
timer2.stop();
timer3.stop();
timer1.start(8);
qDebug()<<"11";
}
}
}
}
void GAME::GradePic(int SS)
{
Grade->setStyleSheet("font:75 15pt Bodoni MT");
if(SS==2)
{
QString A=QString("剩余生命值:")+QString::number(SS-1);
Grade->setText(A);
Pic->setPixmap(QPixmap(":/photo/dangong1 (10).png"));
}
else if (SS==3)
{ QString A=QString("剩余生命值:")+QString::number(SS-1);
Grade->setText(A);
Pic->setFixedSize(25,25);
Pic->setScaledContents(true);
Pic->setPixmap(QPixmap(":/photo/bird.png"));
}
else if(SS==1)
{ QString A=QString("剩余生命值:")+QString::number(SS-1);
Grade->setText(A);
Pic->setPixmap(QPixmap(":/photo/dangong1 (9).png"));
}
Grade->move(5,0);//鸟
Pic->move(155,2);
update();
}
void GAME::CreatePig()
{
A1=new pig(this); A1->move(1300,655);
A2=new pig(this); A2->move(1340,305);
A3=new pig(this); A3->move(1060,405);
A4=new pig(this); A4->move(1160,505);
}
void GAME::GOSetting()
{
PLAY->stop();
emit jumptosetting();
}
void GAME::BOOM()
{
if(x>A1->x()-20&&x<(A1->x()+30))
{
if(this->y>A1->y()-20&&this->yy()+20)
{
if(this->A1->isVisible());
{
BOOMMUSIC->setMedia(QUrl("D:/QTproject/MyQtProject/music/BOOM.mp3"));
BOOMMUSIC->play();
this->A1->hide();
Pig1->setPixmap(QPixmap(":/photo/dangong1 (11).png"));
Pig1->setGeometry(A1->x(),A1->y(),50,50);
}
}
}
else if(x>A2->x()-20&&x<(A2->x()+30))
{
if(this->y>A2->y()-30&&this->yy()+30)
{
if(this->A2->isVisible())
{
BOOMMUSIC->setMedia(QUrl("D:/QTproject/MyQtProject/music/BOOM.mp3"));
BOOMMUSIC->play();
qDebug()<<"111";
this->A2->hide();
Pig2->setPixmap(QPixmap(":/photo/dangong1 (11).png"));
Pig2->setGeometry(A2->x(),A2->y(),50,50);
}
}
}
else if(x>A3->x()-30&&x<(A3->x()+30))
{
if(this->y>A3->y()-30&&this->yy()+30)
{
if(this->A3->isVisible())
{
BOOMMUSIC->setMedia(QUrl("D:/QTproject/MyQtProject/music/BOOM.mp3"));
BOOMMUSIC->play();
this->A3->hide();
Pig3->setPixmap(QPixmap(":/photo/dangong1 (11).png"));
Pig3->setGeometry(A3->x(),A3->y(),50,50);
}
}
}
else if(x>A4->x()-20&&x<(A4->x()+30))
{
if(this->y>A4->y()-30&&this->yy()+30)
{
if(this->A4->isVisible())
{
BOOMMUSIC->setMedia(QUrl("D:/QTproject/MyQtProject/music/BOOM.mp3"));
BOOMMUSIC->play();
qDebug()<<"111";
this->A4->hide();
Pig4->setPixmap(QPixmap(":/photo/dangong1 (11).png"));
Pig4->setGeometry(A4->x(),A4->y(),50,50);
}
}
}
}
此GAME类的源码可直接使用打开QT中,但要记得改pro内容以获得播放器播放的权限。
保持如下:
QT += multimedia
QT += core gui network
QT += multimediawidgets
QT += multimedia multimediawidgets
服务器和客户端的搭建就不过多阐述了,简单说一下。服务器是一个单独的内容,用来接收用户的使用需求,IP和端口号是绑死的。
客户端是用户端的内容。
----------------------------------------我是分割线-----------------------------------------------------------------
吃透了上面三个内容,这个游戏就会很简单,里面的素材与音效放在下面啦。
百度网盘链接:https://pan.baidu.com/s/1gQRzcs0Q1c-QrNiudYh03w
提取码:1g2c