目录
1 绪论
1.1程序开发背景及意义
1.2开发技术概述
1.3俄罗斯方块游戏的研究现状
1.3.1 国内外研究现状
1.3.2 文献综述
2相关技术
2.4.1 硬件平台:
2.4.2 软件平台:
3 系统分析
3.1可行性分析
3.1.1经济可行性分析
3.1.2技术可行性分析
3.1.3社会可行性分析
3.2需求分析
3.2.1 功能性需求
3.2.2 非功能性需求
3.2.3 接口控制
4 系统的概要设计
4.1 系统的功能设计
4.1.1 手动处理业务的基本流程
4.1.2 基本流程的功能模块
5 系统的详细设计与实现
5.1 游戏主界面显示模块
5.2 画布、方块显示模块
5.2.1 背景画布模块设计
5.2.2 预览方块模块设计
5.2.3 方块移动、旋转模块设计
6.联系与交流
1 绪论
绪论从程序的开发背景、开发意义以及所需要开发技术和目前国内外对俄罗斯方块游戏的研究现状进行了简要的叙述。
1.1程序开发背景及意义
俄罗斯方块游戏是一款流行于全世界并且经久不衰的游戏,是一款在计算机,手机,电视游戏机,掌上游戏机等一系列产品上都能玩的休闲小游戏,它曾经创造了几乎任何游戏都无可匹敌的轰动和无数的商业价值,是游戏史,软件开发史上的一件重要的大事。
在1984年6月的一天,俄罗斯莫斯科的数学家阿列克谢·帕基特诺夫(Alex Pajitnov)在工作地点莫斯科科学计算机中心玩过一个拼图游戏后突然受到启发,而设计出这款游戏,刚开始他只是在Electronica 60(一种计算机)上进行开发,后来经由瓦丁·格拉西莫夫(Vadim Gerasimov)移植到PC端,并且在莫斯科的计算机界广泛传播,俄罗斯方块开始大火,成为了有史以来最为畅销的经典休闲小游戏,至今还一如既往保持魅力。俄罗斯方块简单的基本游戏规则是在一个用于摆放小正方形的标准虚拟游戏场地,基本单位为小型正方形;由四个小型正方形组成7中不同的规则图形(田字形,Z字形,反Z字形,7字形,反7字形,T字形,长条形)通过玩家操作上键以90度,180度,270度,360度旋转方块一共有28种图形方案,通过左键右键左右移动,下键加速下落调整位置,是方块在屏幕底部拼出完整的一条或几条,然后消除,给新落下的方块腾出位置,每消除一条完整横条,玩家等级提高一级,当等级提高到一定等级时刚快下落速度加快,一旦没被消除的方块到达屏幕顶端,游戏结束。
随着计算机技术的日益更新和不断发展,俄罗斯方块游戏也不断地推出各式各样的模式,也有许多不同的版本供大家玩耍,因为游戏本身有简单,有复杂,能够很好地锻炼游戏玩家的脑力反应能力,和逻辑思维能力,还能给玩家带来无穷的游戏乐趣,所以深受广大玩家的喜欢。对于开发游戏软件,大多数人都感到触摸不到,很神奇,随着开发方法和工具的不断推陈出新,自己动手开发一些小游戏也并非遥不可及。俄罗斯方块游戏在游戏史上的地位无可匹敌,并且游戏的界面简约,代码并不是很复杂,互联网上也有很多关于俄罗斯方块游戏实现的一些算法和设计,难度并非特别大。
俄罗斯方块游戏简单,益智,以其独特简洁的界面和极具玩耍乐趣的模式让众多的游戏爱好者深陷其中,无法自拔,并且老少皆宜。在如今快节奏的生活当中,学生和工作党的学习工作压力也随之越来越大,每个人的任务逐渐繁重,越来越少的自由支配休息时间让人们更加迫切的需要有一些既简单又节省时间的休闲游戏供大家娱乐。毫无疑问,俄罗斯方块是一款简单益智有趣的休闲小游戏,并且可以移植到电脑、手机、平板电脑、电视游戏机、掌上游戏机、电子词典、Mp4等一系列便携设备上。本次课题研究,无论从技术开发上,还是社会意义上,都是很有价值的,是本人对游戏开发的一次胆大尝试。
1.2开发技术概述
俄罗斯方块游戏开发代码相对来说不是特别复杂,本论文基于Java编程语言,采用Java语言中常用的Swing组件。Swing是Java中的图形用户界面(GUI)工具包,是Java基础类的一部分,包括了文本框,分隔窗格,按钮,表等GUI器件,使用纯Java写成,开发人员可以用少量的代码就可以写出Swing各式各样的灵活丰富的功能和模块化组件来创建漂亮优美的用户界面。Java Swing组件中包括以下几个常用的类:JFrame 是屏幕上的图形对象,可以有最大化、最小化、关闭等基本操作,是Java的GUI程序设计的基本思路;JPanel 能够用来嵌套,对窗体中有相同逻辑功能的组件进行组合,能够加到JFrame窗体中,是Swing中的面板容器类。 JLabel 对象是用来显示文本、图像或同时显示二者并且可以设置其中的一些属性;JTextField是一个用来编辑单行文本的运行组件;JButton是一个用来创建按钮的类。除此之外,Java中的Swing组件中还包含有许多功能的类,可以简单的来创建一些优美漂亮的图形界面。
1.3俄罗斯方块游戏的研究现状
1.3.1 国内外研究现状
前苏联科学家阿列克谢·帕基特诺夫(Alex Pajitnov)原本开发的《俄罗斯方块》游戏是作为一种教育用软件的,之后开始提供授权给各个游戏公司,至此以后,各大平台上就出现了各种不同版本的游戏。
Game Boy版的俄罗斯方块游戏在日本本土卖出了424万套,成为了Game Boy游戏史上卖的最火的游戏。在海湾战争期间,俄罗斯方块游戏成为了前线美军最适合的消磨时间的游戏之一。
俄罗斯方块游戏的基本原理对于大多数程序员来说是相对比较简单的,并且俄罗斯方块游戏具有数学性,动态性和很强的知名度。也经常拿来作为游戏程序设计的练习题材。
1.3.2 文献综述
文献[1]和文献[2]以零基础讲解为宗旨,用实例引导读者深入学习,采染基础知识→核心技术→高级应用→项目实战的讲解模式,深入浅出地讲解Java的各项技术及实战技能。从初学者角度出发,通过通俗易懂的语言、丰富多彩的实例,详细介绍了使用Java语言进行程序开发应该掌握的各方面技术。包括:熟悉Eclipse开发工具,Java 语言基础,类和对象,包装类,数字处理类,接口、继承与多态,类的高级特性,异常处理,Swing程序设计,集合类,I/O输入输出,反射,枚举类型与泛型,多线程,网络通信,数据库操作,Swing表格组件,Swing树组件,Swing其他高级组件,高级布局管理器,高级事件处理,AWT绘图与音频播放等。这两本文献覆盖了“够用”得Java语言和技术,实例丰富,内容详尽,对于初学者和有一定的Java基础的学生来说,可以快速的提高学生的开发技术和技能。本课题设计中有关图形界面设计的内容、用户界面构件及设计、事件处理与窗口构造构件以及Swing的基础知识及其系列组件等方面的内容都参考了这两本文献,给予了我很大的帮助。
文献[3]主要讲解了包括2D绘图;游戏动画的制作;网络程序基础;强化游戏界面;人工智能与2.5D游戏;扫雷、迷宫、俄罗斯方块等游戏实例;碰撞、粒子系统、5D立体坐标等绘图算法;多人联机游戏制作。收集了一系列的算法公式,让读者能更方便的利用。以由浅入深的方式,逐步分析游戏设计的过程,带领读者解决游戏开发阶段可能遇到的问题,并总结了Java游戏制作的实战经验。本课程设计中游戏的原理、动画的实现、音效的处理、鼠标和键盘事件处理、人工智能等知识都参考了该文献。
文献[4]探讨了经典的电脑游戏-俄罗斯方块的程序原理及其实现技术,从软件工程的角度描述了程序的功能要求、数据结构以及图形旋转、坐标变换等关键技术。通过这本文献让我了解了更多的关于俄罗斯方块游戏开发的专业领域的知识。
文献[5]属于进阶性书籍,更加侧重于讲解如何使用Java来思考解决问题。这本文献本次课程设计中,给予了我很多关于Java在编程时编程思想和技巧上很多的帮助。
2相关技术
2.4.1 硬件平台:
本程序开发计算机硬件如下:
硬盘:500G
CPU:Intel(R)Core(TM)i5—3230M CPU @2.60GHz
交互工具:键盘、鼠标
显示器:LCD显示器
2.4.2 软件平台:
本系统的开发环境如下
操作系统:Microsoft Windows 7 Ultumate
JDK版本:jdk-8u121-windows-x64
Eclipse版本: Neon.2 Release (4.6.2),eclipse-inst-win64
3 系统分析
系统分析是软件开发过程中我们所要做的第一步,包括系统的需求分析和可行性分析。系统的需求分析,主要是用来说明本系统是一个什么系统,必须用来做什么,就这个问题上达到开发人员和主要用户之间的共识。系统的可行性分析,主要就是对系统的所有的一切资源实施进行分析,用来说明系统的开发和投入的合理性,可行性和必然性,并对其中可能会出现的不可预见性的问题进行合理的分析。软件开发中最具有挑战性的环节莫过于对系统的需求分析,花费在需求分析上的时间无疑是非常有价值的,如果时常发生需求变更,会给软件开发在预定计划内完成的任务带来非常严重的不利影响。做好系统的需求分析和可行性分析,这样有利于提高软件开发过程中的便利性,能对软件开发过程进行实时监控和管理,更方便的按计划进行,从而达到提高软件的质量的目的,为程序开发人员,用户等提供更便携的交流合作。作为工作成果的原始依据,系统的需求分析和可行性分析也间接的可以向潜在用户表达自己系统的功能,让用户来判断系统的功能等是否符合所要达到的需求。
3.1可行性分析
可行性分析基于技术,经济,工程,技术等方面的项目主要内容和配套条件,如市场需求,资源供应,施工规模,工艺路线,设备选型,环境影响,资金筹集,盈利能力等。 其他方面研究分析比较,项目完成后可能取得的财务,经济和社会环境影响的预测,该项目是否值得投资,以及如何对项目决策进行咨询建设,为全面的系统分析方法提供依据。 可行性分析应具有远见,公正,可靠,科学的特点。
为了保证可行性研究工作的科学性、客观性和公正性,有效地防止错误和遗漏,在可行性研究中,首先必须站在客观公正的立场进行调查研究,做好基础资料的收集工作。对于收集的基础资料,要按照客观实际情况进行论证评价,如实地反映客观经济规律,从客观数据出发,通过科学分析,得出项目是否可行的结论。
可行性研究报告的内容深度必须达到国家规定的标准,基本内容要完整,应尽可能多地占有数据资料,避免粗制滥造,搞形式主义。
在做法上要掌握好以下几个要点:先论证,后决策;处理好项目建议书、可行性研究、评估这三个阶段的关系,哪一个阶段发现不可行都应当停止研究;要将调查研究贯彻始终。一定要掌握切实可靠的资料,以保证资料选取的全面性、重要性、客观性和连续性;多方案比较,择优选取。对于涉外项目,或者在加入WTO等外在因素的压力下必须与国外接轨的项目,可行性研究的内容及深度还应尽可能与国际接轨。
为保证可行性研究的工作质量,应保证咨询设计单位足够的工作周期,防止因各种原因的不负责任草率行事。
可行性分析的目的是确定是否可以在最短时间之内用最低的成本解决这个问题。可行性分析最主要的不是解决问题,而是要研究这些问题是否值得去花费人力和财力去研究和解决。如果有简单易行的方法则予以肯定。
3.1.1经济可行性分析
系统的经济可行性分析的目的是,核算系统从开发建设到系统运行期间所需的资金投入,以及新系统的市场需求及经济效益,将投入预算与预计收益进行对比,核算经济方面的成本的可行性。
本游戏系统主要是用于大学生软件工程毕业课程设计,不需要考虑其所能产生的经济效益和游戏日后的发展状态。对游戏系统的本身的经济要求并不高,只是通过本游戏系统的开发来提升学生自身的知识和能力水平。只需要有一台装有JDK运行环境和Java开发工具Eclipse软件的电脑就可以,所以经济问题可不用考虑。
3.1.2技术可行性分析
可用于编写俄罗斯方块游戏的编程语言有很多,本次课题主要是在基于Java的环境下进行游戏系统的开发,所以本系统主要利用的是Java中的Swing组件进行开发,需要对变量定义,初始化,界面设计,游戏初始化,进入游戏,退出游戏,处理游戏过程中的各种操作进行相应功能的代码要求,技术方面要求并非特别困难,技术可行。
3.1.3社会可行性分析
本游戏系统的开发主要是用于毕业课程设计与论文,用以巩固大学四年学习的知识,主要以个人和学校为单位,仅供个人娱乐和学校的课程设计与毕业论文检查入档案,不会对社会造成任何的影响,所以无需考虑到任何法律,版权等一系列社会因素,在这方面完全可行。
3.2需求分析
所谓的“需求分析”是指对待解决的问题的详细分析,澄清问题的要求,包括需要输入什么数据,得到什么结果,最后应该输出什么。可以说,在软件工程中“需求分析”是确定电脑“做什么”,达到什么样的效果。可以说,需求分析是在系统完成之前完成的。
在软件工程中,需求分析是指在创建新的或更改现有计算机系统时描述新系统的目的,范围,定义和功能所需的所有工作。需求分析是软件工程中的关键过程。在这个过程中,系统分析师和软件工程师决定了客户的需求。只有在确定了这些需求之后,才能分析和寻求新系统的解决方案。需求分析阶段的任务是确定软件系统功能。
在软件工程的历史上,人们一直认为需求分析是软件工程中最简单的一步。但是在过去十年中,越来越多的人意识到需求分析是最重要的过程。如果分析师在需求分析时无法正确地了解客户的需求,则最终软件无法真正达到客户的需求,或软件项目在指定时间内无法完成。
3.2.1 功能性需求
▪ 游戏界面需求:游戏的良好的界面会让玩家眼前一亮,更加能充分的感受到游戏带来的娱乐性,放松性。本游戏的默认背景色是深绿色,游戏主界面画面自定义为自己的所喜欢的图片,并可以更改,主界面方块默认用橘黄色,预显方块颜色默认为淡紫色。背景色、前景色对比鲜明,以达到让玩家眼前一亮的感觉,并能在游戏达到高等级状态,方块下落速度渐高的情况下使玩家能够清楚的分辨出下落方块的形状,增加游戏的刺激性。
▪ 游戏形状需求:用数组作为存储方块52种状态的数据结构,即初级等级长条形、Z字形、反Z形、田字形、7字形、反7形、T字型一共7种形状的向4个方向的旋转变形,和中级等级的三种方块12种不同的状态,高级等级的三种方块12种不同的状态。各个方块可以实现按逆时针的旋转方式旋转,并且方块能否旋转需要用条件加以判断,如果旋转后可能发生越界,则不能旋转,需要调整位置来保证他可以旋转。
▪ 键盘处理事件需求:当方块下落时,玩家可以通过键盘上的方向键:上键实现旋转,下键实现加速下落,左键实现左移,右键实现右移,和空格键实现一键下落,字母P键实现暂停,字母C键实现继续等一系列的操作。
▪ 鼠标处理事件需求:通过鼠标,可以点击控制面板中的菜单按钮和帮助按钮,选择菜单栏的菜单项,可以实现游戏的开局,选择游戏等级,更改游戏中方块的颜色显示,游戏主界面背景色和前景色的显示,更改游戏背景图片,方块下落速度,是否播放游戏中的声音等一系列的功能。
▪ 显示需求:本游戏程序的显示需求是要求当方块落下后填满一整行,则该行消除,其余剩下的未填满的行自动逐次向下移动,消去一行右界面得分增加十分,当分数增加到100分时,等级增加一等级。当方块落下叠加到主界面的全部所有行时,方块不再下落,游戏结束,主界面提示“Game Over”字样。
3.2.2 非功能性需求
非功能性需求:俄罗斯方块游戏系统的非功能性需求包括游戏主界面左上角图标显示,调整窗口尺寸最大化最小化(但不包括主界面的尺寸大小),游戏运行时弹出窗口的位置居中等一系列非功能性需求。
3.2.3 接口控制
本俄罗斯游戏系统在Windows操作系统下,主要是通过键盘进行游戏的操
作,通过鼠标进行开局,退出,设置等一系列操作。首先,游戏利用键盘的按键进行游戏的操作,所以需要使用键盘的接口事件。其次,在游戏进行的全过程中,需要使用鼠标进行游戏的控制,包括开始,选择等级,改变设置,改变颜色,查看版本信息,退出等,所以要对鼠标的单击,按键添加接口监听事件,编写相应的代码来实现鼠标和键盘的相应功能。
4 系统的概要设计
4.1 系统的功能设计
4.1.1 手动处理业务的基本流程
本游戏的设计以娱乐为初衷,以益智为目的,在综合研究以往俄罗斯方块经典游戏功能的基础上推陈出新,加之新的功能,赋以新的生机和活力。以下具体阐述游戏的基本流程。
运行说明:
1>运行程序,点击右侧控制面板内的“开始”或“控制”菜单内的“开始”按钮开始游戏。
2>使用上、下、左、右键和空格键,P键,C键控制方块的变形、下落、向左和向右移动和一键迅速下落,暂停,继续。
3>方块满行消除,分数自动增加,等级自动增加一级。
4>等级增加、方块下落速度增加,按右侧控制面板或“游戏”菜单内的“初级”“中级”,“高级”按钮来手动改变游戏难易程度。也可点击“方块颜色”菜单内的选项,更改方块颜色等,也可以通过“自定义”菜单内的选项,来更改游戏的一些属性。
5>按键盘键字母P键可以控制游戏暂停,然后按子母键C键可以控制游戏继续上次游戏。按“结束游戏”按钮,游戏会彻底停止正在进行的当局游戏,再按“开始”或“控制”菜单内的“重新开始”会开始新游戏。
6>当方块占满整个窗口,不能再有新方块下落时,游戏会弹出“Game Over”的对话框提示游戏结束。
游戏的基本流程图如图4—1所示:
图4-1游戏的基本流程图
4.1.2 基本流程的功能模块
本系统基于游戏的各项功能来设计游戏的各个功能模块。图4-2为本游戏的系统功能模块示意图,如图所示,本游戏主要有两大模块:游戏界面区,游戏控制区。游戏界面区分显示玩家可选操作、显示玩家操作结果两个部分。游戏控制区分更改颜色、开始、更改游戏等级为初级、更改游戏等级为中级、更改游戏等级为高级、自定义下落速度、更改背景、退出以及其他等一些功能模块。
图4-2系统功能模块示意图
图4-3为游戏界面区模块设计示意图,如图所示,游戏界面区模块可细分为闯进新游戏界面、处理玩家操作、显示玩家操作结果三个功能模块。
图4-3界面模块示意图
图3-4为游戏控制区设计示意图,如图所示,游戏控制区模块分为开始、自定义操作设置、初始游戏级别设置、初始颜色设置、退出等功能模块。
5 系统的详细设计与实现
Java是一种纯面向对象(Object-Oriented)的程序语言,它的诸多优点在此就不作详细论述了。从面向对象的观念出发,本程序主要可分为以下几个模块:
●游戏主界面显示模块
●方块及数据显示模块
●方块移动控制模块
●游戏界面颜色控制模块
●游戏进度、等级控制模块
分析对象的技巧在于它的功能的扩展性及维护效率。试想,如果因为外部环境或者用户需求的变化需要对程序进行功能扩展或者维护,就要对代码作大幅度的更动甚至重写,这样就失去了面向对象的优势,所以在本程序分析时将独立性高的模块作为一个对象,以提高程序的可扩展性和可维护性。以下该游戏中类的设计:
MyFrame类:继承自JFrame类,作为游戏的主类,负责对游戏的主体全局进行控制,连接与指挥各个类的枢纽。
PreView类:继承自JPanel类,作为操作面板类,负责安放主游戏窗口,积分板,级别控制按钮等窗口用以控制游戏进程。
GameCanvas类:继承自JPanel类,ChangeBlockColor线程类动态改变画布类的方格颜色,画布类通过检查方格颜色来体现ChangeBlockColor方块的移动情况与消去状况。
Box类:方格类,组成方块的基本元素,主要表达方式为颜色。
Block类:作为操控方块的类,控制方块的移动,下落以及变形。
5.1 游戏主界面显示模块
一个优秀的软件系统不仅体现在核心的功能的多样性和强大上,如果使用者所面对的是枯燥的、陈旧的界面的话,那么这个的软件系统是不成功的,所以好的、精美的界面设计是极为重要的环节。为玩家设计制作布局合理、视觉效果良好的界面的重要性就不言而喻了。
游戏主界面采用Swing组件开发,并且向其注册监听器,以实现各种控制功能,综合游戏窗体的设计,其上至少需要注册三个监听器,分别是动作监听器(ActionListener)、键盘监听器(KeyListener)、选项监听器(ItemListener)。
根据初步设计,可以确定客户端上所要用到的Swing组件对象有JFrame对象、JPanel对象,JLabel对象、JButton对象、JMenuBar对象、JMenu对象、JMenuItem对象、JTextField对象、JTextArea对象、JDialog对象等,至少十个Swing组件对象。下图5-1为游戏主界面截图。
图5-1游戏主界面截图
本游戏主界面设计的初始颜色搭配基于对比鲜明的原则,默认背景色为深绿色,左上角设置俄罗斯方块图标,得分初始值为0,等级初始值为1,最高分记录初始值为0。游戏主窗体尺寸设置为(520,580),方块移动范围窗格由一个20行、12列的二维数组控制,且左上角图标设置为方块图案,起标识作用。
5.2 画布、方块显示模块
本游戏中将画布设计为自定义图片,可以根据自己的需求来自己动手更改背景图片,在方块下落过程中,根据颜色的变化识别下落的方块。
5.2.1 背景画布模块设计
该游戏的主背景画布是一个20行、12列的二维数组,方块显示是由相应颜色变化来标识,主窗体用颜色填充后可形成呈现出来背景样式和方块。本游戏用继承自JPanel的GameCanvas类控制背景画布的显示,用rows代表画布的行数,cols代表画布的列数,行数和列数决定着画布拥有方格的数目。背景画布主要实现代码如下:
首先,用一个画布类的构造函数来表示整个主界面的行数、列数以及主界
中的相对位置:
/**
* 画布类的构造函数
* @param rows int, 画布的行数
* @param cols int, 画布的列数
* 行数和列数决定着画布拥有方格的数目
*/
public GameCanvas(int rows, int cols) {
this.rows = rows;
this.cols = cols;
this.setOpaque(false);
boxes = new Box[rows][cols];
for (int i = 0; i < boxes.length; i++) {
for (int j = 0; j < boxes[i].length; j++) {
boxes[i][j] = new Box(false);
}
}
setBounds(0, 0, 300, 500);//设置相对位置坐标
setBorder(new EtchedBorder(
EtchedBorder.RAISED, Color.white, new Color(148, 145, 140)));
}
/**
* 取得画布中方格的行数
* @return int, 方格的行数
*/
public int getRows() {
return rows;
}
/**
* 取得画布中方格的列数
* @return int, 方格的列数
*/
public int getCols() {
return cols;
}
其次,在设置一个画布类的构造函数来表示整个主界面的前景色,背景色并获取其前景色和背景色:
/**
* 画布类的构造函数
* @param rows 与public GameCanvas(int rows, int cols)同
* @param cols 与public GameCanvas(int rows, int cols)同
* @param backColor Color, 背景色
* @param frontColor Color, 前景色
*/
public GameCanvas(int rows, int cols,
Color backColor, Color frontColor) {
this(rows, cols);
this.backColor = backColor;
this.frontColor = frontColor;
}
/**
* 设置游戏背景色彩
* @param backColor Color, 背景色彩
*/
public void setBackgroundColor(Color backColor) {
this.backColor = backColor;
}
/**
* 取得游戏背景色彩
* @return Color, 背景色彩
*/
public Color getBackgroundColor() {
return backColor;
}
5.2.2 预览方块模块设计
方块和数据信息是游戏中最基本的功能模块。Box这个类方格类,是组成块的基本元素,用自己的颜色来表示块的外观 ,MyTask继承TimerTask类用来定时下落,用计数方式来实现速度的改变,MyListener类继承KeyAdapter类用来实现按键监听,控制方块的上下左右。定义一个4x4方阵,共16个小格。用“0”和“1”来表示每个方格是绘制新颜色还是保留底色。
每得到一个新方块,都是随机从七种形态的方块中选取一种。游戏定义了一个变量,代表新方块的模型。比如定义int型数组STYLE代表28中方块类型,7行4列,每个元素代表其中一种方块。即0<=blockkindnum<=6,0=<blockstatusnum<=3
那么,当方块落下需要得到新方块时,只需随机得到一对blockkindnum,blockstatusnum值,然后再根据这个STYLE的值构画相应的方块。剩下的问题就是应该怎么随机到一对STYLE行列值。
Java语言包中的Math类提供了一个生成随机数的方法random(),调用这个方法会产生一个在0-1之间的双精度浮点数。所以每次要得到新方块时,只需调用一次这个方法,得到一个0-1的双精度浮点数,然后用该数乘以7,之后强转成整型,即可得到1—7的整数,用来控制行。用该数乘以4,之后强转成整型,即可得到1—4的整数,用来控制列。
由此可以组合出多种图形定义然后用代码实现下列功能:
1>每次执行首先为随机数产生不同的初值。
int col = (int) (Math.random() * (gc.getCols() - 3));//随即位置生成列
int style = Constant.STYLES[(int) (Math.random() * Block.get_addl())][(int) (Math.random() * 4)];
图5-2随机产生方块流程图
2>随机选取一个图形,图5-2随机产生方块图具体描述用生成的随机数控
产生的图形。
3>当前图形在其4*4网格中的位置信息。
绘制4行4列的方块预显方格,随机生成预显示的方块样式。本游戏用二维数组存储方块的28种样式。
值得注意的是:在传统的俄罗斯方块游戏的基础上,本游戏系统为了体现出创新的思维,本着为了学习的原则,在传统游戏的基础上增加了中级三种其他的方块样式和高级三种其他的方块样式。一共有52种方块样式,具体的存储方式主要实现代码如下:
/**
* 分别对应对13种模型的52种状态
*/
public final static int[][] STYLES = {// 共28种状态
{0xf000, 0x8888, 0xf000, 0x8888}, // 长条型的四种状态
{0x4e00, 0x4640, 0xe400, 0x4c40}, // 'T'型的四种状态
{0x4620, 0x6c00, 0x4620, 0x6c00}, // 反'Z'型的四种状态
{0x2640, 0xc600, 0x2640, 0xc600}, // 'Z'型的四种状态
{0x6220, 0x1700, 0x2230, 0x7400}, // '7'型的四种状态
{0x6440, 0xe200, 0x44c0, 0x8e00}, // 反'7'型的四种状态
{0x6600, 0x6600, 0x6600, 0x6600}, // 方块的四种状态
{0x8c88,0xf200,0x44c4,0x4f00},//增加的中级样式方块3个
{0xea00,0xc4c0,0xae00,0xc8c0},
{0x8c00,0xc800,0xc400,0x4c00},
{0xac00,0xcc40,0x6e00,0x8cc0},//增加的高级样式方块3个
{0x4e40,0x4e40,0x4e40,0x4e40},
{0x8480,0xa400,0x4840,0x4a00},
};
传统俄罗斯方块游戏的7种方块样式,相信很多人都知道,在这里就不一一截图展示常见的方块样式。以下是在传统游戏的模式下增加的三种中级难度和三种高级难度的方块模型:
●增加的三种中级难度方块模型(经过90度、180度、270度、360度旋得到四种转状态)
图5-10增加的三种中级难度方块模型
●增加的三种高级难度方块模型(经过90度、180度、270度、360度旋得到四种转状态)
图5-11增加的三种高级难度方块模型
5.2.3 方块移动、旋转模块设计
方块的翻转与移动比较容易实现,方块移动只需要改变方块的横坐标或纵坐标,然后重新绘制方块即可。方块翻转也只需要改变背景数组的值,重新绘制方块即可。
本游戏方块下落时,进行动态绘制,实现Cloneable接口, 以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。方块的操作类BlockOperation继承Thread类,重写run()方法,以实现方块的动态正确下落。当然,在线程中要判定方块是处于moving状态还是pausing状态。
publicvoid run()
{
//moving判定方块是否在动态下落
while (moving)
{
try
{
//betweenleveltime指示相邻等级之间相差时间
sleep(betweenleveltime
* (ControlMainGame.maxlevel - level + flatgene));
} catch (InterruptedException ie)
{
ie.printStackTrace();
}
//pausing判定游戏是否处于暂停状态
if (!pausing)
moving = (moveTo(y + 1, x) && moving);
//moving是在等待的100毫秒间,moving没被改变
}}
当然,在游戏中还要判定方块移动的边界问题, 比如,一个方块在它左边正好差一个格子的空间才能够翻转,但是它的右边恰好有一个格子的空间,这种情况,如果方块不能够翻转,就不方便用户操作,如果能够翻转,就会发生越界,将已经存在的方块挤占掉。要想实现翻转又不发生越界,那么,就应该在方块翻转后把它往右边移动一个格子,然后再绘制方块,这样,方块就不会挤占掉其它已经固定住的方块了,以下解决越界问题。
1>方块翻转判定
在两种情况可能发生越界,一种是方块落下去固定住以后,第二种是周围的空间不允许它进行翻转。
第一种情况只需要参考方块落下去后不能够再移动的判定即可。
对于第二种情况,在每次方块翻转前,必须首先计算出方块周围的空间,如果空间允许则翻转。否则,不能翻转。
因为七种方块是不规则的,每种方块要求的翻转空间都是不一样的,甚至是在它的不同翻转状态下,所要求的翻转空间也是不一样的,首先想到的自然就是为每一种方块,方块的每一种状态都写一个判定条件,但是这样做未免过于麻烦。
根据观察,不难发现,七种形态的方块,长条形的方块如果以横条的形态下落,则只要能够下落,就能翻转,如果以竖条的形态下落,那么它翻转后所处的位置必须要有4x1个格子的空间才能够翻转。对于田字形的方块,只有能够继续下坠,就一定能够翻转,所以田字型的方块只要没有落下,就一直能够翻转。而其它五种形态的方块,又有一个共同点,就是它们都有两种翻转状态横向占三个格子的空间,竖直方向占两个空间,另外两种翻转状态横向占两个格子的空间,竖直方向占三个格子空间,如果他们是以横向占三个格子的状态下落,那么只要能下落,就一定能够翻转,如果是以横向两个格子的状态下落,那么在翻转后,周围必须要有3x2个格子的空间。
所以,方块翻转的判定,要分三种情况,第一种情况是方块落下去后不能翻转;第二种情况是对竖直状态出现的长条形的方块进行翻转判定;第三种情况是对除长条形和田字形之外的其它五种以横向占两个格子的状态出现的方块进行翻转判定。
何种情况下方块能够翻转的问题解决了,接下来,我们就应该解决方块翻转后所处的位置的问题了,因为只有事先知道方块翻转后所处的位置,才能够对那个位置的空间范围进行判定,判定它是否能够容纳方块。
可以确定的是,无论方块怎么翻转,都处在方块数组中,也就是说方块必定是在游戏地图中某一4x4个格子的空间范围内。
方块数组在游戏主界面中的坐标是确定的,不确定的是方块翻转后到底处在方块数组的哪个位置,为了解决这个问题,我们可以限定方块在方块数组中的存储原则是靠左、靠上,这样,无论翻转怎么翻转,方块数组中第一行和第一列都是有方块的,这样也就确定了方块在方块数组中的位置,也就可以得知方块翻转后在游戏地图中的位置了。
假定方块数组的横纵坐标是x和y,那么,这个位置就是,长条形的方块翻转后所处的那一行是游戏地图的第y行,所占的列是第x到x+3列,长条形和田字形以外的五种方块翻转后的所占的行数是游戏地图的第y和第y+1行,所占的列是第x到x+2列。
所以,如果以上空间有空格子,方块就能够翻转。
2>翻转越界纠正
只要方块翻转后所处的空间足够,方块就能够翻转,但是,如果方块翻转后所处的空间不足够,而在它的另一边却有足够的空间呢?
方块在边界处时,翻转后不仅可能翻出地图外,还可能发生数组越界,当然,只需要将地图数组定义得大一些,就能够避免数组越界错误,对于方块越界,如果在它的另一边有足够空间,那么,就应该把方块往另一个方向移动适当的单位,纠正方块越界错误。如图5-12方块翻转流程图所示,方块翻转需要经三次判定:是否已经下落到底部、翻转后是否有足够空间、翻转后是否越界。
图5-12 方块翻转处理流程图
玩家操作键盘实现方块的移动、旋转,代码引进ControlKeyListener类继承KeyAdapter类进行键盘监听功能的实现。KeyAdapter类继承自Object类,实现KeyListener接口,用来接收键盘事件的抽象适配器类。此类中的方法为空。此类存在的目的是方便创建侦听器对象。扩展此类即可创建 KeyEvent 侦听器并重写所需事件的方法,即是 ControlKeyListener类。使用ControlKeyListener可创建侦听器对象,然后使用组件的 addKeyListener 方法向该组件注册此侦听器对象。当按下、释放或键入某个键时,将调用该侦听器对象中的相应方法,并将 KeyEvent 传递给相应的方法。实现代码如下:
privateclass ControlKeyListener extends KeyAdapter
{
publicvoid keyPressed(KeyEvent ke)
{
if (!game.isPlaying())
return;
BlockOperation blockope = game.getCurBlock();
switch (ke.getKeyCode())
{
case KeyEvent.VK_DOWN:
blockope.moveDown();
break;
case KeyEvent.VK_LEFT:
blockope.moveLeft();
break;
case KeyEvent.VK_RIGHT:
blockope.moveRight();
break;
case KeyEvent.VK_UP:
blockope.turnNext();
break;
default:
break;}}}
6.联系与交流
q:969060742 完整报告、程序资源、项目源码