炮弹仿真运动

炮弹仿真运动

一、步骤

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 here
	SetTimer(1,100,NULL);
}

void CFaSheView::OnMStop() 
{
	// TODO: Add your command handler code here
	KillTimer(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 default
	m_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 default
	m_FlagLBD = 0;
	CView::OnLButtonUp(nFlags, point);
}

void CFaSheView::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if (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++;
		else
			break;
	}
	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 here
	SetTimer(2,50,NULL);//50毫秒
}

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

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

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值