LOFTER for ipad —— 让兴趣,更有趣

点击下载 关闭
sgf-py开发指南(十)开发一个控件

在通常的gui编程中,控件是框架提供好的,例如一个按钮,进度条,滑块等等。在sgf-py中这些都可以用Element实现,底层是sdl的surface。

深入了解传统意义上的控件

        在传统的windows开发中,“窗口”是组成windows可视化界面的基本元素,通过窗口中的控件用户可以很友好的实现人机交互。

以3d建模软件Blender为例,一个窗口中有这大量的控件,在图中简单的列举出了一些。

        一个windows程序的基本组成是“窗口”+“消息”,对于一个传统意义上的窗口是这样。同样的对于窗口中的控件来说也是这样的,主窗口中的控件依旧是一个窗口,只不过看起来不像而已。

        在于控件(窗口)互动的时候,控件(窗口)会产生各种各样的消息,这些消息会进入消息队列等待用户或者系统处理。

        同样的,在游戏中,“控件”的用作方式于传统的窗口程序相差无几。但游戏中的“控件”不一定是一个窗口了。

        不同的游戏开发者在游戏中实现控件的方法多种多样,比较出名的是imgui,在sgf-py中提供一些常用的UI控件,同样支持自定义。

sgf-py中的控件

        sgf-py的渲染器支持框架中Actor,Sprite,Element三种类的渲染。Actor类一般作于创建游戏角色,游戏物品等。Sprite继承了pygame.sprite,对原有的pygame的类进行了拓展,一般用于实现粒子特效,是粒子系统的基本类。Element类则是最为基本的渲染对象,用于创建UI控件,例如游戏中的按钮,滑动条等。所以很自然的选用Element类为我们控件的父类。

控件开发之旅--以开发一个滑动条为例

        首先我们可以在框架中轻易的写出开始的代码,如下图所示:

        这是一个非常简单的滑块类,它继承了sgf-py的Element类,这样渲染器就可以识别出该类是可渲染的。

        接下了就是更进一步的分析,Element类的初始化方法中必须传入一个矩形的类型参数,该矩形参数由一个4元组构成(矩形左上角x坐标,矩形左上角y坐标, 矩形长度,矩形宽度),所以自然的Slider类的长宽,位置应该也就固定了,但事实并不是这么简单,原因见下图:

        可以看到这是一个简单的滑动条,滑道的区域要比Element规定的区域小,并且左右都必须有一定的间隔,因为这种类型的滑条滑块的一部分是在滑道之外裸露的,比如该滑条值为最小时和值为最大时。导致这个情况的原因也显而易见,滑块的中心位置才是该滑动条要表达的值,这也符合人类的直观感受。

        所以,经过以上的分析后,我们可以得出滑动条类构造方法中还需几个必要参数:滑动条要表达的最大值和最小值,滑块的长宽,为了渲染的必要还要规定滑块的颜色,滑道的颜色。以上,看起来好像已经足够了,但是,不能忘记,我们是在游戏中创建一个滑动条的UI控件,所以必须更加使它贴近游戏内容,举个例子,比如下图所示:

        这个是一款avg游戏,心跳文学部(Doki Doki Literature Club)的设置页面,它有趣的滑动条UI为游戏增色不少。

        所以,我们的滑动条也要想这样,不能只是千篇一律的样式。解决这个问题也很简单,就是支持滑块和滑道自定义贴图。所以,我们必须加上与贴图有关的参数,代码如下图所示:

        sgf-py中的Img相关处理利用了pillow库,相关的方法也是借助pillow库实现的。们现在已经写好了最基本的相关代码,然后天加一些渲染方法,让我们看看是否可以显示在场景中, 完整代码如下图所示:

     以下是运行的效果图:

        到这一步,滑动条的显示是成功了,接下来要做的就是人机交互,作为一个基本的滑动条,它首先要可以滑动。与场景的消息处理相关的步骤交给ioEvent3组件完成,我们在这里只考虑逻辑。

        鼠标拖动滑块,意味着该控件检测到鼠标位于滑块区域,且鼠标左键按下处于长按的状态,同时,记录滑块中点的位置,作为其要表达的值。

        代码如下:

        在构造方法中添加事件

        滑动方法的代码如下:

        运行效果如下gif所示:

        到这一步,控件的渲染和最基本的交互现在已经差不多完成了,接下来是完善它的功能,例如反映该滑块所要表达的值。

        首先,要明确滑动条反映的值,必须明确一个最基本的单位1。比如一个滑动条,滑道长度为1000像素单位,而它所表达的值区间是[0, 100],故可知他的单位1为1000 / (100 - 0) = 10, 即每滑动10个像素单位,该滑动条要表达的值+1。

        那么问题也就来了,如果滑块中心在滑道上的位置离起始点的距离为5个像素单位,那该控件要表达的值为多少呢?是0还是1?再比如距离为995个像素单位,那值是99还是100?仔细思考不难发现这个问题的答案均可以,这里按第一种来,即距离不超过10个像素单位不会+1。

        按照这个思路修改代码(如下图):

        滑动函数和获取值的函数:

        运行效果如下gif所示:

        到这里差不多就已经大功告成,可以更换一些有趣的贴图达到不一样的效果,另外还有竖着的滑动条,起点在右的滑动条,只显示5的倍数值的滑动条等,这些的思路一样,有的换个参数,有的继承该类重写该类的方法,有的改变一下事件的逻辑就可以了。

        有了这样一个控件,再以后的开发中直接就可以拿来使用了。

        综上,这篇文章介绍了一个简单控件的开发,只要按照相同的思路一步步写下来,利用Element类和sgf-py开发任何常见的简单控件都是非常简单的。例如,按钮,进度条,多选框等等。

        拖了这么久更新,终于忙完考研的事了,未来3年应该有足够多的时间来研究我所想做的事情了,希望在读研期间我能完善这个框架,让他支持3d,2d和主流的渲染功能。让这个系列文章监督着我完成我最初的梦想,希望我以后不忘初心。

推荐文章
评论(0)
分享到
转载我的主页