c++课程设计俄罗斯方块游戏1毕业论文.docx
《c++课程设计俄罗斯方块游戏1毕业论文.docx》由会员分享,可在线阅读,更多相关《c++课程设计俄罗斯方块游戏1毕业论文.docx(10页珍藏版)》请在冰豆网上搜索。
![c++课程设计俄罗斯方块游戏1毕业论文.docx](https://file1.bdocx.com/fileroot1/2022-12/12/9c0abf4b-6815-4c17-b48f-6e40d61b09a9/9c0abf4b-6815-4c17-b48f-6e40d61b09a91.gif)
c++课程设计俄罗斯方块游戏1毕业论文
课程设计报告
课程名称:
面向对象程序设计C++
设计题目:
俄罗斯方块游戏
专业:
计算机科学与技术
姓名:
学号:
指导教师:
2015年12月25日
一、需求分析3
1.1系统概述3
1.2游戏特色3
1.3功能需求3
二、总体设计4
2.1系统模块4
2.2系统业务处理流程5
三、详细设计5
3.1砖块预显示5
3.2分数统计6
3.3砖块移动和游戏暂停的实现7
3.4播放背景音乐8
3.5游戏设置与帮助8
3.6背景位图的插入9
3.7砖块三维化9
3.8俄罗斯方块双人版的实现10
四、测试与结果11
4.1整个游戏运行界面图11
4.2游戏设置与帮助页面图11
五、总结12
一、需求分析
1.1系统概述
《俄罗斯方块》玩家通过键盘控制方块的形状样式和速度,组成相连的1行或1行以上方块会自动消除,方块消除到一定数量后会得到一定的分数,玩家可以升级,从而难度加大,也就是速度加快,玩家还可以通过消除一组方块,使得到的分数翻倍等到更多的分数,造成更强的分数效果。
游戏中玩家可以和其他玩家1V1对战。
1.2游戏特色
《俄罗斯方块》是基于pc休闲平台上的单机对战休闲游戏,这就要求游戏本身不能过于庞大复杂,需要考虑到单机对战的灵活性和多变性。
在游戏中通过对方块速度的变,能够使玩家不仅仅通过自己消除方块来获胜,还可以等到更多的分数,因此获得胜利。
《俄罗斯方块》游戏在传统的俄罗斯方块当中加入了新鲜的游戏元素,例如可爱的方块的颜色,绚目的消除方块特效显示,在游戏本身的简单耐玩的基础上,大大丰富了游戏的观赏性和趣味性,令玩家有了完全的游戏体验,充分享受游戏带来的乐趣。
1.3功能需求
(1)实现双人俄罗斯方块
(2)隐藏菜单栏、工具栏、状态栏
(3)实现难度可以选择
(4)实现下一个砖块预测功能
(5)实现总分统计功能,和每步消除所得分数显示
(6)实现下、左、右、旋转、暂停功能
(7)实现背景音乐播放功能
(8)添加游戏帮助菜单
(9)实现砖块三维化
(10)实现双缓冲避免屏幕闪烁
(11)设置窗口大小,禁用最大化按钮,禁止鼠标拖动改变窗口大小
二、总体设计
2.1系统模块
图2-1
2.2系统业务处理流程
随1机牛一曲啊专块类型和狀态
块类型与状态随叶I:
凯个码览类變和状爲
设锐砖块棘赳
<>J卜落否戟
输出固
■■/宦块/
置顶砖块
将時诀眾£挟
贝遴牆时数纽
诀/|:
拦
N
置顶砖块
祥时川数据乂
图2-2
三、详细设计
3.1砖块预显示
砖块预显示的原理就是在第一次生成砖块的时候,一次生成2个砖块。
然后将第2个砖块预显示,第1个砖块掉下来。
接着将预显示的砖块掉下来,新随机生成的砖块预显示。
这样的话,我们用flagl标记是不是第一次产生砖块
厂倾显示砖块生成部分代码:
if(1==
bTypel-(rand()%NUM_BRICK_TYPES)+l;//rand()%7:
随机产生數字&iOrientl■(unsignedint)(rand()%4);//随机状态左七flagl=0i
}
brickType-bTypel^//rand()K7:
趣机卢生0-6ffi動宇*
InitOrientation=iOrientl;//随机状态FF
if(9“flael)//2
{
bTypel-(rand()%HLh'_BRICK_TYPE5)+l;//rand(:
<7:
隨机产生•甜獨!
宇*iOrientl■(unsignedint}(rand()%斗);"随机状态日订
if(bTypel■■1)
activeB-ickyi=newCISrick;/FE腌多态性的体现
elseif(bTypel=-2)
activeBrickYl*newCLBrick;
elseif(bTypel==3)activeBrickYl-nthCSBrick;
"...省略4,5忑昇
activtBr1ck¥1->seKo1our((un$ignedchar)bTypel);,设贵砖块两色activeBr让kYlTpuUtTupliOLiEntl,binJidth2);畫顶binYl->eetImage(outputIna百亡丫1);//将固定块拷贝到制寸数组activeBrickVl*>&perator>>(outputIfrageYl);将冈I]左生的加入.
3.2分数统计
这里实现了,显示每次消除所得的分数和游戏总共所得的分数。
由于,我们有一个返回消除了多少行的函数removeFullLines(),所以我们将这个返回值乘以积分规则里面的值,就实现了显示每次消除所得的分数。
然后游戏总分就是累加每次得到的分数值。
因为砖块最多就是消除4行,所以这里用个switch()语
句来实现。
m_num是一个成员变量,保存的就是removeFullLines()的返回值。
"分數统计部分代码:
switch^rr_nurr2)
£
case0:
{
m_num2=m_nu[n2*0;nun)Lines2+=m_nuin2;
Jbreak;
case1:
{
m_num2=m_numi*5Q;nuniLines2+=m_num2;
}break;
"...省略打3
case4:
{
m_num2=m_num2*1000;num^inesi+=m_num2;
Jbreak;
default:
break;
3.3砖块移动和游戏暂停的实现
这里原本是需要响应键盘按下事件的,所以需要添加WM_KEYDOW息响应
然后将函数传进来的nChar,也就是你按的键盘值,和你游戏中设定的移动按键比较。
从而执行相应的操作。
同时这里也要熟悉一下虚拟按键码。
但是由于我们添加了位图按钮,导致键盘按键事件响应不了,我们这里就重载了PreTranslateMessage函数,在这个函数里面拦截按键消息,从而响应。
1一键下落:
这里用了一个循环,直到下落到砖块与边界或者其他砖块产生冲突才停止下落。
2空格暂停:
暂停的原理就是关闭定时器,KillTimer(l);//关闭定时器
3空格继续:
SetTimer(O,difficulty,NULL);〃继续恢复原来的下落速度
"具体代码如下:
BOOLCTetrisView:
:
PreTranslatereasagepf-'sg)
if(pPsg->Te5sage"EyDC'i.N)
{
//,,i
if(VK_ESCAPE==pMs£*>wParam)//ESCjEi±i
{PostQuitMessage(0};
}
if(VK_SPACE==p^5E->wPara(n&&n_Stop1){
KillTiiner(l);//^闭定时器
KillTiner
(2);//^闭定时器m_Stop工0;
}
elseif(n_Stop--0)
<
SetTimertl^ifficulty^NULL};//^续
SetTimer(2,difficulty?
HULL);■绻续m_Stop=1;
}
}
return匚Vieu:
:
PreT^anslate^-essageipK,sg);
3.4播放背景音乐
添加头文件:
#inelude//播放音乐。
然后在工程->设置->链接->对象/库模块里面添加winmm.lib
然后就将已经准备好的.wav格式的音乐引入VC中。
这里可以自己先去下
载.mp3格式的音乐,然后用格式工厂转换一下格式,我就是这么干的。
心耳体爵战昔乐和关闭音乐的代颐下:
PlaySDund((LPCT5TR]IQH_WAVE1±AfInstanceHandl«(}SND_RESOURCE|ENQ_AS¥WC);}j逵加在71财壬我里面
PlaySounfKNULL,NULL^SND.FILEHAME);音乐
3.5游戏设置与帮助
这里就是调用了一个对话框,用来做一些解释说明。
实现步骤:
1插入一个对话框
2给对话框关联一个类
3在需要弹出对话框的函数里面定义一个对话框的对象,然后DoModal().弹出模态对话框。
静态文本超链接颜色和鼠标样式:
由于静态文本是不能响应鼠标点击事件的,所以我们要现将静态文本的ID改掉口:
IDCSTATICBl然后在样式中将通知勾选上。
这样就可以响应鼠标点
//TWOfAddyourspscislizeicadThereBHct/orcell■theclass
击事件了。
Gmt£,应「二寸J;
接着就是要实现鼠标移动到超链接上面显示一个手的形状,这里我们需要载入一个手型的光标。
本来是载入这个:
IDC_HAND就可以了,但是当我载入它的时候,编译,提示'TDC_HAN未定义。
查了一下原来是版本的问题,不支持手型的。
后来谷歌上找到了一个可以载入手型的方法:
m_hCursor=:
:
LoadCursor(NULL,MAKEINTRESOURCE(32649));
if(pHif-.x>Mct.l■静upV4Ftrt-riftitup*f3<-mct’tap*tpftfi-^pr-^就是用一个全局的载入光标函数来载入。
光标载入好之后,添加一个鼠标移动事件的响应,当鼠标移动到指定区域,显示手型光标。
returnCZ-ldl-jtP-eT--:
ii;
3.6背景位图的插入
这个就是界面美化神器了,就是因为这张背景整个游戏才变得比原来的美观了几倍。
第一次做的单文档,白色背景,是在是太不友好了。
这个背景图片是我从4399上面截图下来的,然后用ps制作了一下,使其符合我的要求。
"插入背杲囹片的代冯
CBitrrapbmp;
binp.^oadBitmapdDB.BITKLAPl);///■加载f立圏I
m_brushBackground*Cre^tePatternBrush(ibmp);创建位图画刷
CRectrect;
GetClientRect(&rect容户IK大小
pDC->Fi11Rett(rect广u百hBxIcg广ourid);〃将拒形区域用位图填充
3.7砖块三维化
这里用到函数Draw3dRect()实现砖块三维化,其中需要3个参数参数:
1.矩形区域;参数2:
RGB()参数3:
RGB():
voidDraw3dRect(LPCRECrIpRectfCOLORREFclrTopLe-FttCOLORREFclrBottonlUEht);
其中后面两个参数,由下面这两个函数返回。
具体代码如下:
COLORREF匚TetrisView:
:
6etLightColor(COLORREFm_crBody){
BYTEr=GetRValue(ir_crBody);
BYTEg=GetGValue(m_crBody);
BYTEb=QetBValue(m_crBody);
r-:
r+COLOR_CHA^GE>25S?
255:
r+CDLOR_CHANGE;
g=g+COLOR_CHANGE>255?
255:
g4-COLOR_CHANGE;
b-b+COLOR_CHANGE>255?
255:
b+COLOR_CHAMGE;returnRGB(r,g?
b);
}
COLORREFCTetrisView:
:
GetDerkColor(COLORREFT_trBod>0
BYTEr二GetRVelue(fn_crBody);
BYTEg=GetGValue(m_crBody);
BYftb=GetBValu^(m_crBody);
r=r-匚OLOR_CHANGE<0?
0:
r-COLOR.CHAHGE;
g-E-匚OLOR_CHANGE<0?
9:
g-COLOR_CHANCE;
b=b-COLOR_CHANGE<0:
b-COLOR_CHANGE;returnRGB(rjg^b)J
3.8俄罗斯方块双人版的实现
其实实现双人版的很简单,就是将FillRect()填充区域右移一定距离就实现
了双人版的。
当然,是在你将第二个游戏的代码也编写好的前提下,不然只是把
左边玩家的界面再显示一次,那没得意思。
同理,预显示也就是这么实现的,就是调整了一下砖块显示的位置。
/M坪航家上辅戏面橫显示的牝码=
for(i
£
for(j®&ij(
rd=€Rect(J*riS12e+149ai*nSlze+70,(i*l)*ri5ize+7@);
rc2=WectCi^nSil^SSjPnSiEe+7^(ji+l>*n5iM+«S5j(i+i)*n$lw+TO)j
打综制面扳
//^SlLplayer
if(B!
=ImsEO[i][j])
{
pK->FillRect(rcljiCBrush(0rickColar[iragel[i][j]])),;打画临时直块(运纳中)
pDC->Drnn3-dRect(rt!
B(Bifci.ckCclofi[iTia£el[iJ[J]]LGetDarkColor(BrlekCc10^(imfleel[£J[JJ]))j}
//畀面2player
if(0!
-iiMge2[i][j])
pDC->Fillftect(rc2JSCBnishfBriekColor[11][jj]))/画临旳鹫块(运动申)
pK・>DrawldRect(rc2p6BtLightCnlnr(BricKCQlar[image2GetDarkCDlor(BrLcfcCalor(image2[i)[j]]
四、测试与结果
4.1整个游戏运行界面图
其中Next是预显示,Point是每次固定块后所得的分数,X0用于播放/暂停背景音乐,a,b,c用于选择游戏难度。
START点击开始游戏。
下面还有个总分统计栏。
图4-1
4.2游戏设置与帮助页面图
图4-2
五、总结
这次编写双人版俄罗斯方块,主要参照了VC+实验指导书,界面主要就是插入了一个位图背景,图是从4399上面截图下来的,然后ps成自己需要的大小并转化成.bmp格式。
插入后,再就是在适当的地方显示砖块和分数统计,这样一个界面就做好了。
界面上的按钮,我是用位图按钮CBitmapButton实现的,这里有个小插曲,就是4张图片的大小问题,我本来的意思是想让鼠标点击的时候就显示一张小一点的图片,从而达到按钮的效果,所以我就做了4张大小不同的位图,导致了后来的白边的产生。
另外,由于添加了位图按钮导致了按键事件WM_KEYDOW鼠标点击事件WM_LBUTTONDOW晌应,我也不知道是为什么。
好在MFC中消息都要经过翻译后再发送,所以我就在PreTranslateMessage实现了按键和鼠标点击事件,开始不知道pMsg->pt传送进来的是相对于桌面的坐标。
另外还有一个问题就是关于CRect的问题,女口:
我定义了一个CRectrect(10,10,100,100);然后我将rect.top,rect.left…转换成CString类型,
然后pDC->TextOut输出出来确是(0,0,99,99)不明白这是什么原因。
总之,这次小游戏的编写,让我自己学到了不少的东西,对MFC勺操作也更加熟练了。