2111.基于Visual C++实现的单机版俄罗斯方块游戏的设计毕业论文 .doc
本科生毕业设计 基于Visual C+实现的单机版俄罗斯方块游戏的设计摘 要俄罗斯方块是非常传统的游戏,操作简单,难度却不低,广受娱乐界欢迎。给人们的生活带来了健康愉快的补充,唯美的艺术享受。本文在基于Visual C+实现的单机版俄罗斯方块游戏的基础上,深入的研究MFC框架中的各个类的关系和它们内部之间的联系。主要工作和结论:1. 分析了俄罗斯游戏规则。2.系统的介绍了实现俄罗斯方块游戏的算法设计过程。3. 将研究的思路运用于实际,在VC+6.0平台下实现了俄罗斯方块游戏。关键词:俄罗斯方块游戏;VC+;MFC框架AbstractRussia is a very traditional box of the game, simple operation, the difficulty is not low, widely welcomed by the entertainment industry. To the people's life a happy and healthy complement to the flavor of the enjoyment of the arts. In this paper, based on the Visual C + + to achieve the single version of the Russian box on the basis of the game, MFC-depth study in the framework of various types and their internal relations between the links. And the main conclusions : 1. Analysis of the Russian rules of the game. 2. The system introduces a game of Russian box algorithm design process. 3. Will examine the practical application of ideas, in VC + +6.0 platform under the Russian box game. Key words : Russian box game; VC + +; MFC framework 目 录II摘 要IABSTRACTI1 引言31.1 选题及研究意义31.2 论文研究的主要内容32.1 APP应用程序类物件42.2 文档视图机制52.3 DOCUMENT文挡操作62.4 文档-视图的关联63 俄罗斯游戏分析和总体设计73.1 俄罗斯方块游戏功能描述83.2 游戏规则分析84 俄罗斯方块游戏的实现94.1游戏核心数据的抽象与设计104.2 操作方法的抽象与设计134.3 流程的设计与实现154.3.1 正常流程的设计154.3.2 正常流程的实现(定时处理)164.3.3中断操作流程的设计194.3.3中断操作流程的实现204.4 游戏区域绘图的实现214.4.1位图资源的准备214.4.2绘图机制设计224.4.3 绘图环境资源的初始化和释放224.4.4 游戏区域的绘制245.功能的完善275.1 游戏背景音乐的实现295.2 工具栏快捷键的实现30结束语33参考文献33致 谢34本科生毕业论文俄罗斯方块游戏的实现1 引言我们国家正处于全球文化产业日新月异大格局中,电子游戏、网络游戏的发展速度之快,更是令人眼花缭乱,目不暇接。未来的电子和游戏发展趋势必将是更智能化、更艺术性、更人性味。在高性能的硬件设备的支持下,游戏的驱动引擎更具威力,控制功能更加完备,在一个错综复杂的极度扩张的游戏大世界中,带着超乎常人智慧的人工智能的应对力,使得所有要素包括艺术的风格、情感的互动、故事的铺展、视觉的表现、用户的界面,融合为有机的一体,给人们带来更丰富的娱乐和体验。好的游戏给人们的生活带来了健康愉快的补充,唯美的艺术享受,潜默的教育功效。本系统采用VC+为主要开发工具设计实现了一个单机板的俄罗斯方块游戏。与其他程序相比,笔者的作品有三个特色:一是精心设计的人机界面,不仅友好而且易于操作。二是笔者的游戏采用的是单机板。三是采用MFC应用程序开发模型进行编制,使开发人员减轻创建Windows应用程序的负担。网络版的俄罗斯方块游戏是两个玩家通过网络进行较量,但在游戏过程中数据要通过服务器进行传送,网络版游戏经常会出现断线、超时等情况这些都是因为网络的速度比较慢造成的。而笔者设计的俄罗斯游戏虽然是单机版的,但速度快,提高了效率。1.1 选题及研究意义俄罗斯方块游戏是一个比较经典的游戏,根据软件工程有关的规范,以合理的开发原则,设计出单机的俄罗斯方块游戏,并给人们的生活带来唯美的艺术享受和健康愉快的补充。游戏软件是一种与文化背景密切联系的产品,具有很强的民族性和丰富的文化内涵。伴随着游戏软件在市场上的销售,与其相关的文化也随之传播。因此发展我国自主的益智、健康的游戏软件已是当务之急。游戏是一种基于计算机的应用软件,是新型的休闲娱乐方式。当前开发的游戏软件应该做到知识性、娱乐性、趣味性、教育性相统一。1.2 论文研究的主要内容在论文完成过程中,认真学习了游戏开发的基本技术,OOD方法软件设计的基础知识,VC+程序设计语言等。结合游戏开发的过程、算法的设计与分析(如下坠物的生成、下坠物随机选择、游戏区画板实现的方法等)、软件工程等角度重点研究了实现游戏的算法和采用VC+平台设计游戏的优点和现存结构的不足之处。以下是论文的组织结构:第1部分是引言,主要介绍论文选题的意义、选题背景等相关情况。第2部分概述MFC应用程序框架。第3部分是游戏规则的分析。第4部分是游戏算法的实现、游戏功能模块、操作界面以及系统分析及设计。第5部分是对整个论文的结束语。对论文的主要工作作了归纳总结,分析了进一步需要做的工作。2 MFC应用程序架构传统的Windows应用程序的开发使用API(Application Programming Interface)函数。API函数的功能主要是为Windows应用程序开发提供统一的编程接口。在使用API编程的过程中,窗口的创建和消息的处理都需要手工编码。一个简单的Windows应用程序的代码需要上百行,这使Windows应用程序开发变成了一件繁重的工作。现在编程,都是在Visual C+ 环境下采用基本MFC(Microsoft Foundation Class)的Windows编程方法。Microsoft基本类库MFC是一个Windows应用程序框架,它是C+类结构的扩展。利用MFC提供的面向对象程序行色机的框架,可大大减轻程序开发人员创建Windows应用程序的负担。MFC提供了管理窗口、菜单、对话诓的代码,可实现基本的输入输出和数据的存储。此外,MFC还提供一个应用程序来发模型,此模型被称为文档视图模型。文档视图模型视将应用程序数据与用户界面元素分离的一种应用编程方法,它允许这两部分程序独立存在。这样,程序员在更改其中部分代码的时候,不会大幅度地更改另一部分。该游戏的实现采用 MFC框架。在构架类视图中有MFC 基本架构组合 : App(应用程序)类、Document(文档)类、View(视图)类、Frame(框架)类和用于提示关于作者的对话框CAboutDlg类。下面对这几个类做一个简单的列表,如表2.1所示。表2.1 MFC应用程序架构表类别基类 描述ApplicationCwinApp代表应用程序的核心DocumentCdocument包含应用程序的数据集Windows Cwind主要用于图形用户界面(GUI)的对象,可以处理常见的 Windows消息FrameCframeWnd用于应用程序的主要Windows框架ViewVciew用于显示数据并与文档Document对象交互2.1 APP应用程序类物件每种语言都有一个程序入口(主函数),如C/C+语言的 main()函数。总地来说, main()函数的调用与终止代表着程序执行的开始与结束,在程序运行的过程中,无非是对一些业务性的功能流程进行不断的处理,当完成后才退出程序。其实,所有的程序也是采用同样的方法去实现, MFC机制巧妙地利用了Application 类去封装实现了这样的效果功能,每个CWinApp类对象实体都代表应用程序本身,它是基本的 Application Class(应用程序类),其封装了 Windows-based 应用程序的初始化、运行、 Message 映射和终止等功能。假如创建了这样的一个对象实体,在运行期间处理初始化、消息映射、或者其他动作时就可以通过属性操作的调用去实现,而不像拥有结构化设计思想的 mainO 函数那样的顺序去实现。那么,现在就来看看这个 CWinApp 类对象的性质。在 MFC框架中,应用程序必须有且仅有一个从 CWinApp 派生的 Class Object(类物件),这个 Object 在 Windows 创建之前就会被创建,也就是说这个Object 会和其他 C+ 全局 Object 同时创建。当 Windows 调用 WinMainO 时(在MFC应用程序中,不必亲自调用 WinMainO,因为机制已经对它封装好,当应用程序启动时会由框架自动调用),这个 Object已经可用了,并且该 Object是全局的。 当用AppWizard创建DocumentNiew 模式应用程序时,AppWizard会声明一个从CWinApp派生的Application Class, 因此,由AppWizard 所产生的.cpp文件中还包括 Message 映射、空的构造函数、一个应用程序 Object(即一个变量)和InitInstanceO函数。AppWizard提供的源代码和Message映射可以满足一些基本的任务,但在通常情况下,还是需要手工修改那些源程序,特别是要修改Initinstance()函数。在 CWinApp 中,有以下几个关键的可重写的成员数。 ·InitInstance(): 此函数对文档模板(Document Template)进行创建和初始化,即在这过程中伴随着Document、View 和 Frame 的创建。· Run(): 初始化后,WinMain 就会调用这个成员函数去处理 Message 循环。· ExitInstance(): 每当一个应用程序的Copy (拷贝)终止时,就会调用这个函数,即发生在应用程序退出时。· OnIdle(): 当没有 Windows Message 处理时,就会由Framework调用这个函数,并重写这个函数去执行后台任务。当用户从CWinApp派生一个Application Class 时,必须重写成员函数InitInstance() 去创建应用程序的Main Window Objecto Windows 允许同时运行同一个应用程序的多个“Copy”, 而且该应用程序的每个Instance(包括第一个的)都会被初始化,而初始化时都会用到被 Override了的 InitInstance() 函数所提供的信息。通常情况下,每个 Windows-based 应用程序都有一个 Main Window 。因此,在初始化完成后, Framework 就会检查是否存在一个指向有效 Main Windows( CWinApp:m_pMain Wnd) 的指针,如果不存在的话,应用程序就会终止。当利用 AppWizard 创建应用工程项目时,AppWizard 会重写缺省的InitInstance()来创建Main Window Object,还会使 CWinApp 的数据成员 m_pMainWnd 指向那个 Window 。2.2 文档视图机制文档对视图的管理。若用非文档,视图机制的时候,交互界面显示的只有一种视图,在这种情况下,可以将内部数据以一种对应规则用图像显示出来。将一份数据用不同的方式去展示,并且将它们放在不同的窗口视图中,MFC机制给出了这样的实现方法:先用一个 CDocument 这样的物件去处理数据的管理,然后用一个CView这样的物件去管理视图的显示,这样一来,所有不同的显示图像若要以某种方式反映出数据的特性,必须在数据源和众多不同方式的图像显示之间有一定的关联。对于它们的关联,MFC机制用了一个很好的方法,就是将所有与这个数据源相关的图像显示都独立用 CView 物件去表示,而当数据源就抽象成 CDocument 物件, 而在 Document 中有这样的一个指针列表 CPtrList 类型的日 员变量 m_viewList, 将所有这些与之关联的视图用链表串起来。而这些用于显示不同性质的图像视图类也可以通过 GetDocument()来获取其所对应的 Document 文档数据。2.3 Document文挡操作由于 MFC 机制设计出文档类对象专门负责数据的 I/O 存取和数据的运算和操作等。一般来说,数据运算是通过 Document 类里面的扩展功能来实现的,这样做可以形成一种密集数据处理,达到方便易用和管理的好处。对于一个文件而言,如果文件内对象的排列顺序是固定的,那么对于文件读和写从形式上只有使用的运算符的不同。在 MFC 的文档-视图-框架结构中,一个文档的内部对象的构成往往是固定的,在这种情况下,写到文件中的对象在文件中的布局也是固定的。因此 CDocument 是利用其基类 CObject 提供的 Serilize()虚函数实现自动文档的读写操作的。 当用户在界面上选择文件菜单或打开文件 (ID_FILE_OPEN)时,CWinApp派生类的 OnFileOpenO 函数将被自动调用,它通过文档模板创建或重用框架、文档和视图对象,并最 终调用 CDocument: :OnOpenDocument()来读文件。 当用户选择菜单文件或文件保存(ID_FILE_SAVE) ,选择文件或另存(ID_FILE_SAVEAS) 时,是通过呼叫函数 CWinApp: :OnFileSave() 和CWinApp: :OnFileSaveAs()并最终调用 CDocument: :OnSaveDocument() 实现的。2.4 文档-视图的关联视图与文档和窗口的关联和协调工作可以从视图类对象的 OnDraw() 函数开始,找出关联的物件与关系。在 MFC 机制中,关于 DocumentNiew 架构的项目工程和 OnDrawO 函数的驱动绘图触发的流程 :CDocument:UpdateAIIViews()->CView:OnUpdate()-> CWnd: :Invalidate()->OnPaint()->OnDraw()从流程可知当用于装载重要数据的 Document 类对象中的数据发生变化时,为了能让与其关联的各个视图实时表现出数据的特征性质,需要通知所有这些关联的视图进行更新重绘 , 而Document类对象就拥有通知所有视图重绘的这样的一个功能函数。对于UpdateAIIViews() 函数实现对各个视图类对象对数据显示的更新是通过文档类内部CPtrlist类型的成员变量 m_viewList来维护和管理所有相关联的视图对象 , 如图 1.1所示。 Documentm_viewListView_1pView_1View_2pView_2View_3pView_3View_4pView_4 图1.1 变量m_viewList视图对象而对于该文档关联视图的增添,与将 DocumentTemplte 文档模板添加到模板类表一样, 也是有相应的处理函数,对于文档模板在模板管理列表的添加是在App类的 Initlnstance()里面使用 AddDocTemplate() 函数去实现,而对于视图在视图列表的添加, 可以使用 Document 类对象的成员函数 AddView() 去实现。当与文档类关联的视图类收到文档类通过 UpdateAIIViews() 函数发出的更新重绘通知后 , 会触发视图类的 OnUpdate() 函数的实现。3 俄罗斯游戏分析和总体设计3.1 俄罗斯方块游戏功能描述对于俄罗斯方块游戏,其功能描述如下:·游戏开始,游戏区域上方不断地出现预定义形状的下坠物件。·下坠物件可以通过旋转改变其显示形态,并且不断地往下坠, 直到它接触到游戏区域底部或其他之前已经累叠起的下坠物件。当一个下坠物件到达底部后,其位置则确定下来并占有该空间的位置区域。·当游戏区域的某一行被下坠物件完全填充,则消除该行的所有下坠物,垒在其上的物件将掉下代替该行空间。·游戏的结束是以下坠物件的顶部到达游戏区域顶部作为判断依据,表示装满溢出。并且在某一瞬间,下一个下坠物件的形态在游戏区域的右上方有预先提示,同时每抵消一行空间积分自增 100。3.2 游戏规则分析首先,在游戏开始后检查当前的下坠物是否已经到了底部,如果不是的话就将下坠物到了该定时器间隔的时间后整体往下移动一个单位,否则,进行到达底部后的操作。对于到达底部后的操作,可以分成以下几个步骤来处理。(1)先对进行到底部后的所有可以抵消的行进行销行处理。(2)生成一个新的“下一个下坠物”,这个下坠物的形态需要随机地生成。(3)在将旧的“下一个下坠物”置换成新的下一个下坠物,并在屏幕右上方显示。(4)将当前的“下坠物”换成以前产生的旧的“下一个下坠物”,并且马上使用。由于在这个过程中已经重新使用了一个新的下坠物件,在刚使用时并且还没有下降前,应该判断它是否已经不可以下降到底部(也就是说,在方块己经堆砌到接近游戏区域顶部的时候,下坠物件一旦被使用,就已经到达了底部),如果是刚好到达底部则实行销行检测和操作, 并且判断顶部(第一行)的某些区域是否已经被占用了,是则表示游戏已经触发结束的标志时间,应该进入游戏结束状态。(5)在前面判断为到达底部后,进行销行检测与操作。(6)在下坠物到达底部的同时,判断是否已经到达了游戏的顶部,是则表示游戏结束,进行游戏结束的资源释放与数据环境清理工作整个流程如图1.2所示。开始到达低部1.销行操作2.生成新的“下一个下坠物”3.将新生的下坠物代替旧的“下一个下坠物”4.将旧的“下一个下坠物”用作当前下坠物5.销行操作6.游戏结束处理到达顶部,游戏结束结束到达低部7.下降一个单位 图 1.2 流程图4 俄罗斯方块游戏的实现俄罗斯方块游戏设计的实现,主要包括游戏核心数据的抽象与设计、操作方法的抽象与设计、及流程的设计与实现等。下面将对这几个部分作具体的设计。4.1游戏核心数据的抽象与设计在抽象出方法和属性前,先来分析一下整个游戏的具体实现。首先 , 游戏有开始、暂停、结束等操作接口,而在游戏过程中,随着用户的按键交互,会出现方块的形态变化、方块快速下坠、安放该下坠物件、销毁填满的行、产生下一将要出现的方块等功能。这里,先分析游戏的特点,把整个游戏的核心数据结构提取出来,再根据数据结构的特点提取出核心功能模块的关联,然后对这些功能一一进行细化,从而完成整个游戏的设计。下面就来分析整个游戏的整体状况,如图1.3所示。 图1.3 游戏内部方块从如图 1.3 所示可以看到,游戏区域可以看作是由许多个等面积的小方块构成的大面积区域。而这些区域的状态只有2种,被下坠物占据和空闲(没有被下坠物占据),因此,对于整个游戏区域的数据,用一块空间来标识即可。其状态只有两种:被占据1和空闲0。这块空间的分配,可以采用动态分配的方式或者静态分配的方式去实现,至于数据结构的选择,可以是链表、队列或者数组等,我这里选择静态分配并划分一个足够大的二维数组的方式来实现,如下所示。/in file:skyblue_RectView.h#define MAX_ROW 100 /地图的最大行数#define MAX_COL 100 /地图的最大列数/in file:skyblue_RectView.h class:Cskyblue_RectView/内部存取数据结构int m_stateMapMAX_ROWMAX_COL从上述代码可以看到,在视图类对象里面分配了一个存储游戏区域地图状态的二维数组ID_stateMap成员变量,并定义其最大行数和列数都为100(当然,实际可能并不需要那么大,只是先分配好足够的地图空间以供使用而已)。同时,还应该预先定义该区域的两种状态值:#define MAP_state_empty 0 /空(未被占据)#define MAP_state_not_empty 1 /被占据整个游戏区域的地图设计好后,再来看看具体的下坠物,通过分析它们的特性,还可以抽象出一些物件来。在每个下坠物在下坠的过程中,总是占有地图中的某一块区域,那么怎样表达这些下坠物的形态和它们占有的位置关系呢?在此,先来看看它们的基本类型,然后进行归纳分析,其基本类型如图1.4所示。 图1.4 方块基本类型从图1.4可以看到,这些下坠物的形状一共有7种,对于这些形态各异的下坠物间存在一个最基本的共性,就是它们占有的位置空间是一样的,都是4个小方块区域。对于它们在某一瞬间的位置标识,我们可以采用一个 4x2 的小数组标识出来,如图1.5所示。 图1.5 方块位置标识 也就是说,用4个存储单位空间存储当前下坠物的每一子块的位置来对整 个下坠物件的位置进行标识,而每个存储空间的大小就是一个点的坐标值(x,y),于是就有如下定义。 /in file : skyblue_Rectciew.h /用于保存当前方块的动态位置,4个小方块分别在大数组中的存放位置为先左后右, /每一列又遵循先上后下的原则 Int ActiveStatus42; /存入下一个要出现的方块形状的数组 Int NextStatus42;在上述代码中,分配了一个整型的二维数组ActiceStatus来存储每个下坠物的 4 个子方块的坐标位置,其实在游戏过程中,变动的下坠物件除了当前用户正在操控的下坠物件外,项目程序的右上方还需要显示出下一个下坠物件的形状。也就是说,在游戏过程中的某一瞬间,除了需要记录当前用户正在控制的下坠物状态外,还需要记录预先随机生产出来的下坠物件状态,于是代码中多了一个 NextStatus数组成员变量,用以存储下坠物的形态。还有一个问题没有解决,这些形状各异的下坠物件,虽然都是由4个小方块构成,但是对于它们的编号还没有一定的规律,因此需要人为地定下一些规则,而这个规则就是:编号从下坠物的左边起往右编排,而在同一列的方块中,则从上往下的顺序开始编号它们的对应关系如图1.6所示。01232031图1.6 方块类型对应位置标识如图 1.6所示的两个不同的下坠物,每个方块按照从左到右的方式进行编号,并且在编号过程中对于同一列的方块实行从上到下进行编号,而该方块所在游戏区域的位置坐标 则 存储在下标与编号所对应的ActiceStatus二维数组的每个单位里面,如: ActiceStatus00 和ActiceStatus01则是第0号方块的横坐标X和纵坐标Y。 ActiceStatus20 和ActiceStatus21则是第2号方块的横坐标X和纵坐标Y。至此,可以实现下坠物件的位置标识了,那么对于某一下坠物的形态特性又怎么标识呢?可以使用这样的方法:用一个宏去标识 ,第1 位的数值变化范围为17,用于标识下坠物的种类(7种),第2位标识该种类下坠物的不同形态,不同的下坠物,如“田”字形的下坠物只有1种形态,所以没有第2位,其他的不同形态则从14(最多有4种形态)按顺序标识即可,如第2种下坠物的第3种形态,其宏标识为23,如图 1.7所示。下坠物编号:4状态编号: 1 2 3 4 形状宏标识 41 42 43 44图1.7 方块变形表示4.2 操作方法的抽象与设计 当完成整个游戏的基本核心数据的表达并进行抽象与设计后,接下来,就可以根据游戏的特性对核心的基本操作方法进行抽象,进而实现这些功能。下面将着重分析游戏过程中的实现细节,以便抽象出基本的操作功能。首先是游戏开始,应该有个事件触发游戏的开始,譬如菜单栏选项等,相应地,也可以 类推出游戏暂停与游戏结束等操作功能。游戏开始后,产生一个下坠物件,并且在右上角生成下坠物件的基本形态,因此有随机物件产生这个操作。在游戏过程中,方块会自动随着时间的推移而向下移动,因此有向下移动的操作。在游戏过程中,用户可以通过按键对下坠物的功能进行操作,如变形操作、加速下降操作、向左移动操作、向右移动操作等。上面说到的几点大多是从与用户交互的角度去观察分析的,而从游戏的规则方面,也可以作一下分析,当下坠物响应用户的指示向左或向右移动的时候,需要判断该不坠物件是否已经到这了游戏区域的边界而无法向左或着向右移动:当下坠物的形态改变的时候,需要计算出应该改变成何种形态: 当下坠物向下移动的时候,需要判断是否已经到达了底部等。先虚拟出该俄罗斯方块游戏的类对象,并抽象出核心的数据属性和操作方法等,然后再作细,最后将整个虚拟类的外壳脱掉,再移植到视图类中去,其实现如下所示。CRectGameView: public cview /内部存取数据结构 Int m_stateMapMAX_ROWMAX_COL; /用于保存当前方块的动态位置,4个小方块分别在大数组中的存取位置为先左后/右,每一列又遵循先上后下的原则Int Activestatus42;/存入下一个要出现的方块形状的数组Int Nextstatus42; /初始化操作GameInitnal(); /游戏的初始化/用于判断数据相关状态的操作IsLeftLimit(); /下坠物体是否可向左移动IsRightLitmit(); /下坠物体是否可向右移动IsBottom(); /是否已经到达底部IsGameEnd(); /是否游戏已经结束/方块物体下坠过程中的操作RectChange(); /下坠物体变形RectDown(); /下坠物体正常下落RectArrow(); /下坠物体方向移动(左,右,下加速)/状态控制操作GameStart(); /游戏开始GamePause(); /游戏暂停GameEnd(); /游戏结束通过上面的代码可以看出,在虚拟类中抽象出了核心的内部数据和一些基本的操作函数。对于操作函数,可以把它们分成内部实现的基本核心操(如判断操作)以及明显提供给外部使用的整体模块外部操作(如状态控制操作)。而内部的基本操作又可以分成判断操作和执行操作这样两种类型。这里将上面涉及到的操作整理成表,如表4-1所示。表4-1 操作函数及功能描述 属性和操作 功能描述外部操作状态控制操作组GameStart()游戏进入开始状态,进行相关数据的初始化以及关联操作GamePause()游戏进入暂停状态,进行数据的保持与其他关联的操作GameEnd()游戏进入结束状态,进行数据的清除以及资源的销毁和释放操作内部基本核心操作判断操作组IsLeftLimit()向左偏移前,判断该下坠物件是否已经到达了游戏区域的最左边界(不可以再左移IsRightLitmit()向右偏移前,判断该下坠物件是否已经到达了游戏区域的最右边界(不可以再右移)IsBottom()向下偏移加速或者下坠物件自动向下偏移前,判断是否已经到达了底部(这里对底部定义是游戏区域底部或下面有其他下坠物)IsGameEnd()判断下坠物是否到达了游戏区域顶部而应该结束游戏执行操作组RectChange()下坠物件的状态变形,方法为在原来的状态下逆时针旋转90度RectDown()该下坠物件的4个小方块所有坐标位置向下偏移一个单位RectArrow()直接响应用户按键,向左或者向右或者向下偏移一个单位其他操作Gamelnitnal()游戏的初始化操作 4.3 流程的设计与实现流程的设计分正常流程设计和中断流程设计。下面对这两部分做具体的设计和实现。4.3.1 正常流程的设计对于正常流程的实现是由定时器驱动的,也就是说,当预定的时间间隔到达后就执行这样的一个工作流程,所以必须先设置一个定时器机制,下面来对增加一个定时器进行实现。从分析游戏的特性可以知道,定时器的产生与生效应该在游戏开始的时候,而在游戏暂 停或者游戏结束时则将已经设定的定时器失效/销亡(对于暂停的情况,使它销亡,当游戏从 暂停状态又进入游戏状态的时候,则重新创建一个定时器并激活它的运作),所以分别在游戏的开始函数、暂停函数以及结束函数中实现定时器的激活与去激活工作。这里,先在资源编辑器菜单资源里面添加3 个菜单选项,分别是游戏的“开始”、“暂停”和“结束”(由于这 3个功能是外部给用户操作的功能,所以可以预先在菜单栏中添加相应的功能选项,然后在视图类中实现它们即可,当它们找到直接关联的物件后对虚拟类的功能操作预先脱壳), 然后利用ClassWizard直接在视图类对象 Cskyblue_RectView 中为它们添加空白的处理函数 , 具体如表4-2所示。表4-2 菜单选项功能对应表菜单选项名称快捷键资源ID晌应处理函数开始游戏&S.ID GAME_STARTOnGameStart()暂停游戏&P.ID GAME_PAUSHOnGamePaush()结束游戏&E.ID GAME_ENDOnGameEnd()现在,就可以在上面的3个空白的函数中添加定时器了,其具体实现如下所示。/in file:skyblue_Rectview.cpp/游戏开始void Cskyblue_Rectview:ongamestart() m_bGamepaush=FALSE;SetTimer(1、1500-250*m_iLevel、Nulll);/游戏暂停void Cskyblue_RectView:onGamePaush() m_bGamepaush=TRUE; killTimer(1);/游戏结束void Cskyblue_RectView:onGameEnd() m_bGameEnd=TRUE; m_bGamepaush= FALSE; /清除游戏暂停状态 killTimer(1);从上面的3个函数代码中可以看到,在添加这3个函数时,视图类还添加了涉及到游戏状态的3个成员变量,它们分别是用作判定当前游戏等级的m_iLevel、记录游戏状态的m_bGamePaush(是否暂停)和m_bGameEnd(是否结束游戏),