版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、摘摘 要要 俄罗斯方块是非常传统的游戏,操作简单,难度却不低,广受娱乐界欢迎。给人们 的生活带来了健康愉快的补充,唯美的艺术享受。 本文在基于 visual c+实现的单机版俄罗斯方块游戏的基础上,深入的研究 mfc 框 架中的各个类的关系和它们内部之间的联系。 主要工作和结论: 1. 分析了俄罗斯游戏规则。 2.系统的介绍了实现俄罗斯方块游戏的算法设计过程。 3. 将研究的思路运用于实际,在 vc+6.0 平台下实现了俄罗斯方块游戏。 关键词关键词 :俄罗斯方块游戏;vc+;mfc 框架 abstract russia is a very traditional box of the gam
2、e, simple operation, the difficulty is not low, widely welcomed by the entertainment industry. to the peoples 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
3、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
4、, in vc + +6.0 platform under the russian box game. key words : russian box game; vc + +; mfc framework 目目 录录 摘摘 要要.i abstract.i 1 引言引言 .3 1.1 选题及研究意义选题及研究意义 .3 1.2 论文研究的主要内容论文研究的主要内容 .3 2.1 appapp 应用程序类物件应用程序类物件 .4 2.2 文档文档视图机制视图机制 .5 2.3 documentdocument 文挡操作文挡操作 .6 2.4 文档文档- -视图的关联视图的关联 .6 3 俄罗斯游
5、戏分析和总体设计俄罗斯游戏分析和总体设计 .7 3.1 俄罗斯方块俄罗斯方块游戏游戏功能描述功能描述 .8 3.2 游戏游戏规则规则分析分析 .8 4 俄罗斯方块游戏的实现俄罗斯方块游戏的实现 .9 4.1 游戏游戏核心数据的抽象与设计核心数据的抽象与设计 .10 4.2 操作方法的抽象与设计操作方法的抽象与设计 .13 4.3 流程的设计流程的设计与实现与实现 .15 4.3.1 正常流程的设计正常流程的设计 .15 4.3.2 正常流程的实现正常流程的实现( (定时处理定时处理) ) .16 4.3.3 中断操作流程的设计中断操作流程的设计 .19 4.3.3 中断操作流程的实现中断操作流
6、程的实现 .20 4.4 游戏区域绘图的实现游戏区域绘图的实现 .21 4.4.1 位图资源的准备位图资源的准备 .21 4.4.2 绘图机制设计绘图机制设计 .22 4.4.3 绘图环境资源的初始化和释放绘图环境资源的初始化和释放 .22 4.4.4 游戏区域的绘制游戏区域的绘制 .24 5. .功能的完善功能的完善 .27 5.1 游戏背景音乐的实现游戏背景音乐的实现 .29 5.2 工具栏快捷键的实现工具栏快捷键的实现 .30 结束语结束语 .33 参考文献参考文献 .33 致致 谢谢 .34 俄罗斯方块游戏的实现 1 引言 我们国家正处于全球文化产业日新月异大格局中,电子游戏、网络游戏
7、的发展速度 之快,更是令人眼花缭乱,目不暇接。未来的电子和游戏发展趋势必将是更智能化、更 艺术性、更人性味。在高性能的硬件设备的支持下,游戏的驱动引擎更具威力,控制功 能更加完备,在一个错综复杂的极度扩张的游戏大世界中,带着超乎常人智慧的人工智 能的应对力,使得所有要素包括艺术的风格、情感的互动、故事的铺展、视觉的表现、 用户的界面,融合为有机的一体,给人们带来更丰富的娱乐和体验。好的游戏给人们的 生活带来了健康愉快的补充,唯美的艺术享受,潜默的教育功效。 本系统采用vc+为主要开发工具设计实现了一个单机板的俄罗斯方块游戏。与其他 程序相比,笔者的作品有三个特色:一是精心设计的人机界面,不仅友
8、好而且易于操作。 二是笔者的游戏采用的是单机板。三是采用mfc应用程序开发模型进行编制,使开发人 员减轻创建windows应用程序的负担。网络版的俄罗斯方块游戏是两个玩家通过网络进行 较量,但在游戏过程中数据要通过服务器进行传送,网络版游戏经常会出现断线、超时 等情况这些都是因为网络的速度比较慢造成的。而笔者设计的俄罗斯游戏虽然是单机版 的,但速度快,提高了效率。 1.1 选题及研究意义选题及研究意义 俄罗斯方块游戏是一个比较经典的游戏,根据软件工程有关的规范,以合理的开发 原则,设计出单机的俄罗斯方块游戏,并给人们的生活带来唯美的艺术享受和健康愉快 的补充。 游戏软件是一种与文化背景密切联系
9、的产品,具有很强的民族性和丰富的文化内涵。 伴随着游戏软件在市场上的销售,与其相关的文化也随之传播。因此发展我国自主的益 智、健康的游戏软件已是当务之急。游戏是一种基于计算机的应用软件,是新型的休闲 娱乐方式。当前开发的游戏软件应该做到知识性、娱乐性、趣味性、教育性相统一。 1.2 论文研究的主要内容论文研究的主要内容 在论文完成过程中,认真学习了游戏开发的基本技术,ood 方法软件设计的基础知识, vc+程序设计语言等。结合游戏开发的过程、算法的设计与分析(如下坠物的生成、下 坠物随机选择、游戏区画板实现的方法等)、软件工程等角度重点研究了实现游戏的算 法和采用 vc+平台设计游戏的优点和现
10、存结构的不足之处。 以下是论文的组织结构: 第 1 部分是引言,主要介绍论文选题的意义、选题背景等相关情况。 第 2 部分概述 mfc 应用程序框架。 第 3 部分是游戏规则的分析。 第 4 部分是游戏算法的实现、游戏功能模块、操作界面以及系统分析及设计。 第 5 部分是对整个论文的结束语。对论文的主要工作作了归纳总结,分析了进一步 需要做的工作。 2 mfcmfc 应用程序架构应用程序架构 传统的 windows 应用程序的开发使用 api(application programming interface)函 数。api 函数的功能主要是为 windows 应用程序开发提供统一的编程接口。
11、在使用 api 编 程的过程中,窗口的创建和消息的处理都需要手工编码。一个简单的 windows 应用程序 的代码需要上百行,这使 windows 应用程序开发变成了一件繁重的工作。现在编程,都 是在 visual c+ 环境下采用基本 mfc(microsoft foundation class)的 windows 编程方 法。 microsoft 基本类库 mfc 是一个 windows 应用程序框架,它是 c+类结构的扩展。利 用 mfc 提供的面向对象程序行色机的框架,可大大减轻程序开发人员创建 windows 应用 程序的负担。mfc 提供了管理窗口、菜单、对话诓的代码,可实现基本的
12、输入输出和数 据的存储。 此外,mfc 还提供一个应用程序来发模型,此模型被称为文档视图模型。文档视图 模型视将应用程序数据与用户界面元素分离的一种应用编程方法,它允许这两部分程序 独立存在。这样,程序员在更改其中部分代码的时候,不会大幅度地更改另一部分。 该游戏的实现采用 mfc 框架。在构架类视图中有 mfc 基本架构组合 : app(应用程 序)类、document(文档)类、view(视图)类、frame(框架)类和用于提示关于作者的对话 框 caboutdlg 类。下面对这几个类做一个简单的列表,如表 2.1 所示。 表 2.1 mfc 应用程序架构表 类别基类 描述 applica
13、tioncwinapp代表应用程序的核心 documentcdocument包含应用程序的数据集 windows cwind主要用于图形用户界面(gui)的对象,可以处理常见的 windows 消息 framecframewnd用于应用程序的主要 windows 框架 viewvciew用于显示数据并与文档 document 对象交互 2.1 appapp 应用程序类物件应用程序类物件 每种语言都有一个程序入口(主函数),如 c/c+语言的 main()函数。总地来说, main()函数的调用与终止代表着程序执行的开始与结束,在程序运行的过程中,无非是对 一些业务性的功能流程进行不断的处理,当
14、完成后才退出程序。其实,所有的程序也是采 用同样的方法去实现, mfc 机制巧妙地利用了 application 类去封装实现了这样的效果 功能,每个 cwinapp 类对象实体都代表应用程序本身,它是基本的 application class(应 用程序类),其封装了 windows-based 应用程序的初始化、运行、 message 映射和终止 等功能。假如创建了这样的一个对象实体,在运行期间处理初始化、消息映射、或者其他 动作时就可以通过属性操作的调用去实现,而不像拥有结构化设计思想的 maino 函数那 样的顺序去实现。那么,现在就来看看这个 cwinapp 类对象的性质。 在 mf
15、c 框架中,应用程序必须有且仅有一个从 cwinapp 派生的 class object(类物 件),这个 object 在 windows 创建之前就会被创建,也就是说这个 object 会和其他 c+ 全局 object 同时创建。当 windows 调用 winmaino 时(在 mfc 应用程序中,不必亲自调 用 winmaino,因为机制已经对它封装好,当应用程序启动时会由框架自动调用),这个 object 已经可用了,并且该 object 是全局的。 当用 appwizard 创建 documentniew 模式应用程序时,appwizard 会声明一个从 cwinapp 派生的
16、application class, 因此,由 appwizard 所产生的.cpp 文件中还包括 message 映射、空的构造函数、一个应用程序 object(即一个变量)和 initinstanceo 函 数。appwizard 提供的源代码和 message 映射可以满足一些基本的任务,但在通常情况下,还是需要手工 修改那些源程序,特别是要修改 initinstance()函数。 在 cwinapp 中,有以下几个关键的可重写的成员数。 initinstance(): 此函数对文档模板(document template)进行创建和初始化,即在 这过程中伴随着 document、vie
17、w 和 frame 的创建。 run(): 初始化后,winmain 就会调用这个成员函数去处理 message 循环。 exitinstance(): 每当一个应用程序的 copy (拷贝)终止时,就会调用这个函数, 即发生在应用程序退出时。 onidle(): 当没有 windows message 处理时,就会由 framework 调用这个函数,并 重写这个函数去执行后台任务。 当用户从 cwinapp 派生一个 application class 时,必须重写成员函数 initinstance() 去创建应用程序的 main window objecto windows 允许同时运行
18、同一个 应用程序的多个“copy”, 而且该应用程序的每个 instance(包括第一个的)都会被初始 化,而初始化时都会用到被 override 了的 initinstance() 函数所提供的信息。 通常情况下,每个 windows-based 应用程序都有一个 main window 。因此,在初始化 完成后, framework 就会检查是否存在一个指向有效 main windows( cwinapp:m_pmain wnd) 的指针,如果不存在的话,应用程序就会终止。 当利用 appwizard 创建应用工程项目时,appwizard 会重写缺省的 initinstance() 来创
19、建 main window object,还会使 cwinapp 的数据成员 m_pmainwnd 指向那个 window 。 2.2 文档文档视图机制视图机制 文档对视图的管理。若用非文档,视图机制的时候,交互界面显示的只有一种视图,在 这种情况下,可以将内部数据以一种对应规则用图像显示出来。将一份数据用不同的方式 去展示,并且将它们放在不同的窗口视图中,mfc 机制给出了这样的实现方法:先用一个 cdocument 这样的物件去处理数据的管理,然后用一个 cview 这样的物件去管理视图的显 示,这样一来,所有不同的显示图像若要以某种方式反映出数据的特性,必须在数据源和众 多不同方式的图像
20、显示之间有一定的关联。对于它们的关联,mfc 机制用了一个很好的方 法,就是将所有与这个数据源相关的图像显示都独立用 cview 物件去表示,而当数据源就 抽象成 cdocument 物件, 而在 document 中有这样的一个指针列表 cptrlist 类型的日 员变量 m_viewlist, 将所有这些与之关联的视图用链表串起来。而这些用于显示不同性 质的图像视图类也可以通过 getdocument()来获取其所对应的 document 文档数据。 2.3 documentdocument 文挡操作文挡操作 由于 mfc 机制设计出文档类对象专门负责数据的 i/o 存取和数据的运算和操作
21、等。 一般来说,数据运算是通过 document 类里面的扩展功能来实现的,这样做可以形成一种 密集数据处理,达到方便易用和管理的好处。 对于一个文件而言,如果文件内对象的排列顺序是固定的,那么对于文件读和写从形 式上只有使用的运算符的不同。在 mfc 的文档-视图-框架结构中,一个文档的内部对象 的构成往往是固定的,在这种情况下,写到文件中的对象在文件中的布局也是固定的。因 此 cdocument 是利用其基类 cobject 提供的 serilize()虚函数实现自动文档的读写操 作的。 当用户在界面上选择文件菜单或打开文件 (id_file_open)时,cwinapp 派生类的 onf
22、ileopeno 函数将被自动调用,它通过文档模板创建或重用框架、文档和视图对象,并最 终调用 cdocument: :onopendocument()来读文件。 当用户选择菜单文件或文件保存(id_file_save) ,选择文件或另存(id_file_saveas) 时,是通过呼叫函数 cwinapp: :onfilesave() 和 cwinapp: :onfilesaveas()并最终调用 cdocument: :onsavedocument() 实现的。 2.4 文档文档- -视图的关联视图的关联 视图与文档和窗口的关联和协调工作可以从视图类对象的 ondraw() 函数开始,找出
23、关联的物件与关系。在 mfc 机制中,关于 documentniew 架构的项目工程和 ondrawo 函 数的驱动绘图触发的流程 : cdocument:updateaiiviews()-cview:onupdate()- cwnd: :invalidate()- onpaint()-ondraw() 从流程可知当用于装载重要数据的 document 类对象中的数据发生变化时,为了能让 与其关联的各个视图实时表现出数据的特征性质,需要通知所有这些关联的视图进行更新 重绘 , 而 document 类对象就拥有通知所有视图重绘的这样的一个功能函数。对于 updateaiiviews() 函数实
24、现对各个视图类对象对数据显示的更新是通过文档类内部 cptrlist 类型的成员变量 m_viewlist 来维护和管理所有相关联的视图对象 , 如图 1.1 所示。 document 图 1.1 变量 m_viewlist 视图对象 而对于该文档关联视图的增添,与将 documenttemplte 文档模板添加到模板类表一 样, 也是有相应的处理函数,对于文档模板在模板管理列表的添加是在 app 类的 initlnstance()里面使用 adddoctemplate() 函数去实现,而对于视图在视图列表的添加, 可以使用 document 类对象的成员函数 addview() 去实现。 当
25、与文档类关联的视图类收到文档类通过 updateaiiviews() 函数发出的更新重绘通知 后 , 会触发视图类的 onupdate() 函数的实现。 m_viewlist pview_1 pview_2 pview_3 pview_4view_4 view_3 view_2 view_1 3 俄罗斯游戏分析和总体设计俄罗斯游戏分析和总体设计 3.1 俄罗斯方块俄罗斯方块游戏游戏功能描述功能描述 对于俄罗斯方块游戏,其功能描述如下: 游戏开始,游戏区域上方不断地出现预定义形状的下坠物件。 下坠物件可以通过旋转改变其显示形态,并且不断地往下坠, 直到它接触到游戏区 域底部或其他之前已经累叠起的
26、下坠物件。当一个下坠物件到达底部后,其位置则确定下 来并占有该空间的位置区域。 当游戏区域的某一行被下坠物件完全填充,则消除该行的所有下坠物,垒在其上的 物件将掉下代替该行空间。 游戏的结束是以下坠物件的顶部到达游戏区域顶部作为判断依据,表示装满溢出。 并且在某一瞬间,下一个下坠物件的形态在游戏区域的右上方有预先提示,同时每抵消一 行空间积分自增 100。 3.2 游戏游戏规则规则分析分析 首先,在游戏开始后检查当前的下坠物是否已经到了底部,如果不是的话就将下坠物 到了该定时器间隔的时间后整体往下移动一个单位,否则,进行到达底部后的操作。对于到 达底部后的操作,可以分成以下几个步骤来处理。 (
27、1)先对进行到底部后的所有可以抵消的行进行销行处理。 (2)生成一个新的“下一个下坠物”,这个下坠物的形态需要随机地生成。 (3)在将旧的“下一个下坠物”置换成新的下一个下坠物,并在屏幕右上方显示。 (4)将当前的“下坠物”换成以前产生的旧的“下一个下坠物”,并且马上使用。由于 在这个过程中已经重新使用了一个新的下坠物件,在刚使用时并且还没有下降前,应该判断 它是否已经不可以下降到底部(也就是说,在方块己经堆砌到接近游戏区域顶部的时候,下 坠物件一旦被使用,就已经到达了底部),如果是刚好到达底部则实行销行检测和操作, 并 且判断顶部(第一行)的某些区域是否已经被占用了,是则表示游戏已经触发结束
28、的标志时 间,应该进入游戏结束状态。 (5)在前面判断为到达底部后,进行销行检测与操作。 (6)在下坠物到达底部的同时,判断是否已经到达了游戏的顶部,是则表示游戏结束,进 行游戏结束的资源释放与数据环境清理工作 整个流程如图 1.2 所示。 开始 到达低部 1.销行操作 2.生成新的“下一个下坠物” 3.将新生的下坠物代替旧的 “下一个下坠物” 4.将旧的“下一个下坠物” 用作当前下坠物 5.销行操作 6.游戏结束处理 到达顶部, 游戏结束 结束 到达低部 7.下降一个单位 图 1.2 流程图 4 俄罗斯方块游戏的实现俄罗斯方块游戏的实现 俄罗斯方块游戏设计的实现,主要包括游戏核心数据的抽象与
29、设计、操作方法的抽象 与设计、及流程的设计与实现等。下面将对这几个部分作具体的设计。 4.1 游戏游戏核心数据的抽象与设计核心数据的抽象与设计 在抽象出方法和属性前,先来分析一下整个游戏的具体实现。首先 , 游戏有开始、 暂停、结束等操作接口,而在游戏过程中,随着用户的按键交互,会出现方块的形态变化、 方块快速下坠、安放该下坠物件、销毁填满的行、产生下一将要出现的方块等功能。这 里,先分析游戏的特点,把整个游戏的核心数据结构提取出来,再根据数据结构的特点提取 出核心功能模块的关联,然后对这些功能一一进行细化,从而完成整个游戏的设计。 下面就来分析整个游戏的整体状况,如图 1.3 所示。 图 1
30、.3 游戏内部方块 从如图 1.3 所示可以看到,游戏区域可以看作是由许多个等面积的小方块构成的大 面积区域。而这些区域的状态只有 2 种,被下坠物占据和空闲(没有被下坠物占据),因此, 对于整个游戏区域的数据,用一块空间来标识即可。其状态只有两种:被占据 1 和空闲 0。 这块空间的分配,可以采用动态分配的方式或者静态分配的方式去实现,至于数据结构的 选择,可以是链表、队列或者数组等,我这里选择静态分配并划分一个足够大的二维数组 的方式来实现,如下所示。 /in file:skyblue_rectview.h #define max_row 100 /地图的最大行数 #define max_
31、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_e
32、mpty 1 /被占据 整个游戏区域的地图设计好后,再来看看具体的下坠物,通过分析它们的特性,还可以 抽象出一些物件来。在每个下坠物在下坠的过程中,总是占有地图中的某一块区域,那么 怎样表达这些下坠物的形态和它们占有的位置关系呢?在此,先来看看它们的基本类型,然 后进行归纳分析,其基本类型如图 1.4 所示。 图 1.4 方块基本类型 从图 1.4 可以看到,这些下坠物的形状一共有 7 种,对于这些形态各异的下坠物间存 在一个最基本的共性,就是它们占有的位置空间是一样的,都是 4 个小方块区域。对于它 们在某一瞬间的位置标识,我们可以采用一个 4x2 的小数组标识出来,如图 1.5 所示。 图
33、 1.5 方块位置标识 也就是说,用 4 个存储单位空间存储当前下坠物的每一子块的位置来对整 个下坠物 件的位置进行标识,而每个存储空间的大小就是一个点的坐标值(x,y),于是就有如下定义。 /in file : skyblue_rectciew.h /用于保存当前方块的动态位置,4 个小方块分别在大数组中的存放位置为先左后右, /每一列又遵循先上后下的原则 int activestatus42; /存入下一个要出现的方块形状的数组 int nextstatus42; 在上述代码中,分配了一个整型的二维数组 acticestatus来存储每个下坠物的 4 个子方块的坐标位置,其实在游戏过程中,
34、变动的下坠物件除了当前用户正在操控的下坠 物件外,项目程序的右上方还需要显示出下一个下坠物件的形状。也就是说,在游戏过程 中的某一瞬间,除了需要记录当前用户正在控制的下坠物状态外,还需要记录预先随机生 产出来的下坠物件状态,于是代码中多了一个 nextstatus数组成员变量,用以存储下 坠物的形态。还有一个问题没有解决,这些形状各异的下坠物件,虽然都是由 4 个小方块 构成,但是对于它们的编号还没有一定的规律,因此需要人为地定下一些规则,而 这个规则就是:编号从下坠物的左边起往右编排,而在同一列的方块中,则从上 往下的顺序开始编号它们的对应关系如图 1.6 所示。 图 1.6 方块类型对应位
35、置标识 如图 1.6 所示的两个不同的下坠物,每个方块按照从左到右的方式进行编号,并且在 编号过程中对于同一列的方块实行从上到下进行编号,而该方块所在游戏区域的位置坐标 则 存储在下标与编号所对应的 acticestatus二维数组的每个单位里面,如: acticestatus00 和 acticestatus01则是第 0 号方块的横坐标 x 和纵坐标 y。 acticestatus20 和 acticestatus21则是第 2 号方块的横坐标 x 和纵坐标 y。 至此,可以实现下坠物件的位置标识了,那么对于某一下坠物的形态特性又怎么标识 呢?可以使用这样的方法:用一个宏去标识 ,第 1
36、位的数值变化范围为 17,用于标识下 坠物的种类(7 种),第 2 位标识该种类下坠物的不同形态,不同的下坠物,如“田”字形的 下坠物只有 1 种形态,所以没有第 2 位,其他的不同形态则从 14(最多有 4 种形态)按顺 序标识即可,如第 2 种下坠物的第 3 种形态,其宏标识为 23,如图 1.7 所示。 01 2 3 2 03 1 下坠物编号:4 状态编号: 1 2 3 4 形状宏标识 41 42 43 44 图 1.7 方块变形表示 4.2 操作方法的抽象与设计操作方法的抽象与设计 当完成整个游戏的基本核心数据的表达并进行抽象与设计后,接下来,就可以根据游 戏的特性对核心的基本操作方法
37、进行抽象,进而实现这些功能。下面将着重分析游戏过 程中的实现细节,以便抽象出基本的操作功能。 首先是游戏开始,应该有个事件触发游戏的开始,譬如菜单栏选项等,相应地,也可以 类推出游戏暂停与游戏结束等操作功能。 游戏开始后,产生一个下坠物件,并且在右上角生成下坠物件的基本形态,因此有随 机物件产生这个操作。在游戏过程中,方块会自动随着时间的推移而向下移动,因此有向 下移动的操作。在游戏过程中,用户可以通过按键对下坠物的功能进行操作,如变形操作、 加速下降操作、向左移动操作、向右移动操作等。上面说到的几点大多是从与用户交互 的角度去观察分析的,而从游戏的规则方面,也可以作一下分析,当下坠物响应用户
38、的指 示向左或向右移动的时候,需要判断该不坠物件是否已经到这了游戏区域的边界而无法 向左或着向右移动:当下坠物的形态改变的时候,需要计算出应该改变成何种形态: 当下 坠物向下移动的时候,需要判断是否已经到达了底部等。 先虚拟出该俄罗斯方块游戏的类对象,并抽象出核心的数据属性和操作方法等,然后 再作细,最后将整个虚拟类的外壳脱掉,再移植到视图类中去,其实现如下所示。 crectgameview: public cview /内部存取数据结构 int m_statemapmax_rowmax_col; /用于保存当前方块的动态位置,4 个小方块分别在大数组中的存取位置为先 左后 /右,每一列又遵循
39、先上后下的原则 int activestatus42; /存入下一个要出现的方块形状的数组 int nextstatus42; /初始化操作 gameinitnal(); /游戏的初始化 /用于判断数据相关状态的操作 isleftlimit(); /下坠物体是否可向左移动 isrightlitmit(); /下坠物体是否可向右移动 isbottom(); /是否已经到达底部 isgameend(); /是否游戏已经结束 /方块物体下坠过程中的操作 rectchange(); /下坠物体变形 rectdown(); /下坠物体正常下落 rectarrow(); /下坠物体方向移动(左,右,下加速
40、) /状态控制操作 gamestart(); /游戏开始 gamepause(); /游戏暂停 gameend(); /游戏结束 通过上面的代码可以看出,在虚拟类中抽象出了核心的内部数据和一些基本的操作函 数。对于操作函数,可以把它们分成内部实现的基本核心操(如判断操作)以及明显提供给 外部使用的整体模块外部操作(如状态控制操作)。而内部的基本操作又可以分成判断操 作和执行操作这样两种类型。这里将上面涉及到的操作整理成表,如表 4-1 所示。 表 4-1 操作函数及功能描述 属性和操作 功能描述 外部操作外部操作 状态控制操作组 gamestart()游戏进入开始状态,进行相关数据的初始化以及
41、关联操作 gamepause()游戏进入暂停状态,进行数据的保持与其他关联的操作 gameend()游戏进入结束状态,进行数据的清除以及资源的销毁和释放操作 内部基本核心操作内部基本核心操作 判断操作组 isleftlimit() 向左偏移前,判断该下坠物件是否已经到达了游戏区域的最左边 界(不可以再左移 isrightlitmit() 向右偏移前,判断该下坠物件是否已经到达了游戏区域的最右边 界(不可以再右移) isbottom() 向下偏移加速或者下坠物件自动向下偏移前,判断是否已经到达 了底部(这里对底部定义是游戏区域底部或下面有其他下坠物) isgameend()判断下坠物是否到达了游
42、戏区域顶部而应该结束游戏 执行操作组 rectchange()下坠物件的状态变形,方法为在原来的状态下逆时针旋转 90 度 rectdown()该下坠物件的 4 个小方块所有坐标位置向下偏移一个单位 rectarrow() 直接响应用户按键,向左或者向右或者向下偏移一个单位 其他操作其他操作 gamelnitnal()游戏的初始化操作 4.3 流程的设计流程的设计与实现与实现 流程的设计分正常流程设计和中断流程设计。下面对这两部分做具体的 设计和实现。 4.3.1 正常流程的设计正常流程的设计 对于正常流程的实现是由定时器驱动的,也就是说,当预定的时间间隔到达后就执行 这样的一个工作流程,所以
43、必须先设置一个定时器机制,下面来对增加一个定时器进行实 现。 从分析游戏的特性可以知道,定时器的产生与生效应该在游戏开始的时候,而在游戏 暂 停或者游戏结束时则将已经设定的定时器失效/销亡(对于暂停的情况,使它销亡,当游 戏从 暂停状态又进入游戏状态的时候,则重新创建一个定时器并激活它的运作),所以分 别在游戏的开始函数、暂停函数以及结束函数中实现定时器的激活与去激活工作。这里, 先在资源编辑器菜单资源里面添加 3 个菜单选项,分别是游戏的“开始”、“暂停”和 “结束”(由于这 3 个功能是外部给用户操作的功能,所以可以预先在菜单栏中添加相应 的功能选项,然后在视图类中实现它们即可,当它们找到
44、直接关联的物件后对虚拟类的功 能操作预先脱壳), 然后利用 classwizard 直接在视图类对象 cskyblue_rectview 中为 它们添加空白的处理函数 , 具体如表 4-2 所示。 表 4-2 菜单选项功能对应表 菜单选项名称快捷键资源 id晌应处理函数 开始游戏 settimer(1、1500-250*m_ilevel、nulll); /游戏暂停 void cskyblue_rectview:ongamepaush() m_bgamepaush=true; killtimer(1); /游戏结束 void cskyblue_rectview:ongameend() m_bga
45、meend=true; m_bgamepaush= false; /清除游戏暂停状态 killtimer(1); 从上面的 3 个函数代码中可以看到,在添加这 3 个函数时,视图类还添加了涉及到游 戏状态的 3 个成员变量,它们分别是用作判定当前游戏等级的 m_ilevel、记录游戏状态的 m_bgamepaush(是否暂停)和 m_bgameend(是否结束游戏),它们在视图类中的定义如下所示。 /in file:skyblue_rectview.h class: csskyblue_rectview /当前的级别,换算成速度的算法为:1500-m_ilevel*200 int m_ilev
46、el; /游戏是否已经结束或者暂停 bool m_bgameend; bool m_bgamepaush; 其中 m_ilevel 变量是标识当前游戏的等级,随着游戏等级的升高,定时器的固定时间 间隔会逐渐变短,从而达到加快下降速度的效果。 4.3.2 正常流程的实现正常流程的实现( (定时处理定时处理) ) 经过定时器的设置后,就可以在定时器预定时间到达后对正常流程进行实现了。这里 通 过利用 classwizard 跳到定时器到时后的处理函数 ontimero 去实现,其清单如下所示。 /int file:skyblue_rectview.cpp void cskyblue_rectvie
47、w:ontimer(uint nidevent) /如果原来的方块已到底或游戏刚开始,则掉下一个新的方块 int i,j,k; if (m_isbottom) /1.产生下一个随机下坠物 m_icurrentstatus = m_inextstatus; m_inextstatus = random(7); /得到下一次的方块样式 / if (m_inextstatus=0) m_inextstatus+; /2.修改新的“下一下坠物” rectstatustonextstatus( m_inextstatus ); / crect rect(m_istarty+320, m_istartx,
48、 m_istarty+440, m_istartx+160); / invalidaterect( / invalidate(false); /3.将旧的“下一下坠物”用作当前使用 m_currentrect = m_icurrentstatus; /根据当前下坠物的形状去初始化激活状态下的下坠物坐标 rectstatustoactivestatus( m_icurrentstatus ); /将当前动态数组中的数据反映到大数组中 activestatustogamestatus(); m_isbottom = false; /4.判断当前方块是否已到底 isbottom(); /5.判断游戏
49、是否已结束: 碰了底,且第 1 行有小方块 if (m_isbottom) for (i=0;im_icol;i+) if (gamestatus0i) killtimer(1); afxmessagebox(游戏已结束!); for (j=0;jm_irow;j+) for (k=0;k selectobject(m_pblackbrush); crect rect; getclientrect( pdc - rectangle(rect); /选用灰色画刷,绘制游戏区域的背景 pdc - selectobject(m_pgraybrush); pdc - rectangle(m_istar
50、ty ,m_istartx, m_istarty + 301, m_istartx + 360); pdc-selectobject(m_pblackpen); /画网格线 if (m_bdrawgrid) /画横线 for (i=0;imoveto(m_istarty, m_istartx + i*m_ilarge); pdc-lineto(m_istarty+300, m_istartx +i*m_ilarge); /画竖线 for (i=0;imoveto(m_istarty+i*m_ilarge, m_istartx); pdc-lineto(m_istarty+i*m_ilarge,
51、 m_istartx+360); int x,y,nw,nh; /小方块的绘制 for (i=0;im_irow;i+) for (j=0;jbitblt(x,y,nw,nh, /显示游戏区域及游戏级别的汉字描述 if (!m_bgameend) pdc - setbkcolor(black); pdc - settextcolor(white); pdc - textout(m_istarty+320, m_istartx+220, 游戏区域大小:); pdc - textout(m_istarty+320, m_istartx+240,m_strarea); pdc - textout(m
52、_istarty+320, m_istartx+280, 游戏级别:); pdc - textout(m_istarty+320, m_istartx+300,m_strlevel); /显示总分 if (!m_bgameend) cstring lsstr; lsstr.format(总分为:%d 分,m_iperformance); pdc - setbkcolor(black); pdc - settextcolor(white); pdc - textout(m_istarty+320, m_istartx+180,lsstr); /画下一次将要出现的方块,用于提示用户 if (!m_
53、bgameend) pdc - setbkcolor(black); pdc - settextcolor(white); pdc - textout(m_istarty+320, m_istartx,下一个方块:); int x,y,nw,nh; for (uint k=0;kbitblt(x,y,nw,nh, 从上述代码可以看到,这里并不是先将各个部分的图像所在的位置先计算出来, 然后 在相应的位置绘制适当的图像,而是采用类似于平常的手工作画方式,首先是将整个画布 画上背景色,接着绘制游戏区域的背景色(将原来整个画布的背景覆盖掉),然后在游戏区 域中将位置为被占用状态的区域绘制成小方块图样
54、,并将原先绘制好的游戏区域背景色覆 盖掉。一般来说,使用这种方式去实现绘制, 效率比先逐个计算出每个位置区域应当显示 的图样,然后再一次性地绘制的方式要高,因为这样做不必花费太多的时 间在计算方面。 在绘制之前,分别通过黑色画刷 m_pblackbrush 以及灰色画刷 m_pgraybrush, 对窗 口区域背景以及游戏区域背景进行绘制,并且选择黑色画笔 m_pblackpen 对网格进行绘 制。对于这些画刷和画笔的使用,也要预先准备好,所以在绘图资源初始化和释放函数中, 也要添加它们的创建和释放。 至此,就完成了俄罗斯游戏的全部基本功能,效果如图 1.11 所示。 图 1.11 游戏界面
55、5. .功能的完善功能的完善 完成游戏的功能后,为了使得游戏功能更加健全,还需要对它进行一些完善,下面是附 加功能描述的列表,如表 5-1 所示。 表 5-1 附加功能描述列表 功能名称选项其他描述 游戏等级选择初级顶级对游戏快慢难度的设定 方块图案样式选择深蓝条纹对下坠物的小方块图案 样式选择 游戏区域大小选择小、中、大对游戏区域的行列数选 择 网格的选用有、无是否需要在游戏区域绘 制网格 背景音乐的选用有、无在游戏过程中是否播放 背景音乐 有了上面的目标功能定义后,这里先将这些目标功能通过资源编辑器在主菜单条进行 添加,将前面已有的菜单选项补全,再通过 class wizard 添加对应的
56、响应处理函数,其详 细信息如表 5-2 所示。 表 5-2 菜单选项功能对应表 菜单选项名 称 快捷键资源 id晌应处理函数 基本选项组( hwnd = getsafehwnd(); /分配命令字符串缓冲,错误信息储存缓冲,播放的文件名 char szcmdbuf300,errbuf60,szfilename255; /错误码 mcierror mcierror; /初始化设备元素 strcpy(szfilename,skyblue_rect.mid); /初始化命令字符串 wsprintf( szcmdbuf,open %s type sequencer alias bkmusic,szfi
57、lename); /打开设备 mcierror = mcisendstring( szcmdbuf, errbuf, sizeof(errbuf), null); if (mcierror = 0) /如果打开成功则播放 mcierror = mcisendstring(play bkmusic notify,null,0, hwnd); /根据播放操作是否成功决定是否关闭设备 if (mcierror != 0) mcisendstring(close bkmusic,null,0,null); / /终止插放背景音乐 / void cskyblue_rectview:stopmid() /
58、关闭设备 mcisendstring(close bkmusic,null,0,null); 完成播放 playmid()以及停止播放 stopmid()的功能封装后,现在只需在相应的菜单 选项以及适当的代码位置中加上它们就可以了。 5.2 工具栏快捷键的实现工具栏快捷键的实现 在完成上面补充功能的拓展和完善后,接下来为俄罗斯方块游戏增加一个放置常用 功能选项的工具栏,以便用户可以通过鼠标点击而直接对相应的选项功能进行实现。这 些常用功能选项分别是游戏的“开始”、“暂停”、“结束”、“配置”。 (1)工具栏的定义 /in file:mainfrm.h class:cmainframe ctoo
59、lbar m_wndtoolbar (2)工具栏的创建 /jin file:mainfrm.cpp int cmainframe:oncreate(lpcreatestruct lpcreatestruct) if (cframewnd:oncreate(lpcreatestruct) = -1) return -1; /工具栏的实现 cimagelist img; cstring str; if (!m_wndtoolbar.createex(this, tbstyle_flat, ws_child | ws_visible | cbrs_top | cbrs_gripper | cbrs_
60、tooltips | cbrs_flyby | cbrs_size_dynamic) return -1; /设置按钮的宽度和长度 m_wndtoolbar.gettoolbarctrl().setbuttonwidth(40, 100); /改变属性 m_wndtoolbar.modifystyle(0, tbstyle_flat |cbrs_tooltips | tbstyle_transparent|tbbs_checkbox ); /设置按钮数为 6 m_wndtoolbar.setbuttons(null,4); / 2. 添加图像 /设置热/hot状态的的位图 img.create
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 吉林师范大学《数字图像处理》2021-2022学年期末试卷
- 体育赛事组织安全预案
- 生态修复项目施工总承包管理方案
- 吉林师范大学《传统纹饰设计应用基础》2021-2022学年第一学期期末试卷
- 吉林大学《岩土力学》2021-2022学年第一学期期末试卷
- 吉林大学《统计学原理与应用》2021-2022学年第一学期期末试卷
- 妇幼保健质量管理制度
- 旅游景点灯箱广告安装方案
- 2024装饰工程分包合同范本版
- 吉林大学《交通运输工程导论》2021-2022学年第一学期期末试卷
- 《义务教育数学课程标准(2022年版)》测试题+答案
- 2024年网上大学智能云服务交付工程师认证考试题库800题(含答案)
- 数据安全重要数据风险评估报告
- 特种设备使用单位日管控、周排查、月调度示范表
- 初中语文测试质量分析表(模板)
- HSK标准教程4下课件第十一课《读书好,读好书,好读书》
- 变形观测记录表.doc
- 《与朱元思书》《与顾章书》阅读练习及答案
- 民办中小学校教育收费定价成本监审表
- 山地项目场地平整设计方案说明范本
- 个人房屋买卖合同
评论
0/150
提交评论