MFC综合练习 开发自己的推箱子应用程序.docx

上传人:b****7 文档编号:9451567 上传时间:2023-02-04 格式:DOCX 页数:15 大小:18.97KB
下载 相关 举报
MFC综合练习 开发自己的推箱子应用程序.docx_第1页
第1页 / 共15页
MFC综合练习 开发自己的推箱子应用程序.docx_第2页
第2页 / 共15页
MFC综合练习 开发自己的推箱子应用程序.docx_第3页
第3页 / 共15页
MFC综合练习 开发自己的推箱子应用程序.docx_第4页
第4页 / 共15页
MFC综合练习 开发自己的推箱子应用程序.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

MFC综合练习 开发自己的推箱子应用程序.docx

《MFC综合练习 开发自己的推箱子应用程序.docx》由会员分享,可在线阅读,更多相关《MFC综合练习 开发自己的推箱子应用程序.docx(15页珍藏版)》请在冰豆网上搜索。

MFC综合练习 开发自己的推箱子应用程序.docx

MFC综合练习开发自己的推箱子应用程序

MFC综合练习开发自己的推箱子应用程序。

MFC综合练习:

开发自己的推箱子应用程序。

2011-06-0514:

07这是我为了完成这个学期C++课程设计而做的作业,虽说无法达到老师的要求,但是通过这次练习,确实让我获益匪浅。

应用的主要技术有:

《MFC位图操作》(双缓存机制)

《MFC文档读写操作》(通过Serialize()虚函数实现)

《MFC全屏显示功能》

《MFC键盘处理机制》

等。

这是一个单文档MFC应用程序,主界面如下:

地图是我随机生成的,所以有极大的问题,本想加入地图编辑功能,但是快考试没多少时间了,只好作罢。

一、准备工作:

新建MFC单文档应用程序BOX,添加两个枚举类型到BOXDoc.henumBoxDirect{B_UP,B_DOWN,B_LEFT,B_RIGHT};//表示人物移动的方向

enumBoxMap{M_NONE,M_WALL,M_DEST};//地图信息标志

将所应用到得所有图片资源添加到资源中,ID分别为IDB_BOX、IDB_DEST、IDB_NONE、IDB_PEOPLE、IDB_WALL。

VIEW类负责绘图工作,所以所有和绘图相关的变量都放在BOXView类里:

CBitmapbitmap1,bitmap2,bitmap3,bitmap4,bitmap5;//位图资源

CDCDCBox,DCPeople,DCDest,DCNone,DCWall;//代表内存设备资源

CSizesource1,source2,source3,source4,source5;//分别代表每个位图的尺寸。

二、关于游戏信息类的设计。

我把它取名为CMap,最初的用意是表示地图,后来陆续又加上各种信息在里面,虽然这个名字不合适,但沿用旧名比较好。

classCMap:

publicCObjectpublic:

int*Map;//地图信息

CPointPeople_Position;//人物的位置信息

CPoint*Box_Position;//箱子的位置信息

intM;//M、N分别代表地图的列数行数。

intN;

intBOX_NUM;//代表箱子数目

intREACH_BOX_NUM;//代表已推到目的地的箱子的数目

intTOTAL_STATUS;//代表总的关卡数

intcur_status;//代表当前关卡数

string*status_info;//每个关卡的地图都存放在不同的文件里,status_info代表存放每个地图的文件名称

protected:

DECLARE_SERIAL(CMap)//赋予该类文档读写能力

public:

BOOLIs_Move_Ok(intDirect);//判断是否可推

BOOLMove_Up(void);//向上推

BOOLMove_Down(void);

BOOLMove_Left(void);

BOOLMove_Right(void);

BOOLIs_Box(inti,intj);//(i,j)位置处是否为箱子

CPoint*GetBoxPosition(inti,intj);//获取(i,j)处得箱子的内存地址,以便移动

BOOLInitMap();//初始化地图

BOOLDeleteMap();//删除当前地图,以便释放内存资源,供下次读取

virtualvoidSerialize(CArchive&ar);//文档读写

};

在CBOXDoc类的声明中添加一个CMap对象CMyMap,还有两个函数:

public:

CMapMyMap;

voidNext_Status(intcur_status);//下一关

inlineCMap*GetMap()//获取当前游戏信息

return&MyMap;

三、场景的绘制:

首先初始化画图相关资源,在CBOXView类里面的OnInitialUpdate()函数里添加最合适:

voidCBOXView:

OnInitialUpdate()

CView:

OnInitialUpdate();

CClientDCpDC(this);

BITMAPbm;

bitmap1.LoadBitmap(IDB_BOX);

DCBox.CreateCompatibleDC(&pDC);

DCBox.SelectObject(&bitmap1);

bitmap1.GetObject(sizeof(bm),&bm);

source1.cx=bm.bmWidth;

source1.cy=bm.bmHeight;

bitmap2.LoadBitmap(IDB_PEOPLE);

DCPeople.CreateCompatibleDC(&pDC);

DCPeople.SelectObject(&bitmap2);

bitmap2.GetObject(sizeof(bm),&bm);

source2.cx=bm.bmWidth;

source2.cy=bm.bmHeight;

bitmap3.LoadBitmap(IDB_WALL);

DCWall.CreateCompatibleDC(&pDC);

DCWall.SelectObject(&bitmap3);

bitmap3.GetObject(sizeof(bm),&bm);

source3.cx=bm.bmWidth;

source3.cy=bm.bmHeight;

bitmap4.LoadBitmap(IDB_DEST);

DCDest.CreateCompatibleDC(&pDC);

DCDest.SelectObject(&bitmap4);

bitmap4.GetObject(sizeof(bm),&bm);

source4.cx=bm.bmWidth;

source4.cy=bm.bmHeight;

bitmap5.LoadBitmap(IDB_NONE);

DCNone.CreateCompatibleDC(&pDC);

DCNone.SelectObject(&bitmap5);

bitmap5.GetObject(sizeof(bm),&bm);

source5.cx=bm.bmWidth;

source5.cy=bm.bmHeight;

当然在CBOXView类的析构函数里要是放这些资源:

CBOXView:

~CBOXView()

DCBox.DeleteDC();

DCPeople.DeleteDC();

DCDest.DeleteDC();

DCNone.DeleteDC();

DCWall.DeleteDC();

bitmap1.DeleteObject();

bitmap2.DeleteObject();

bitmap3.DeleteObject();

bitmap4.DeleteObject();;

bitmap5.DeleteObject();;

处理绘图的是CBOXView的OnDraw函数:

voidCBOXView:

OnDraw(CDC*pDC)

CBOXDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

CRectrect;

GetClientRect(&rect);//取得整个窗口尺寸

CMap*MyMap=pDoc-GetMap();//取得地图信息

intDest_Width=rect.Width()/MyMap-M;//计算显示每个位图资源的宽度和高度

intDest_Heigth=rect.Height()/MyMap-N;

inti=0,j=0;

for(i=0;iMyMap-M;i++)

for(j=0;jMyMap-N;j++)

switch((*MyMap).Map[i][j])

caseM_NONE:

pDC-StretchBlt(i*Dest_Width,j*Dest_Heigth,Dest_Width,Dest_Heigth,&DCNone,0,0,source1.cx,source1.cy,SRCCOPY);

break;

caseM_WALL:

pDC-StretchBlt(i*Dest_Width,j*Dest_Heigth,Dest_Width,Dest_Heigth,&DCWall,0,0,source2.cx,source2.cy,SRCCOPY);

break;

caseM_DEST:

pDC-StretchBlt(i*Dest_Width,j*Dest_Heigth,Dest_Width,Dest_Heigth,&DCDest,0,0,source3.cx,source3.cy,SRCCOPY);

break;

for(i=0;iMyMap-BOX_NUM;i++)//绘制箱子

pDC-StretchBlt((*MyMap).Box_Position[i].x*Dest_Width,(*MyMap).Box_Position[i].y*Dest_Heigth,Dest_Width,Dest_Heigth,&DCBox,0,0,source4.cx,source4.cy,SRCCOPY);

//绘制人物

pDC-StretchBlt((*MyMap).People_Position.x*Dest_Width,(*MyMap).People_Position.y*Dest_Heigth,Dest_Width,Dest_Heigth,&DCPeople,0,0,source5.cx,source5.cy,SRCCOPY);

if(MyMap-REACH_BOX_NUM==MyMap-BOX_NUM)//判断本关是否结束。

MessageBox("你很强,你赢了!

","YouGotit!

",MB_OK);

MyMap-cur_status++;//代表当前关卡的变量自动+1MyMap-DeleteMap();

pDoc-Next_Status(MyMap-cur_status);

Invalidate(TRUE);

四、文档的读写

绘制地图的前提是已经从文件中读取到了地图信息,文件读取采用MFC的Serialize()函数,代表地图的文件内容如下(采用TDump工具查看内容):

第一行的08000000040000000200000001000000其中08、04代表地图有八列四行。

绘制出的信息如下:

有两个箱子。

以下列出CBoxDoc和CMAP类的Serialize()函数

IMPLEMENT_SERIAL(CMap,CObject,1);

voidCBOXDoc:

Serialize(CArchive&ar)

if(ar.IsStoring())

MyMap.Serialize(ar);

elseMyMap.Serialize(ar);

voidCMap:

Serialize(CArchive&ar)

if(ar.IsStoring())//保存地图

arM;

arN;

arBOX_NUM;

inti,j;

for(i=0;iM;i++)

for(j=0;jN;j++)

arMap[i][j];

arPeople_Position;

for(i=0;iBOX_NUM;i++)

arBox_Position[i];

else//读取地图

arM;//读行列值

arN;

arBOX_NUM;//读取箱子数目

InitMap();//给存放地图信息的变量分配内存空间

inti,j;

for(i=0;iM;i++)

for(j=0;jN;j++)

arMap[i][j];

arPeople_Position;

for(i=0;iBOX_NUM;i++)

arBox_Position[i];

为了保证一打开游戏就有得玩,必须在CBOXDoc的构造函数里初始化地图信息:

CBOXDoc:

CBOXDoc()

MyMap.cur_status=0;

ifstreamreadinfo("Status.info");

readinfoMyMap.TOTAL_STATUS;

MyMap.status_info=newstring[MyMap.TOTAL_STATUS];

for(inti=0;iMyMap.TOTAL_STATUS;i++)

readinfoMyMap.status_info[i];

Next_Status(MyMap.cur_status);

readinfo.close();

由于每一关都有一个地图,有与之对应的文件,Status.info文件就存在着这些保存着地图信息的文件名列表,Status.info文件内容如下:

Map1.MapMap2.MapMap3.MapMap4.MapMap5.Map

切换关卡的是Next_Status函数

voidCBOX:

Next_Status(intcur_status)

if(MyMap.cur_status=MyMap.TOTAL_STATUS)

MessageBox(NULL,"不好意思,关卡完了!

\n关卡将重置!

","gameover!

",MB_OK);

MyMap.cur_status=0;

CFileExceptionfe;

CFile*pFile=GetFile(MyMap.status_info[MyMap.cur_status].c_str(),CFile:

modeRead|CFile:

shareDenyWrite,&fe);

DeleteContents();

SetModifiedFlag();

CArchiveloadArchive(pFile,CArchive:

load);

loadArchive.m_pDocument=this;

loadArchive.m_bForceFlat=FALSE;

CWaitCursorwait;

if(pFile-GetLength()!

=0)

Serialize(loadArchive);

loadArchive.Close();

ReleaseFile(pFile,FALSE);

其中之前出现的InitMap和DeleteMap定义如下:

BOOLCMap:

InitMap()

Map=newint*[M];

for(inti=0;iM;i++)

Map[i]=newint[N];

Box_Position=newCPoint[BOX_NUM];

REACH_BOX_NUM=0;

returnTRUE;

BOOLCMap:

DeleteMap()

for(inti=0;iM;i++)

deleteMap[i];

deleteMap;

deleteBox_Position;

returnTRUE;

五、响应键盘消息:

负责处理键盘消息的是在CBOCView类的OnChar函数:

voidCBOXView:

OnChar(UINTnChar,UINTnRepCnt,UINTnFlags)

CBOXDoc*pDoc=GetDocument();

CMap*MyMap=pDoc-GetMap();

switch(nChar)

case97:

case65:

if(MyMap-Is_Move_Ok(B_LEFT))

MyMap-Move_Left();

break;

case83:

case115:

if(MyMap-Is_Move_Ok(B_DOWN))

MyMap-Move_Down();

break;

case68:

case100:

if(MyMap-Is_Move_Ok(B_RIGHT))

MyMap-Move_Right();

break;

case87:

case119:

if(MyMap-Is_Move_Ok(B_UP))

MyMap-Move_Up();

break;

caseVK_ESCAPE:

//esc键,和全屏显示效果有关。

CMainFrame*pFrame=(CMainFrame*)AfxGetApp()-m_pMainWnd;//

//调用主窗口类的自定义函数EndFullScreen,便可退出全屏显示状态

pFrame-EndFullScreen();//

}//

default:

gotoINVALID;

Invalidate(TRUE);

INVALID:

CView:

OnChar(nChar,nRepCnt,nFlags);

六、全屏显示效果:

添加一个ID为ID_FULL_SCREEN的菜单项,添加处理这个菜单项的消息处理函数voidCMainFrame:

OnFullScreen()

详细步骤点击链接《MFC全屏显示技术》

七、人物、箱子的移动函数:

BOOLCMap:

Is_Box(inti,intj)

for(intk=0;kBOX_NUM;k++)

if(Box_Position[k].x==i&&Box_Position[k].y==j)

returnTRUE;

returnFALSE;

BOOLCMap:

Is_Move_Ok(intDirect)

intcurx=People_Position.x;

intcury=People_Position.y;

switch(Direct)

caseB_UP:

if(cury==0||(Map[curx][cury-1]==M_WALL)||(Is_Box(curx,cury-1)&&(cury-1==0||(Map[curx][cury-2]==M_WALL)||Is_Box(curx,cury-2))))

returnFALSE;

break;

caseB_DOWN:

if(cury==N-1||(Map[curx][cury+1]==M_WALL)||(Is_Box(curx,cury+1)&&(cury+1==N-1||(Map[curx][cury+2]==M_WALL)||Is_Box(curx,cury+2))))

returnFALSE;

break;

caseB_LEFT:

if(curx==0||(Map[curx-1][cury]==M_WALL)||(Is_Box(curx-1,cury)&&(curx-1==0||(Map[curx-2][cury]==M_WALL)||Is_Box(curx-2,cury))))

returnFALSE;

break;

caseB_RIGHT:

if(curx==M-1||(Map[curx+1][cury]==M_WALL)||(Is_Box(curx+1,cury)&&(curx+1==0||(Map[curx+2][cury]==M_WALL)||Is_Box(curx+2,cury))))

returnFALSE;

break;

returnTRUE;

CPoint*CMap:

GetBoxPosition(inti,intj)

for(intk=0;kBOX_NUM;k++)

if(Box_Position[k].x==i&&Box_Position[k].y==j)

return&Box_Position[k];

returnNULL;

BOOLCMap:

Move_Up(void)

intcurx=People_Position.x;

intcury=People_Position.y;

People_Position.y-=1;

if(Map[curx][cury-1]==M_DEST&&Is_Box(curx,cury-1))

REACH_BOX_NUM-=1;

if(Is_Box(curx,cury-1))

CPoint*temp=GetBoxPosition(curx,cury-1);

temp-y-=1;

if(Map[curx][cury-2]==M_DEST)

REACH_BOX_NUM+=1;

returnTRUE;

BOOLCMap:

Move_Down(void)

intcurx=People_Position.x;

intcury=People_Position.y;

People_Position.y+=1;

if(Is_Box(curx,cury+1)&&Map[curx][cury+1]==M_DEST)

REACH_BOX_NUM-=1;

if(Is_Box(curx,cury+1))

CPoint*temp=GetBoxPosition(curx,cury+1);

temp-y+=1;

if(Map[curx][cury+2]==M_DEST)

REACH_BOX_NUM+=1;

returnTRUE;

BOOLCMap:

Move_Left(void)

intcurx=People_Position.x;

intcury=People_Position.y;

People_Position.x-=1;

if(Is_Box(curx-1,cury)&&Map[curx-1][cury]==M_DEST)

REACH_BOX_NUM-=1;

if(Is_Box(curx-1,cury))

CPoint*temp=GetBoxPosition(curx-1,cury);

temp-x-=1;

if(Map[curx-2][cury]==M_DEST)

REACH_BOX_NUM+=1;

returnTRUE;

BOOLCMap:

Move_Right(void)

intcurx=People_Position.x;

intcury=People_Position.y;

People_Position.x+=1;

if(Is_Box(curx+1,cury)&&Map[curx+1][cury]==M_DEST)

REACH_BOX_NUM-=1;

if(Is_Box(curx+1,cury))

CPoint*temp=GetBoxPosition(curx+1,cury);

temp-x+=1;

if(Map[curx+2][cury]==M_DEST)

REACH_BOX_NUM+=1;

returnTRUE;

这个程序有些复杂,有时间我会上传源代码供大家下载

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1