> 文档中心 > 炮弹仿真运动

炮弹仿真运动


炮弹仿真运动

一、步骤

1、新建一个MFC单文档应用程序,如下图所示
在这里插入图片描述
在这里插入图片描述
2、新建一个类,命名为“CPaoDan”,如下图所示。
在这里插入图片描述
3、在“CPaoDan”类里添加一些成员变量(有些后面会用到),如下图所示。
在这里插入图片描述
代码如下:

class CPaoDan  {public:void Move();void Draw(CDC *p);CPaoDan();virtual ~CPaoDan();CDC *pDC;CPoint m_YD;//原点(只要涉及到坐标必定有坐标原点)float m_kx,m_ky;//x,y轴方向上的比例尺float m_x;float m_y;//以“米”为单位float m_r;//炮弹坐标位置和半径float m_m;//炮弹质量float m_vx,m_vy;//沿x,y轴的速度float m_ax,m_ay;//沿x,y轴的加速度float DeltaT;float m_S;//炮弹横截面积float v,zl;//速度,阻力float Rho;//空气密度float c;//外形阻力系数};

4、紧接着在构造函数里进行初始化,如下图所示。
在这里插入图片描述

5、在CPaoDan里添加成员函数Draw(CDC *p),画炮弹。
在这里插入图片描述
代码如下:

void CPaoDan::Draw(CDC *p){int x,y,r;pDC = p;//画炮弹x = m_YD.x + m_x*m_kx;y = m_YD.y + m_y*m_ky;r = m_r*m_kx;//半径先以x轴方向上的比例尺为准pDC->Ellipse(x-r,y-r,x+r,y+r);//画坐标轴x = m_YD.x;y = m_YD.y;pDC->MoveTo(x,y);x += 800;pDC->LineTo(x,y);x = m_YD.x;y = m_YD.y;pDC->MoveTo(x,y);y -= 500;pDC->LineTo(x,y);//画地面打击目标(假设是矩形)x = m_YD.x + 12000*m_kx;//在12公里处画一目标y = m_YD.y + 100*m_ky;//高度是100米r = 200*m_kx;pDC->Rectangle(x,y,x+r,y+r);//实时动态显示各量的变化CString str;str.Format("阻力f:%f 速度v:%f",zl,v);pDC->TextOut(200,30,str);CString str1;str1.Format("x轴速度:%f  y轴速度:%f",m_vx,m_vy);pDC->TextOut(200,60,str1);CString str2;str2.Format("x轴坐标:%f      y轴坐标:%f",m_x,m_y);pDC->TextOut(200,90,str2);}

6、为了让炮弹动起来,添加“Move()”函数,如下图所示。
在这里插入图片描述
代码如下:

void CPaoDan::Move(){v = sqrt(m_vx*m_vx + m_vy*m_vy);zl = 0.5*c*m_S*Rho*v*v;//阻力公式m_vx += (-zl*m_vx/v/m_m)*DeltaT;m_vy += (-9.8 - zl*m_vy/v/m_m)*DeltaT;m_x += m_vx*DeltaT;m_y += m_vy*DeltaT;m_ax = -zl*m_vx/v/m_m;//x轴阻力加速度m_ay = -9.8 - zl*m_vy/v/m_m;//y轴阻力加速度}

7、在CFaSheView里将“PaoDan.h”嵌入,并在OnDraw(CDC* pDC)里调用,如下图所示。
在这里插入图片描述
在这里插入图片描述
8、添加菜单,并建立类向导,如下图所示。
在这里插入图片描述
代码如下:

void CFaSheView::OnMStart() {// TODO: Add your command handler code hereSetTimer(1,100,NULL);}void CFaSheView::OnMStop() {// TODO: Add your command handler code hereKillTimer(1);}

9、实现滚轴的放大缩小,只需要把比例尺改一下就行,如下图所示。
在这里插入图片描述
代码如下:

BOOL CFaSheView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) {// TODO: Add your message handler code here and/or call default//由于坐标轴用的是像素,没用比例尺,所以不会跟着放大缩小if (zDelta>0){m_PD.m_kx *= 1.1;m_PD.m_ky *= 1.1;}if (zDelta<0){m_PD.m_kx *= 0.9;m_PD.m_ky *= 0.9;}Invalidate(TRUE);return CView::OnMouseWheel(nFlags, zDelta, pt);}

10、接下来就是实现拖动场景中的所有东西。我们只用改变原点就行,因为其他所有东西的计算都是依据原点来的。具体如下图所示。
在这里插入图片描述
在这里插入图片描述
相关代码如下:

void CFaSheView::OnLButtonDown(UINT nFlags, CPoint point) {// TODO: Add your message handler code here and/or call defaultm_LBD = point;m_YDTemp = m_PD.m_YD;m_FlagLBD = 1;CView::OnLButtonDown(nFlags, point);}void CFaSheView::OnLButtonUp(UINT nFlags, CPoint point) {// TODO: Add your message handler code here and/or call defaultm_FlagLBD = 0;CView::OnLButtonUp(nFlags, point);}void CFaSheView::OnMouseMove(UINT nFlags, CPoint point) {// TODO: Add your message handler code here and/or call defaultif (1 == m_FlagLBD){m_PD.m_YD.x = m_YDTemp.x + (point.x - m_LBD.x);m_PD.m_YD.y = m_YDTemp.y + (point.y - m_LBD.y);Invalidate(TRUE);}CView::OnMouseMove(nFlags, point);}

11、运行结果部分截图,如下图所示。

(1)开始运动
在这里插入图片描述
(2)放大物体
在这里插入图片描述
(3)缩小物体
在这里插入图片描述
(4)拖动所有物体
在这里插入图片描述
(5)炮弹运动一段时间后
在这里插入图片描述

12、为了做到更加完美,可以添加对话框,前面已经实现,方法一样,可自行尝试,不再赘述。

//================================================================================================================================================================================================================================//

续下一节(火箭弹)

火箭弹比炮弹多了一个推力。推力是测出来的,可以将提前测好的数据读出来。下图展示的是每隔50毫秒测试的推力(66个数据)。
在这里插入图片描述
二、步骤

1、新建一个CRocket类,可以从CPaoDan类中继承(由CPaoDan类作为一个基类,派生出CRocket类),如下图所示。
在这里插入图片描述
2、在CFaSheView里嵌入头文件,如下图所示。
在这里插入图片描述
注:在构造函数里,先调用基类,再调用派生类;在析构函数里,先调用派生类,再调用基类。

3、添加需要的成员变量,如下图所示。
在这里插入图片描述
4、在CRocket()里做一些初始化改变,有些成员变量不需要改变,就可以直接从炮弹类里继承,如下图所示。
在这里插入图片描述
5、对于推力,首先需要去读取,添加成员函数,如下图所示。
在这里插入图片描述

代码如下:

//读出推力数据(在构造函数里调用)void CRocket::ReadTuiLi(){FILE * fp;int i = 0;fp = fopen("G:\\TuiLiQuXian.txt","r");//从G盘根目录下读数据while(1){if( fscanf(fp,"%f",&m_TL[i]) != EOF)i++;elsebreak;}m_nTL = i;}

6、当然,我们也可以把推力曲线给画出来,如下图所示。
在这里插入图片描述

代码如下:

void CRocket::DrawTuiLi()//里面不需要参数"pDC",因为继承了基类(炮弹类)的{int x,y,i;//画坐标轴x = m_YDTL.x;y = m_YDTL.y;pDC->MoveTo(x,y);x += 250;pDC->LineTo(x,y);x = m_YDTL.x;y = m_YDTL.y;pDC->MoveTo(x,y);y -= 200;pDC->LineTo(x,y);//画推力曲线x = m_YDTL.x;y = m_YDTL.y;pDC->MoveTo(x,y);for(i = 0; i < m_nTL; i++){x += 100*m_kxtl;y = m_YDTL.y + m_TL[i]*m_kytl;pDC->LineTo(x,y);}}

7、在CFaSheView的OnDraw(CDC *pDC)里调用,如下图所示。
在这里插入图片描述
8、画出推力曲线后,编译运行结果如下图所示。
在这里插入图片描述

9、给派生类CRocket添加Move函数(CPaoDan里的Move函数就不起作用了),如下图所示。
在这里插入图片描述
代码如下:

void CRocket::Move(float deltaT){v = sqrt(m_vx*m_vx + m_vy*m_vy);zl = 0.5*c*m_S*Rho*v*v;//阻力公式if (m_iTL < m_nTL){m_vx += (-zl*m_vx/v/m_m)*deltaT + m_TL[m_iTL]*m_vx/v/m_m*deltaT;m_vy += -(9.8 + zl*m_vy/v/m_m)*deltaT + m_TL[m_iTL]*m_vy/v/m_m*deltaT;m_iTL++;}else{m_vx += (-zl*m_vx/v/m_m)*DeltaT;m_vy += -(9.8 + zl*m_vy/v/m_m)*DeltaT;}m_x += m_vx*DeltaT;m_y += m_vy*DeltaT;m_ax = -zl*m_vx/v/m_m;//x轴阻力加速度m_ay = -9.8 - zl*m_vy/v/m_m;//y轴阻力加速度}

10、添加“火箭”菜单,建立类向导,另设置一个时钟,如下图所示。
在这里插入图片描述
相关代码:

void CFaSheView::OnMStartRocket() {// TODO: Add your command handler code hereSetTimer(2,50,NULL);//50毫秒}

11、然后在OnTimer(UINT nIDEvent)里调用。
代码如下:

void CFaSheView::OnTimer(UINT nIDEvent) {// TODO: Add your message handler code here and/or call defaultswitch(nIDEvent){case 1:m_PD.Move();break;case 2:m_Rocket.Move(0.05);break;}Invalidate(true);CView::OnTimer(nIDEvent);}

12、运行结果如下图所示。
在这里插入图片描述