什么是复合控件?就是将多个基本控件组合在一起,给用户提供更多交互功能的控件,例如:游戏中的设置对话框,可以用来更改游戏设置。那么,游戏中的自定义复合控件是如何实现的呢?我们先来看看本节课要实现的效果——数字选择框,一个由掩码图层和多个按钮控件组合而成的复合控件,运行效果如下:
当用户点击数字面板时,将弹出数字选择面板。好了,我们来看看游戏代码更改了哪些地方。首先,修改了数字面板响应鼠标点击的回调函数的代码,修改后的代码如下:
这个回调函数内主要是做以下几件事:1、清除事件标记,表示已事件(鼠标点击)处理;2、修改响应事件的索引层次序(数字选择面板所在层);3、修改游戏状态(显示数字选择面板)。由于修改了游戏状态值,我们再看看游戏状态值发生了哪些改变,代码如下:
游戏状态4表示显示数字选择面板。注意,一旦修改了游戏状态值,那么绘制游戏场景的函数也需要修改,修改后的代码如下:
由于显示数字选择面板时,游戏主面板也需要显示出来,所以游戏状态值4和游戏状态值2共用了显示游戏主面板的代码,然后判断游戏状态值是不是4,是的话再把数字选择面板显示出来。现在是时候来看看数字选择面板的实现代码了,首先,我们看看那个掩码层是如何实现的,代码如下:
掩码层类gxsMaskLayer继承自gxsShape类,有两个成员函数initParameter()和draw(),initParameter()函数主要是对掩码层的位置及大小进行初始化,以上数字均为设计时使用的坐标,所以在运行时要进行缩放。掩码层在设计时其位置为(0,500),大小为400×100,游戏主面板尺寸为400×600(设计尺寸)。draw()函数代码如下:
这个函数将掩码层下面的图像取出来,然后逐像素与蓝色进行aplha混和,其结果是背景和蓝色各占一半(透过蓝色可以看见背景图像)。下面我们看看数字选择面板类gxsNumForSelect的实现代码,代码如下:
构造函数带参数n,表示控件的名称,用来初始化sName成员变量;pMask表示掩码层对象,注意那个gxsUI.call(this)语句,这条语句初始化aChildUI数组(子控件数组);initParameter()成员函数依据控件初始化参数数组中的值初始化数字选择面板,我们看看数字选择面板的初始化参数是什么,代码如下:
以上变量的作用都不难理解,主要是child,这个数组用来保存子控件(均为按钮控件)在g_aControlPara数组中的索引,每一个子控件在g_aControlPara数组中的定义如下:
每个按钮控件在g_aControlPara数组中均由三个对象构成,obj表示按钮控件本身;fcb表示点击按钮控件后将调用的回调函数;initPara为按钮控件的初始化参数。由于数字选择面板在g_aControlPara数组内使用了子控件索引数组,所以gxsUI类init()成员函数的代码需要修改,修改后的代码如下:
之前的代码在初始化绘制控件使用的图片对象之后就返回了,现在要判断当前初始化的控件是否有子控件,如果有的话则依次将每一个子控件添加到aChildUI数组成员变量中。看到这里你肯定会说,扯蛋!你都还没有创建子控件如何添加?那么子控件到底是在什么地方创建的呢?下面我们来看看创建子控件的代码:
好了,代码给出来了,下面我来问问你:这些按钮控件会在什么时候创建呢?这个问题留给大家思考,下面,让我们继续讲数字选择面板的实现代码,draw()成员函数的代码如下:
首先绘制掩码层,然后按每行9个子控件依次排列子控件,接着依次绘制每一个子控件。我们看看子控件是如何排列整齐的,排列子控件的代码如下:
由于有子控件,在处理事件时要考虑到子控件应优先对事件进行处理,所以gxsUI.handle()成员函数的代码需要修改,修改后的代码如下:
在处理事件的时候需要判断当前控件是否有子控件,有的话让子控件优先响应事件。那个clear()成员函数是新增加的,代码如下:
这个函数主要判断控件状态是否变更完毕,如是的话将控件状态复位。接着引成员函数调用控件的回调函数并返回事件已处理标记true。最后就是数字选择面板子控件的回调函数中调用的FillNum()函数的代码了,这个函数的作用是将相应数字填入数字面板,目前是一个空函数,下次将介绍它的实现。
子控件的事件处理是整个游戏中的难点,很高兴你能坚持到这里,接下来的内容都比较简单了。最后,将今天的内容录了一个视频,文章未提到的地方可以参看视频。
未完待续,敬请关注!后续更精彩,谢谢大家!