# 用 Qt 实现“合成大西瓜”小游戏
## 主要流程
整体流程
实现思路:通过开设 Mainscene 界面,定义水果类 fruit,实现各种操作。
![](https://www.writebug.com/myres/static/uploads/2022/6/26/2430fe3d2b6836dbaf5c22bbc26d57d6.writebug)
定义水果类 fruit,
```c++
class fruit
{
int type; //种类
double x1,y1; //球的初始坐标
double x2,y2; //球现在的坐标
double vx,vy; //定义球速
double ax,ay; //定义球的加速度
double size; //大小
double m; //质量
int color; //颜色
bool isdown; //是否开始下落
void initball(int type);
球的初始化
};
```
定义 Mainscene 类
```c++
class Mainscene
{
Public:
int status; //游戏进行状态
QPoint mouse; //记录鼠标的坐标
std::vector <Fruit> fruit;//用容器储存球
QPushButton *Start; //开始按钮
QPushButton *Exit; //退出按钮
QPushButton *Pause; //暂停按钮
QPushButton *Finish; //结束按钮
void Setbutton(QPushButton *,int width,int height,int x,int y,int a);
//初始化按钮格式
void iniUI(); //初始化界面
void iniSignals(); //信号连接
void nextBall(); //下一个球初始化
void movecoordinate(); //根据球当前的速度与碰撞状态改变所有球的坐标
void collideWall(int i);//判断是否撞墙并改变速度方向
void collideball(); //判断球与球是否相撞并改变速度的大小和方向
void combine(int i,int j);//合成新球
private slots:
void showbuttons(bool); //控制初始界面按钮的显示
void StartGame(); //开始游戏
void showscore(); //显示积分
void back(); //返回到主界面
void gamepause(); //游戏暂停
void gamefinish(); //游戏结束
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void paintEvent(QPaintEvent *event); //重载绘图事件
void mouseMoveEvent(QMouseEvent *event); //重载鼠标移动事件
void mousePressEvent(QMouseEvent *event); //重载点击事件
void timerEvent(QTimerEvent *event); //重载计时器事件
```
算法或公式
核心算法:二维碰撞
原理:由于两个小球碰撞,切线上的速度都是互相平行的,没有作用力而连心线上是相互碰撞的(如下图所示),会有作用力,所以我们只需要求出球 1 和球 2 的连心线方向上的速度值。然后再根据动量守恒定律和机械能守恒定律求出碰撞后的球 1 和球 2 的连心线方向。最后再互相加上各自在切线上的速度即可得到各自碰撞后的 x 速度,y 速度。
![](https://www.writebug.com/myres/static/uploads/2022/6/26/3928498e12bc6c7119fea69e238b04c5.writebug)
和 v1t : 是球 1 在连心线方向和切线方向上的投影速度
和 v2t : 是球 2 在连心线方向和切线方向上的投影速度
: 球 1 的速度方向,等于 v1n + v1t
: 球 2 的速度方向,等于 v2n + v2t
```c++
distance = Math.sqrt(Math.pow((ball1.pointX - ball2.pointX),2) + Math.pow((ball1.pointY - ball2.pointY),2));
radius = ball1.r + ball2.r;
dx = ball1.pointX - ball2.pointX
dy = ball1.pointY - ball2.pointY
ex = dx / radius;
ey = dy / radius; // 获取连心线的单位向量(ex,ey)
= ex * ball1.vx + ey * ball1.vy
= ex * ball2.vx + ey * ball2.vy
```
![](https://www.writebug.com/myres/static/uploads/2022/6/26/2e0bdef94a09fc9f537b736ba47ef2aa.writebug)
' : 球1碰撞后的速度方向,等于v1n' + v1t
' : 球2碰撞后的的速度方向,等于v2n' + v2t
'和v2n' :
两个小球碰撞后的投影速度
假如这两个小球是一样大, v1n'和 v2n'取值就是:
' = v2n
' = v1n
并且根据动量守恒定律和机械能守恒定律得出:
![](https://www.writebug.com/myres/static/uploads/2022/6/26/a28e467e4ebdf9877e5c4244d1b69a1a.writebug)
和 v2 : 两个小球碰前速度.
和 m2 : 两个小球的质量
```c++
'和v2' :
两个小球碰后速度
double ux=-dy/distance,uy=dx/distance;//切向单位向量(ux,uy),方向为(ex,ey)逆时针旋转π/2
//球在两球连线方向上的速度投影为v=(vx,vy)·(ex,ey)
double v1=ex*balls[i].vx+ey*balls[i].vy;//i的法向速度
double v2=ex*balls[j].vx+ey*balls[j].vy;//j的法向速度
if (v2<v1) continue;//两球擦肩而过,不相撞
//球在切线方向上的速度投影为v'=(vx,vy)·(ux,uy)
double v11=ux*balls[i].vx+uy*balls[i].vy;//i的切向速度
double v22=ux*balls[j].vx+uy*balls[j].vy;//j的切向速度
//根据动量守恒和动能定理计算碰撞后两球连线方向上的速度u1和u2,其中K表示动能损失程度
double m1=balls[i].mass,m2=balls[j].mass;
double u1=K*((m1-m2)*v1+2*m2*v2)/(m1+m2);//i碰撞后法向速度
double u2=K*((m2-m1)*v2+2*m1*v1)/(m1+m2);//j碰撞后法向速度
```
速度矢量(vx,vy)=(u1*ex+v11*ux,u1*ey+v11*uy)·(i,j)
```c++
balls[i].vx=1*(u1*ex+v11*ux);
balls[i].vy=1*(u1*ey+v11*uy);
balls[j].vx=1*(u2*ex+v22*ux);
balls[j].vy=1*(u2*ey+v22*uy);
```
合成算法
```c++
combine(int i, int j)
{
Ball b;
initball(balls[i].type+1);
double vi=sqrt(balls[i].vx*balls[i].vx+balls[i].vy*balls[i].vy);
double vj=sqrt(balls[j].vx*balls[j].vx+balls[j].vy*balls[j].vy);
if (vi<vj)//合成的位置为速度较小的球
{
=b._x=balls[i].x;
=b._y=balls[i].y;
}
else {
=b._x=balls[j].x;
=b._y=balls[j].y;
}
vx=(balls[i].vx+balls[j].vx)/2.0;
vy=(balls[i].vy+balls[j].vy)/2.0;
ay=1;
falling=1;
balls[i]=b; //将合成的新球替换balls[i]
collideWall(i);
balls[j]=balls[balls.size()-1];
balls.pop_back(); //从balls数组中删除balls[j]
gamescore+=2*balls[i].type;
str.sprintf("score:%d",gamescore);
q->setText(str);
}
```
收获
单元测试
![](https://www.writebug.com/myres/static/uploads/2022/6/26/8477256573d8cebbd039999bd118b29f.writebug)
(开始界面)
![](https://www.writebug.com/myres/static/uploads/2022/6/26/b1d98caa3e3b1af26f0ca8e514c4915a.writebug)
(游戏暂停)
![](https://www.writebug.com/myres/static/uploads/2022/6/26/20b19fd744663c7cc3c1a6a25b2e9730.writebug)
(游戏进行中)
## 收获
掌握了 Qt 的基本操作,从零基础开始学习,基本能完成一个小项目
在查阅资料方面,能够根据需要到网上进行查阅,增强了自主学习的能力以及修改代码的能力。
对 C++ 的认识加深,认识到面向对象编程的优越性以及封装、继承等基本特点。将所学运用到实际应用中。
反复修改代码的过程既是折磨,更多的是探索的乐趣,在此过程中我收获了 coding 带来的愉悦以及成功后的成就感。
## 致谢
特别感谢 C++ 课的助教徐学长和白学长一年来对我学习上的巨大帮助,也感谢 20 级孙学长传授我 Qt 制作小游戏的经验,我会更加努力,学以致用,创造出更有价值的项目。
以上。
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
资源包含文件:设计报告word+项目源码 用Qt实现“合成大西瓜”小游戏 开发软件 Qt Creator 5.0.2 1)面向对象。 2)单元测试。 3)模型部分 4)验证 实现思路:通过开设Mainscene界面,定义水果类fruit,实现各种操作。 详细介绍参考:https://biyezuopin.blog.csdn.net/article/details/125473833
资源推荐
资源详情
资源评论
收起资源包目录
基于Qt实现的“合成大西瓜”小游戏.zip (70个子文件)
代码6.0
main.cpp 176B
ball.h 600B
ball.cpp 467B
mainwindow.h 2KB
mainwindow.cpp 18KB
mainwindow.ui 558B
README.md 7KB
代码4.0
main.cpp 176B
ball.h 600B
ball.cpp 467B
mainwindow.h 2KB
mainwindow.cpp 18KB
代码5.0
main.cpp 176B
ball.h 600B
ball.cpp 467B
mainwindow.h 2KB
mainwindow.cpp 18KB
watermelon
main.cpp 176B
ball.h 600B
watermelon.pro 959B
ball.cpp 467B
mainwindow.h 2KB
mainwindow.cpp 18KB
mainwindow.ui 558B
watermelon.pro.user 19KB
代码8.0
main.cpp 176B
ball.h 600B
watermelon.pro 977B
ball.cpp 467B
mainwindow.h 2KB
mainwindow.cpp 18KB
mainwindow.ui 558B
watermelon.pro.user 19KB
stephe.qrc 101B
代码最终版
main.cpp 176B
ball.h 600B
watermelon.pro 977B
ball.cpp 467B
mainwindow.h 2KB
mainwindow.cpp 18KB
mainwindow.ui 558B
watermelon.pro.user 19KB
stephe.qrc 101B
watermelon.pro 977B
代码3.0
main.cpp 176B
ball.h 600B
ball.cpp 467B
mainwindow.cpp 18KB
LICENSE 1KB
代码9.0
main.cpp 176B
ball.h 600B
watermelon.pro 977B
ball.cpp 467B
mainwindow.h 2KB
mainwindow.cpp 18KB
mainwindow.ui 558B
watermelon.pro.user 19KB
stephe.qrc 101B
代码2.0
main.cpp 176B
代码7.0
main.cpp 176B
ball.h 600B
watermelon.pro 977B
ball.cpp 467B
mainwindow.h 2KB
mainwindow.cpp 18KB
mainwindow.ui 558B
stephe.qrc 101B
代码1.0
ball.h 600B
ball.cpp 467B
C 大作业实验报告.docx 608KB
共 70 条
- 1
shejizuopin
- 粉丝: 1w+
- 资源: 1288
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
前往页