C++课程设计打砖块游戏.docx
《C++课程设计打砖块游戏.docx》由会员分享,可在线阅读,更多相关《C++课程设计打砖块游戏.docx(20页珍藏版)》请在冰豆网上搜索。
C++课程设计打砖块游戏
MFC课程设计说明书
●设计题目:
打砖块游戏
●所属系部:
计算机工程系
●专业:
计算机科学与技术
●学号:
XXXXXXX
●姓名:
XXXX
●指导教师:
XXXX
●设计日期:
12-26
一、
设计任务
1.1任务描述
使用MFC框架设计一个打砖块游戏。
在客户区内显示砖块分布,小球和托盘。
按空格键开始游戏,Esc键结束游戏。
开始游戏小球可以跳起来打砖块,移动鼠标实现托盘的移动,打到的砖块消失。
如果托盘没有接到小球,那么生命值减一,共有三次生命,生命都用完时,可以继续或结束。
1.2设计要求
1.自定义屏幕二维坐标系:
x轴水平向右为正,y轴垂直向上为正,坐标系原点位于客户区中心。
2.新加上两个类Brick类和Baffle类,分别用来定义并绘制砖块和托盘。
3.使用定时器函数控制小球的运动。
4.使用双缓冲技术实现动画。
5.在TestView类中实现砖块的分布
6.添加函数实现小球各种的碰撞速度大小和方向的改变。
7.添加函数实现鼠标移动控制托盘。
1.3
效果图
设计效果图如图1所示。
图1小球打砖块效果图
二、设计思路
本设计首先构建双缓冲框架,小球和砖块、客户区边界发生碰撞后,改变运动方向。
设置游戏关卡并绘制砖块分布。
鼠标移动控制托盘。
托盘没有接住小球,生命值则减一。
游戏结束时显示对话框以便继续或退出游戏。
三、关键源代码及注释
3.1关于窗口外观设计的代码:
intCMainFrame:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
{
if(CFrameWnd:
:
OnCreate(lpCreateStruct)==-1)
return-1;
SetMenu(NULL);//去掉菜单栏
CMenu*p=GetSystemMenu(FALSE);
p->RemoveMenu(SC_SIZE,MF_BYCOMMAND);//禁止改变窗口大小
return0;
}
BOOLCMainFrame:
:
PreCreateWindow(CREATESTRUCT&cs)
{
if(!
CFrameWnd:
:
PreCreateWindow(cs))
returnFALSE;
theCREATESTRUCTcs
cs.style&=~(WS_MAXIMIZEBOX);//过滤最大化
cs.x=100;
cs.y=100;
cs.cx=809;
cs.cy=610;
returnTRUE;
}
3.2Baffle类中的各种定义
CBaffle:
:
CBaffle(doublex,doubley,doublew,doubleh,doubles)
{
m_XPos=x,m_YPos=y;
m_Width=w,m_Height=h,m_HalfW=w/2.0,m_HalfH=h/2.0;
m_Speed=s,m_PreXPos=x;
}
voidCBaffle:
:
SetPositionX(doublex)//设置x方向位置
{
m_PreXPos=m_XPos;
m_XPos=x;
}
voidCBaffle:
:
SetPositionY(doubley)//设置y方向位置
{
m_YPos=y;
}
voidCBaffle:
:
SetWidth(doublew)//设置宽度
{
m_Width=w;
m_HalfW=w/2.0;
}
voidCBaffle:
:
SetHeight(doubleh)//设置高度
{
m_Height=h;
m_HalfH=h/2.0;
}
voidCBaffle:
:
CalculateSpeed()//速度计算
{
m_Speed=(m_XPos-m_PreXPos);
}
voidCBaffle:
:
DrawBaffle(CDC*pDC)//绘制托盘
{
CDCMemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmapNewBitmap,*pOldBitmap;
NewBitmap.LoadBitmap(IDB_BAFFLE);
pOldBitmap=MemDC.SelectObject(&NewBitmap);
pDC->BitBlt(int(m_XPos-m_HalfW),int(m_YPos-m_HalfH+2),int(m_Width),int(m_Height),&MemDC,0,0,SRCCOPY);
MemDC.DeleteDC();
}
voidCBaffle:
:
SetSpeed(doubles)
{
m_Speed=s;//设置速度
}
3.3Brick类中的各种定义
CBrick:
:
CBrick(doublex,doubley,doublew,doubleh)
{
m_XPos=x,m_YPos=y;
m_Width=w,m_Height=h;
m_HalfW=w/2.0,m_HalfH=h/2.0;
m_Enable=TRUE;
m_Score=0;
m_Color=RGB(255,255,255);
}
voidCBrick:
:
SetEnable()
{
m_Enable=TRUE;
}
voidCBrick:
:
SetDisable()
{
m_Enable=FALSE;
}
voidCBrick:
:
SetPosition(doublex,doubley)//设置坐标
{
m_XPos=x,m_YPos=y;
}
voidCBrick:
:
SetWidth(doublew)
{
m_Width=w,m_HalfW=w/2;
}
voidCBrick:
:
SetHeight(doubleh)
{
m_Height=h,m_HalfH=h/2;
}
voidCBrick:
:
SetColor(COLORREFclr)
{
m_Color=clr;
}
voidCBrick:
:
SetScore(intvalue)
{
m_Score=value;
}
voidCBrick:
:
DrawBrick(CDC*pDC,double&c,double&d)//绘制砖块
{
CDCMemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmapNewBitmap,*pOldBitmap;
NewBitmap.LoadBitmap(IDB_BRICK);
doubledx=c-m_HalfW;
doubledy=d-m_HalfH;
pOldBitmap=MemDC.SelectObject(&NewBitmap);
pDC->BitBlt(int(dx),int(dy),int(m_Width),int(m_Height),&MemDC,0,0,SRCCOPY);
MemDC.DeleteDC();
}
3.4双缓冲函数
voidCTestView:
:
DoubleBuffer()//双缓冲
{
CDC*pDC=GetDC();
GetClientRect(&rect);//获得客户区的大小
pDC->SetMapMode(MM_ANISOTROPIC);//pDC自定义坐标系
pDC->SetWindowExt(rect.Width(),rect.Height());//设置窗口范围
pDC->SetViewportExt(rect.Width(),-rect.Height());//x轴水平向右,y轴垂直向上
pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);//屏幕中心为原点
CDCMemDC;//内存DC
CBitmapNewBitmap,*pOldBitmap;//内存中承载图像的临时位图
MemDC.CreateCompatibleDC(pDC);//建立与屏幕pDC兼容的MemDC
NewBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());//创建兼容位图
pOldBitmap=MemDC.SelectObject(&NewBitmap);//将兼容位图选入MemDC
MemDC.SetMapMode(MM_ANISOTROPIC);//MemDC自定义坐标系
MemDC.SetWindowExt(rect.Width(),rect.Height());
MemDC.SetViewportExt(rect.Width(),-rect.Height());
MemDC.SetViewportOrg(rect.Width()/2,rect.Height()/2);
DrawObject(&MemDC);
BorderTest();
pDC->BitBlt(-rect.Width()/2,-rect.Height()/2,rect.Width(),rect.Height(),&MemDC,
-rect.Width()/2,-rect.Height()/2,SRCCOPY);//将内存位图拷贝到屏幕
MemDC.SelectObject(pOldBitmap);//恢复位图
NewBitmap.DeleteObject();//删除位图
MemDC.DeleteDC();//删除MemDC
ReleaseDC(pDC);//释放DC
}
3.5插入背景位图函数
CBitmapm_bmp;
m_bmp.LoadBitmap(IDB_BITMAP2);
BITMAPbm;
m_bmp.GetBitmap(&bm);
CDCdcMem;
dcMem.CreateCompatibleDC(pDC);
CBitmap*pOldbmp=dcMem.SelectObject(&m_bmp);
pDC->BitBlt(-Rect.Width()/2,-Rect.Height()/2,Rect.Width(),Rect.Height(),&dcMem,0,0,SRCCOPY);
dcMem.SelectObject(pOldbmp);
3.6插入文字代码:
CStringstr;
str="打砖块游戏";
intx,y;
CSizesize;
pDC->SetTextColor(RGB(255,0,180));
str.Format("%s",str);
size=pDC->GetTextExtent(str,str.GetLength());
x=(int)((double)(-25));
y=(int)((double)(Rect.Height()/2-10));
pDC->TextOut(x,y,str);
str="游戏规则:
按空格键或鼠标右键开始,按Esc键暂停。
目标为:
击落所有的砖块!
";
pDC->SetTextColor(RGB(200,0,150));
str.Format("%s",str);
size=pDC->GetTextExtent(str,str.GetLength());
x=(int)((double)(-Rect.Width()/2+120));
y=(int)((double)(-Rect.Height()/2+150));
pDC->TextOut(x,y,str);
3.7关于游戏设置关卡的代码:
if(m_Init++<2)//如果游戏没有开始运行
{
if(!
m_GameOnOff)
{
InitBricks();//设置关卡
m_GameOnOff=TRUE;//程序初始化时,自动进入游戏
}
if(m_Init==2)
SetTimer(1,10,NULL);//设定时器
}
ShowBricks(pDC);//绘制砖块
TestMarbles();//检测弹球碰撞
ShowMarbles(pDC);//绘制弹球
m_pBaffle->DrawBaffle(pDC);//绘制托盘
}
voidCTestView:
:
InitBricks()//设置关卡
{
intm_BrickMatrix[GameRow][GameColumn]={//砖块分布情况图
1,1,1,0,0,1,0,0,0,0,1,0,0,1,1,1,
1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,
0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,
0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,
0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,
0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,
0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,
0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,
0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,
0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,
0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
//起始块砖块中心点所在位置
doubleStartX=-m_WindowHalfW+m_BrickHalfW;
doubleStartY=m_WindowHalfH-m_BrickHalfH;
for(inti=0;i{
for(intj=0;j{m_Bricks[i][j].SetPosition(StartX+j*m_BrickWidth,StartY-i*m_BrickHeight);//设置砖块位置
m_Bricks[i][j].SetWidth(m_BrickWidth);//设置砖块宽度
m_Bricks[i][j].SetHeight(m_BrickHeight);//设置砖块高度
if(m_BrickMatrix[i][j]>=1)//设置状态
{
m_Bricks[i][j].SetEnable();
m_BrikcsCnt++;
}
else
{
m_Bricks[i][j].SetDisable();
}
}
}
}
voidCTestView:
:
ShowBricks(CDC*pDC)//显示砖块
{
for(inti=0;i{
for(intj=0;j{
if(m_Bricks[i][j].m_Enable)
{
m_Bricks[i][j].DrawBrick(pDC,m_Bricks[i][j].m_XPos,m_Bricks[i][j].m_YPos);
}
}
}
}
3.8碰撞检测函数
根据point±r与客户区的半宽度和半高度之间的关系,可以判断球体是否和砖块或客户区边界发生碰撞。
若发生碰撞,则改变球体的运动方向。
voidCTestView:
:
TestMarbles()//碰撞测试
{
intflagBroder,flagBrick,flagBaffle,Currentflag;
//==============================测试并计算弹球与边界碰撞之后的速度
flagBroder=m_pMarble->TestBorder(m_WindowWidth,m_WindowHeight);
flagBrick=3;//未碰撞
if(flagBroder>=0&&flagBroder<2)//一般碰撞
{
PlaySound((LPCTSTR)IDR_boing,AfxGetInstanceHandle(),SND_RESOURCE|SND_ASYNC);
}
if(flagBroder==0)//x方向碰撞
m_pMarble->SetSpeedX(-m_pMarble->m_SpeedX);//x方向速度取反
if(flagBroder==1)//y方向碰撞
m_pMarble->SetSpeedY(-m_pMarble->m_SpeedY);//y方向速度取反
if(flagBroder==2)//x,y方向同时碰撞
{
m_pMarble->SetSpeedX(-m_pMarble->m_SpeedX);//x方向速度取反
m_pMarble->SetSpeedY(-m_pMarble->m_SpeedY);//y方向速度取反
}
if(flagBroder==4)//出底线,生命值减1
{
PlaySound((LPCTSTR)IDR_alarm,AfxGetInstanceHandle(),SND_RESOURCE|SND_ASYNC);
m_MarbleOnOff=FALSE;//弹球停止运行
m_Life--;//生命值减1
m_pBaffle->SetPositionX(0.0);//重置托盘位置
m_pMarble->SetPosition(MarbleOriX,MarbleOriY);//重置弹球的位置
m_pBaffle->m_Speed=0;//重置托盘的速度
GameOVer();//游戏结束
}
//==============================测试并计算弹球与砖块碰撞之后的速度
for(inti=0;i{
for(intj=0;j{
Currentflag=3;//未碰撞
if(m_Bricks[i][j].m_Enable)//对于有效的砖块进行测试
{
Currentflag=m_pMarble->TestBrick(m_Bricks[i][j]);
}
if(Currentflag!
=3)//如果碰撞
{
m_Bricks[i][j].SetDisable();//砖块无效
flagBrick=Currentflag;
PlaySound((LPCTSTR)IDR_effect,AfxGetInstanceHandle(),SND_RESOURCE|SND_ASYNC);
m_BrikcsCnt--;//砖块数减1
GameOVer();//游戏结束
}
}
}
if(flagBrick==0)//与砖块在x方向碰撞
m_pMarble->SetSpeedX(-m_pMarble->m_SpeedX);
if(flagBrick==1)//在y方向碰撞
m_pMarble->SetSpeedY(-m_pMarble->m_SpeedY);
if(flagBrick==2)//在两个方向上均发生碰撞
{
m_pMarble->SetSpeedX(-m_pMarble->m_SpeedX);
m_pMarble->SetSpeedY(-m_pMarble->m_SpeedY);
}
//================================测试并计算弹球与托盘碰撞之后的速度
flagBaffle=m_pMarble->TestBaffle(*m_pBaffle);
if((flagBaffle==1)&&m_MarbleOnOff)//与托盘发生碰撞
{
m_pMarble->SetSpeedY(-m_pMarble->m_SpeedY);
m_pMarble->SetSpeedX(-m_pMarble->m_SpeedX+m_pBaffle->m_Speed);
PlaySound((LPCTSTR)IDR_boing,AfxGetInstanceHandle(),SND_RESOURCE|SND_ASYNC);
}
}
voidCTestView:
:
ShowMarbles(CDC*pDC)//显示弹球
{
m_pMarble->DrawMarbles(pDC);
if(m_Life>0)
{
if(m_MarbleOnOff)
m_pMarble->MoveMarbles();
}
}
voidCTestView:
:
OnMouseMove(UINTnFlags,CPointpoint)//鼠标移动函数
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
SetCursor(NULL);
if(m_GameOnOff)//如果游戏在运行
{
doublex=point.x;
doubley=point.y;
m_XPos=x-m_WindowHalfW,m_YPos=m_WindowHalfH-y;//设备坐标变换为屏幕坐标
//托盘只在x方向上移动,只考虑左右碰撞
if(fabs(m_XPos)>m_WindowHalfW-m_pBaffle->m_HalfW)//x方向碰撞
{
if(m_XPos>0)//与左侧边界碰撞
m_pBaffle->SetPositionX(m_WindowHalfW-m_pBaffle->m_HalfW);
else//与右侧边界碰撞
m_pBaffle->SetPositionX(-m_WindowHalfW+m_pBaffle->m_HalfW);
}
else
{
m_pB