魔方游戏vc程序设计Word下载.docx
《魔方游戏vc程序设计Word下载.docx》由会员分享,可在线阅读,更多相关《魔方游戏vc程序设计Word下载.docx(56页珍藏版)》请在冰点文库上搜索。
![魔方游戏vc程序设计Word下载.docx](https://file1.bingdoc.com/fileroot1/2023-5/1/4408edf1-8032-409b-b154-9810cd31e13f/4408edf1-8032-409b-b154-9810cd31e13f1.gif)
(1)建立魔方的三维模型。
(2)初始化时随机生成一个打乱顺序的魔方,并显示。
(3)用户可以选择通过键盘某一行或者某一列进行旋转。
每次旋转结束后,判断魔方的当前状态是否符合游戏结束的条件,如果符合,则提示用户游戏结束。
否则,游戏继续进行。
游戏另外附加的功能还包括:
(1)保存当前魔方状态。
(2)从数据文件中加载一个魔方。
(3)缩放魔方大小。
(4)查看正确答案。
五、详细设计
1.魔方的三维模型建立
魔方的数据主要体现在魔法表面各个正方形的颜色排列上,只要表达了这些颜色数据,也就表达了魔方状态。
按照OpenGL默认的三维坐标进行建模。
魔方几何中心位于坐标原点。
为了便于计算和处理,给每个面进行编号。
编号如下:
0:
上平面
1:
前平面
2:
右平面
3:
后平面
4:
左平面
5:
下平面
同时建立面之间的位置相对关系。
用数组“intcompensation[6]={5,3,4,1,2,0};
”来表示这种关系。
为了进行魔方游戏,需要用一种结构表示和记录当前魔方状态,这里用数组“color[6][9];
”来储存6个面中共54个正方形颜色。
各种颜色定义如下:
floatmat_diffuse[6][4]={
{0.6,0.0,0.0,0.0},//0:
红色
{0.6,0.6,0.0,0.0},//1:
黄色
{0.6,0.6,0.6,0.0},//2:
白色
{0.0,0.6,0.0,0.0},//3:
绿色
{0.6,0.0,0.6,0.0},//4:
紫色
{0.0,0.0,0.6,0.0}//5:
蓝色
};
floatmat_lighted[6][4]={
{1.0,0.0,0.0,0.0},//0:
{1.0,1.0,0.0,0.0},//1:
{1.0,1.0,1.0,0.0},//2:
{0.0,1.0,0.0,0.0},//3:
{1.0,0.0,1.0,0.0},//4:
{0.0,0.0,1.0,0.0}//5:
通过逐个绘制方块来绘制某一时刻魔方的模型
//多边形的绘制模式,前后两面都要绘制并且是填充方式进行绘制
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
//设置材质属性,不发光
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,mat_none);
//设置材质属性,没有镜面反射
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_none);
//魔方每个正方形小方块的大小
doubleactuallen=(sidelen-2*stitch)/3;
//////////开始绘制上底面/////////
//起点的x和z方向的两个参数
startpoint1=-sidelen/2;
startpoint2=-sidelen/2;
//按照color存储的颜色绘制上底面的9个方块
for(i=0;
i<
3;
i++)
{
for(j=0;
j<
j++)
glBegin(GL_POLYGON);
if(IsSelected[0][3*i+j]==0)
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diffuse
[color[0][3*i+j]]);
else
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_lighted
//这里用多边形来代替方块
glVertex3d(startpoint1,sidelen/2,startpoint2+margin);
glVertex3d(startpoint1+margin,sidelen/2,startpoint2);
glVertex3d(startpoint1+actuallen-margin,sidelen/2,startpoint2);
glVertex3d(startpoint1+actuallen,sidelen/2,startpoint2+margin);
glVertex3d(startpoint1+actuallen,sidelen/2,startpoint2+actuallen-margin);
glVertex3d(startpoint1+actuallen-margin,sidelen/2,startpoint2+actuallen);
glVertex3d(startpoint1+margin,sidelen/2,startpoint2+actuallen);
glVertex3d(startpoint1,sidelen/2,startpoint2+actuallen-margin);
glEnd();
startpoint2+=actuallen+stitch;
}
startpoint1+=actuallen+stitch;
startpoint2=-sidelen/2;
}
//////////绘制上底面结束/////////
其他平面的绘制代码见源程序
2.魔方的旋转
对魔方的旋转实际上是就是对魔方表面的颜色状态的改变。
每次通过转动来改变魔方状态时,只能转动某一行或者某一列,称之为层。
用两个参数“Intm_nCurFace;
”和“intm_nCurline;
”结合在一起来确定转动的是哪一层。
m_nCurFace用来表示当前操作的层所在的平面方向:
yoz平面
xoy平面
xoz平面
m_nCurline的取值对应相同方向的三个层,0,1,2分别表示左中右层。
voidCMagicCubeView:
:
RotateMagicRight(intface,intline)
{
inttemp[3];
inti,j;
//保存前一个面
temp[i]=color[involvedfaces[face][0]][rotation[(face*3+line)*4][i]];
//旋转
for(i=1;
=3;
for(j=0;
{
color[involvedfaces[face][i-1]][rotation[(face*3+line)*4+i-1][j]]=
color[involvedfaces[face][i]][rotation[(face*3+line)*4+i][j]];
}
for(i=0;
color[involvedfaces[face][3]][rotation[(face*3+line)*4+3][i]]=temp[i];
if(line==0)
RotateFaceRight(involvedfaces[face][4]);
elseif(line==2)
RotateFaceRight(compensation[involvedfaces[face][4]]);
}
//逆时针旋转编号为face的表面
RotateFaceLeft(intface)
intswapm[9];
inti;
9;
swapm[i]=color[face][singleleft[i]];
color[face][i]=swapm[i];
3.交互手段
交互分为两类。
一是选择当前转动层,二是对选定的层进行顺时针或逆时针旋转。
(1)选择
通过PageUp和PageDown改变m_nCurFace的值。
确定操作的层的方向后,再通过光标“↑”和“↓”更改m_nCurLine选择某一层。
(2)转动某一层
通过“←”和“→”来选择逆时针还是顺时针转动该层。
转动的方向指的是从左侧面、前平面或者下底面到魔法中心的视线方向所看到的转动情况。
(3)整体旋转
在转动魔方某个层时,需要查看魔方整体情况,以确定下一步的动作。
这时需要通过鼠标拖动魔方绕着x轴或者y轴进行整体旋转。
OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags)
CMagicCubeView*pDoc=(CMagicCubeView*)GetDocument();
switch(nChar){
//切换到下一个面方向
caseVK_PRIOR:
m_nCurFace=(m_nCurFace+1)%3;
m_nCurLine=0;
break;
//切换到上一个面方向
caseVK_NEXT:
m_nCurFace=(m_nCurFace+2)%3;
//切换到下一个层
caseVK_DOWN:
m_nCurLine=(m_nCurLine+1)%3;
//切换到上一个层
caseVK_UP:
m_nCurLine=(m_nCurLine+2)%3;
//逆时针旋转第(m_nCurFace*3+m_nCurLine)个层
caseVK_LEFT:
RotateMagicLeft(m_nCurFace,m_nCurLine);
caseVK_RIGHT:
RotateMagicRight(m_nCurFace,m_nCurLine);
case'
A'
a'
m_xRotation+=90;
if(m_xRotation>
=360)
m_xRotation-=360;
S'
s'
m_yRotation+=90;
if(m_yRotation>
m_yRotation-=360;
Q'
q'
m_xTranslation+=0.2;
if(m_xTranslation>
=1)
m_xTranslation=1;
W'
w'
m_xTranslation-=0.2;
if(m_xTranslation<
=-1)
m_xTranslation=-1;
InvalidateRect(NULL,FALSE);
CView:
OnKeyDown(nChar,nRepCnt,nFlags);
4.保存魔方当前状态
当用户终止游戏时,可保存当前魔方数据到数据文件中,下次打开应用程序后可以加载该数据,继续进行未完成的游戏。
保存即将54个表面方块的颜色编号按顺序写入文件:
ofstreamfout("
new.mf"
);
for(inti=0;
i<
6;
i++)
for(intj=0;
j<
9;
fout<
<
color[i][j];
加载数据:
Fout>
>
5.显示正确解法
魔方初始时是根据随机数挑选层来逆时针旋转,这样产生了一个随机打乱的魔方,我们可以通过记录随机序列方式记下魔方被打乱的轨迹。
将这种轨迹反过来分析,就是对应模仿的正确解法。
保存轨迹:
method.mf"
for(inti=0;
num;
intface=rand()%3;
intline=rand()%3;
RotateMagicLeft(face,line);
//
Fout<
face<
"
"
line<
endl;
获得正确解法并将结果显现出来:
OnAnswer()
ifstreamfin("
intface,line;
vector<
int>
m;
chars[][20]={"
yoz方向左层"
"
yoz方向中层"
yoz方向右层"
xoy方向近层"
xoy方向中层"
xoy方向远层"
xoz方向底层"
xoz方向中层"
xoz方向顶层"
};
CStringstr;
for(;
fin>
face&
&
fin>
line;
)
m.push_back(face*3+line);
inti=m.size()-1;
while(i>
=0)
//<
--表示逆时针,-->
表示顺时针
str+=s[m[i]];
str+="
顺时针旋转\n"
;
i--;
MessageBox(str);
六、具体实现
(1)新建工程,选择“MFC应用程序”,程序类型为多文档方式,工程名为MagicCube。
(2)选择资源视图,添加菜单项。
对菜单进行编辑,在菜单项空白处单击右键,选择“新插入”进行菜单项插入。
在属性窗口将菜单项的Popup属性False,在修改Caption和ID属性为“保存”和“ID_SAVE”。
按同样过程添加“加载”和“显示答案”菜单项。
插入菜单项
(3)为菜单项添加响应函数。
在需要添加响应的菜单项上单击右键,选择“添加事件处理程序”
为菜单项添加事件处理程序
弹出“事件处理程序向导”对话框,在向导的“类列表”中选择CMagicCubeView类,在“消息类型”中选择“COMMAND”,再单击“添加编辑”按钮。
跳转到对应的代码区域。
依次添加菜单项的事件响应函数。
事件处理程序向导
响应事件代码
(4)添加其他系统消息响应函数。
在属性窗口中选择“消息”标签。
选择对应消息,添加响应函数。
需要处理的消息函数包括:
“WM_CREATE”、“WM_PAINT”、“WM_SIZE”、“WM_DESTROY”、“WM_KEYDOWN”、“WM_LBUTTONDOWN”、“WM_LBUTTONUP”、“WM_MOUSEMOVE”。
属性窗口
(5)在View类的头文件中添加下列文件:
#include<
gl/gl.h>
gl/glu.h>
gl/glaux.h>
要使用OpenGL函数库还要链接相应的库文件。
在“项目”菜单中选择“MagicCude属性”项
打开项目属性
选择“配置属性”→“连接器”→“输入”,在“附加依赖项”编辑框中,添加三个静态库openg132.lib、glu32.lib、glaux.lib,中间用空格隔开。
修改附加依赖项
(5)参照源代码在文件中加入各种声明、定义与成员函数等代码
七、系统测试
运行程序,运行结果如图。
通过PageUp和PageDown可确定操作的层的方向,再通过光标“↑”和“↓”可选择某一层。
可通过鼠标观察魔方整体旋转。
程序运行结果
单击“显示答案”按钮,可获得魔方的正确解法。
八、总结
1、缺点与不足
开发基于OpenGL的应用程序,本设计采用库文件中的核心库(gl)、实用库(glu)、辅助库(glaux)等。
虽然顺利完成课程设计,但是还存在很多不同之处,有很多地方值得改进。
魔方在旋转的过程中,要可以从不同的视角观察,这样使玩家更容易操纵魔方。
本实验通过PageUp和PageDown确定操作的层的方向后,再通过光标“↑”和“↓”选择某一层,“←”和“→”来选择逆时针还是顺时针转动该层。
感觉上交互不是很好。
个人希望在键盘操作的同时可以通过鼠标来选择某一层的旋转。
同时立体感做的不够好,没有转动的过程动作,这个有点抽象。
也是游戏一个缺点之一。
2、收获、心得
这次课程设计中,我们在添加部分函数时出现了一些状况,在实现魔方的交互手段时,出现了问题。
当时魔方只能在xoy面上选择层,而不能通过PageUp和PageDown确定操作的层的方向。
通过检查并修改函数终于解决了问题,魔方可以在xoy面、xoz面、yoz面上任意转换。
还有就是加了旋转函数后遇到了一些问题,旋转过程中有时候会出现折叠和重叠现象,经过仔细的检查修改,发现原因是在调用旋转函数时,有部分子块的运动没有写入函数,于是问题得到了解决。
这次课程设计,学到了很多。
不仅巩固了先前学的MFC程序设计知识,而且也培养了我们的动手能力,更令我们的创造性思维得到了一定程度的拓展。
此外,我们还复习了C语言知识,也对编程及3D设计产生了一定的兴趣,分析问题和解决问题的能力也得到了不小的提高。
并且,我们也学到了一些人生的道理。
在做一件看似很难的事时,我们要有一个总体的框架,不要有畏难心理。
静下心来,沉着的分析问题,问题总会迎刃而解的。
因此,成功的关键在于你是否拥有这样的心理。
九、参考文献
[1]聂江武,杜娜,周峰VisualC++.NET2005基础与实践教程2007年9月
[2]孙鑫VC++深入详解第三版北京电子工业出版社2007年1-26
[3]杨柏林,陈根浪,徐静OpenGL编程精粹第三版北京机械工业出版社2010年1-121
[4]周纯杰,刘正林,何顶新,周凯波标准C语言程序设计及应用第二版武汉华中科技大学出版社2008年1-263
[5]DaveShreiner,TheKhrononsOpenGLARBWorkingGroupOpenGL编程指南第七版北京机械工业出版社2010年21-328
十、源代码
//MagicCubeView.h:
CMagicCubeView类的接口
#pragmaonce
classCMagicCubeView:
publicCView
protected:
//仅从序列化创建
CMagicCubeView();
DECLARE_DYNCREATE(CMagicCubeView)
//属性
public:
CMagicCubeDoc*GetDocument()const;
//OpenGL绘图描述表
HGLRCm_hGLContext;
//像素格式索引
intm_GLPixelIndex;
//记录鼠标左键是否按下
BOOLm_LeftButtonDown;
//记录左键按下时,鼠标位置
CPointm_LeftDownPos;
//绕x轴旋转的弧度
floatm_xRotation;
//绕y轴旋转的弧度
floatm_yRotation;
//x轴方向的平移
floatm_xTranslation;
//y轴方向的平移
floatm_yTranslation;
//z轴方向的平移
floatm_zTranslation;
//x轴方向的缩放比例系数
floatm_xScaling;
//y轴方向的缩放比例系数
floatm_yScaling;
//z轴方向的缩放比例系数
floatm_zScaling;
//设置窗口像素格式
BOOLSetWindowPixelFormat(HDChDC);
//初始化参数
voidInit(void);
//绘制场景