MTK平台大鱼吃小鱼的实现4.2 游戏的实现图4.8 游戏分层DL层(data layer 数据层):主要是抽象游戏中的数据,并选择合适的存储方式进行存储。
LL层(logic layer 逻辑层):主要是将游戏中逻辑(游戏规则)分解为一系列的功能方法,通过对游戏逻辑的分解,可以结构化项目的代码,也可以实现对于项目进度的准确把握,方便项目进度的控制。
UL层(user layer用户层):主要完成游戏的程序界面布局,以及实现游戏操作按键的设定。
4.2.1 DL层设计数据是一个程序的灵魂,数据的存放方式被称之为数据结构(Data Structure),不同的程序需要根据自身的需要,设计不同的数据存储方式,而数据结构有将对后续的程序算法产生直接的影响,所以数据结构设计的好坏,对于整个项目的影响是很严重的。
在程序开发中,设计数据结构的步骤一般如下:(1)分析需要存储的信息(2)将这些信息抽象为程序中的数据(3)根据程序中的数据进行结构设计(1) 分析需要存储的信息在程序中需要存储的信息一般分为两部分:界面控制信息和逻辑控制信息。
界面控制信息用于控制界面上各个元素的显示等,逻辑控制信息用于进行程序内部的逻辑处理,一般界面控制信息是可见的,而逻辑控制信息在界面上不是直接可见的。
在“大鱼吃小鱼”游戏中,界面控制信息主要包含两个部分:玩家控制的鱼的位置信息,自由移动的鱼的位置信息,屏幕上玩家的信息:包括得分、难度等级、生命数以及时间的倒计时。
而逻辑控制信息主要包含:玩家控制的鱼的移动方向、自由移动的鱼的移动方向。
(2)将这些信息抽象为程序中的数据程序中需要存储的信息抽象出来了以后,就是以什么类型的数据来存储这些信息的问题了,这里是计算机编程中对于数据的抽象。
本课题使用的手机屏幕大小为320×240,这里的320和240指的是屏幕显示的像素(pixel)个数像素是由picture(图像)和element(元素)这两个单词的字母所组成的,是用来计算数码影像的基本单位,一个像素通常在屏幕上显示为单个染色点。
对于界面控制信息的存储,计算机编程中使用的知识和数学上是一样的,都是利用坐标系的知识来存储位置信息。
对于平面游戏(2D游戏)来说,存储位置时使用的也是直角坐标系(笛卡尔坐标系),只是坐标系的形式和数学上的坐标系不完全一致。
在计算机中,我们建立二维x,y坐标轴,水平方向为x轴,向右为x轴正方向,垂直方向为y轴,向下为y轴正方向,x、y交点为坐标原点。
将屏幕左上角放置在原点,则屏幕在坐标轴中的范围可表示为(0≤x≤319,0≤y≤239),屏幕右下角的坐标为(319,239)。
图4.9 游戏设计坐标图有了坐标系的知识以后,就方便了界面中位置的存储了。
对于所有的鱼,包括玩家控制的鱼以及能够自由移动的鱼,我们只需要存储它们的坐标以及移动的方向,也就是说,需要存储每条鱼的坐标和移动方向。
另外,由于每一条鱼都是一个区域,程序中一般存储每条鱼左上角的坐标,而将鱼宽度和高度处理成常量。
这样每条鱼就需要两个整数分别存储x坐标、y坐标。
所有的鱼的整个结构则需要一组这样的结构体进行实际的存储就可以了。
对于玩家的得分、生命数、难度等级以及剩余时间直接通过四个整型变量存储即可。
对于逻辑控制信息的存储,鱼的移动方向在实际存储时,需要进行抽象,在该游戏中,鱼的移动方向不外乎四种:上、下、左、右。
在程序中只需要找出能够存储四种状态的类型即可,一般选择整数型,而为了便于程序的阅读,一般将四种方向声明为程序中的常量。
(3)根据程序中的数据进行结构设计将数据抽象成程序中的数据以后,就需要设计使用什么样的结构来存储这些数据了。
在程序中,鱼移动的方向可以定义为一个枚举类型,设计结果如下:typedef enum{FISH_CLT_MOVE_NONE,//不受控制时FISH_CLT_MOVE_LEFT,//向左移动FISH_CLT_MOVE_RIGHT,//向右移动FISH_CLT_MOVE_UP,//向上移动FISH_CLT_MOVE_DOWN //向下移动}mmi_swallowfish_move;鱼的位置以及移动方向,在程序中,均可认为属于鱼的属性,则可以定义成一个结构体,在程序中更为简洁,设计结果如下:typedef struct{S16 x;//鱼的横坐标S16 y;//鱼的纵坐标mmi_swallowfish_move direction;//鱼移动的方向}mmi_swallowfish_property;对于每条鱼存储,可以采用的数据结构有很多,例如数组、链表等线性的结构都可以,在本程序中,选择结构体数组进行实现。
由于难度等级的变化,小鱼的数量不一,所以在使用数组时,首先声明一个长度比较大的数组,开始只使用其中的一部分,当鱼的条数增加,变化使用的数据即可。
每一个数组元素均可代表一条鱼,设计如下:mmi_swallowfish_property g_free_fish[10];游戏中,玩家的得分、生命数、难度等级以及时间的剩余都比较简单,通过四个全局变量来记录当前的值,设计如下:static S8 g_score = 0;//记录当前游戏的得分static S8 g_player_lives = 3;//当前游戏玩家所剩的生命数,游戏最初默认为3static U8 g_level = 0;//玩家选择的游戏难易程度static S32 g_time_left ;//当前的剩余时间static S8 g_speed;//根据难度等级不同,自由移动的鱼的速度相应的有所不同此外,游戏还包括了其他许多变量,设计结果如下:变量S16 g_plot_level用来表示不同大小的鱼,当g_plot_level的值为1时,玩家控制的鱼则为小鱼;当g_plot_level的值为2时,玩家控制的鱼则为中鱼,以此类推;定义一个布尔类型的变量is_game_over来表示游戏是否结束,当游戏结束时is_game_over的值为True,当游戏未结束时,is_game_over值为False;游戏中,还需要将每个难度级别的最高分显示出来,而这部分的分别值存储在NVRAM 中,设计如下:U16 nvram_id[3] = {NVRAM_SWALLOWFISH_GRADES_LEVEL1,NVRAM_SWALLOWFISH_GRADES_LEVEL2,NVRAM_SWALLOWFISH_GRADES_LEVEL3};每一级对应的最高分写进对应的nvram_id的每个元素中。
4.2.2 LL层设计游戏逻辑即游戏规则,是游戏编程中最核心的部分,也是最难实现的部分,在游戏程序的开发过程中,大部分时间都是用在游戏逻辑的实现上。
游戏逻辑基于游戏数据结构,从程序开发角度来看,游戏逻辑就是对于游戏数据的规则变换。
当然,这些数据的变换需要根据游戏规则进行实现。
然后把最终变化的结果以界面的形式显示给最终用户,对于游戏程序来说也就是游戏玩家。
进行游戏逻辑的设计,首先要把游戏规则分析出来,所谓游戏规则,就是在游戏中需要程序设计人员实现的规定和控制,这些可以根据游戏的功能进行实现。
“大鱼吃小鱼”游戏需要实现的游戏规则如下:(l)游戏初始化(2)玩家控制的鱼的移动及方向控制(3)自由移动的鱼(4)大鱼小鱼的碰撞和处理(5)游戏结束和胜利的判别(6)游戏的暂停在程序实际实现时,一般使用方法来组织游戏逻辑相关的代码,也就是将对应的游戏逻辑转换为一个函数或许多函数。
由于以上逻辑都比较简单,所以在实际实现时都转换为一个方法。
下面依次来讲解以上游戏逻辑的实现,并介绍实现时需要注意的一些问题。
(1)游戏初始化游戏初始化实现的功能是初始化游戏的相关数据,一般在游戏开始、游戏结束以及过关游戏的关卡切换时调用。
实现该功能首先需要清晰的知道需要初始化那些数据,如何进行初始化。
在“大鱼吃小鱼”游戏中,需要初始化的主要数据是玩家控制的鱼和自由移动的鱼的位置、方向,另外还包含玩家的一些信息,以及一些游戏中控制的变量。
在本游戏中,采用如下的策略进行初始化:将玩家控制基本初始化在屏幕的中央、初始移动方向,其他自由移动的鱼的坐标按照一定规则设定。
游戏的初始化代码如下:{g_free_fish[0].x = 60;g_free_fish[0].y = 50;g_free_fish[0].direction = FISH_CLT_MOVE_RIGHT;g_free_fish[1].x = 150;g_free_fish[1].y = 80;g_free_fish[1].direction = FISH_CLT_MOVE_LEFT;g_free_fish[2].x = 40;g_free_fish[2].y = 100;g_free_fish[2].direction = FISH_CLT_MOVE_DOWN;g_free_fish[3].x = 200;g_free_fish[3].y = 160;g_free_fish[3].direction = FISH_CLT_MOVE_UP;g_free_fish[4].x = 90;g_free_fish[4].y = 190;g_free_fish[4].direction = FISH_CLT_MOVE_RIGHT;g_free_fish[5].x = 240;g_free_fish[5].y = 130;g_free_fish[5].direction = FISH_CLT_MOVE_LEFT;g_free_fish[6].x = 280;g_free_fish[6].y = 210;g_free_fish[6].direction = FISH_CLT_MOVE_DOWN;g_free_fish[7].x = 100;g_free_fish[7].y = 60;g_free_fish[7].direction = FISH_CLT_MOVE_UP;g_free_fish[8].x = 130;g_free_fish[8].y = 150;g_free_fish[8].direction = FISH_CLT_MOVE_RIGHT;g_score = 0;g_time_left = (g_time_attack + 1) * 600;g_plot_level = 1;g_player_lives = 3;g_fish_ctl_x = 70;g_fish_ctl_y = 40;}(2)玩家控制的鱼的移动及方向控制玩家控制的鱼的移动及方向控制是大鱼吃小鱼游戏的核心规则,也是需要考虑时间比较长的规则。
玩家控制的鱼的移动的规则如下:在本课题中,所有鱼的移动是通过一个定时器的设定,在每隔200ms的情况下,小鱼的位置(即坐标值)不停变化,然后刷屏,绘制小鱼,利用人们视觉的暂留性,使玩家感觉小鱼在不停地移动。