游戏最终界面如图:
目录:
题目要求
参考VC++程序设计实验指导书,将上次编写的dos版双人俄罗斯方块改写成VC界面版。
功能需求
①实现双人俄罗斯方块
②隐藏菜单栏、工具栏、状态栏
③实现难度可以选择
④实现下一个砖块预测功能
⑤实现总分统计功能,和每步消除所得分数显示
⑥实现下、左、右、旋转、暂停功能
⑦实现背景音乐播放功能
⑧添加游戏帮助菜单
⑨实现砖块三维化
附加:实现双缓冲避免屏幕闪烁。设置窗口大小,禁用最大化按钮,禁止鼠标拖动改变窗口大小。
总体设计
系统模块
系统业务处理流程
详细设计
砖块预显示:
砖块预显示的原理就是在第一次生成砖块的时候,一次生成2个砖块。然后将第2个砖块预显示,第1个砖块掉下来。接着将预显示的砖块掉下来,新随机生成的砖块预显示。这样的话,我们用flag1标记是不是第一次产生砖块。
//预显示砖块生成部分代码:
if (1 == flag1)//1
{
bType1 = (rand() % NUM_BRICK_TYPES) + 1;//rand()%7:随机产生0-6的数字。
iOrient1 = (unsigned int) (rand() % 4);//随机状态0-3
flag1 = 0;
}
brickType = bType1;//rand()%7:随机产生0-6的数字。
initOrientation = iOrient1;//随机状态0-3
if (0 == flag1)//2
{
bType1 = (rand() % NUM_BRICK_TYPES) + 1;//rand()%7:随机产生0-6的数字。
iOrient1 = (unsigned int) (rand() % 4);//随机状态0-3
if (bType1 == 1)
activeBrickY1 = new CIBrick; //动态多态性的体现
else if (bType1 == 2)
activeBrickY1 = new CLBrick;
else if (bType1 == 3)
activeBrickY1 = new CSBrick;
//...省略4,5,6,7
activeBrickY1->setColour((unsigned char)bType1);//设置砖块颜色
activeBrickY1->putAtTop(iOrient1, binWidth/2);//置顶
binY1->getImage(outputImageY1); //将固定块拷贝到临时数组
activeBrickY1->operator>>(outputImageY1); //将刚产生的加入
}
分数统计:
这里实现了,显示每次消除所得的分数和游戏总共所得的分数。由于,我们有一个返回消除了多少行的函数removeFullLines(),所以我们将这个返回值乘以积分规则里面的值,就实现了显示每次消除所得的分数。然后游戏总分就是累加每次得到的分数值。因为砖块最多就是消除4行,所以这里用个switch()语句来实现。m_num2是一个成员变量,保存的就是removeFullLines()的返回值。
//分数统计部分代码:
switch(m_num2)
{
case 0:
{
m_num2 = m_num2*0;
numLines2 += m_num2;
}break;
case 1:
{
m_num2 = m_num2*50;
numLines2 += m_num2;
}break;
//…省略2,3
case 4:
{
m_num2 = m_num2*1000;
numLines2 += m_num2;
}break;
default:break;
}
砖块移动和游戏暂停的实现:
这里原本是需要响应键盘按下事件的,所以需要添加WM_KEYDOWN消息响应。然后将函数传进来的nChar,也就是你按的键盘值,和你游戏中设定的移动按键比较。从而执行相应的操作。同时这里也要熟悉一下虚拟按键码。
但是由于我们添加了位图按钮,导致键盘按键事件响应不了,我们这里就重载了PreTranslateMessage函数,在这个函数里面拦截按键消息,从而响应。
①一键下落:这里用了一个循环,直到下落到砖块与边界或者其他砖块产生冲突才停止下落。
②空格暂停:暂停的原理就是关闭定时器,KillTimer(1);//关闭定时器
③空格继续:SetTimer(0,difficulty,NULL);//继续 恢复原来的下落速度
游戏难度选择:
默认的难度是简单,就是在构造函数中将