cp的小屋

not yet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

                                       

   
 图1   图2
   
图3  图4
                                                           
    在游戏聊天文本框中支持类似QQ的表情动画以及各种转义符号已经成为网络游戏的必然选择,表情动画
大家都很熟悉,转义符号是指在文本中嵌入一些特殊字符以表示文本属性或者一些特定的输出控制。其实表情动画也是通过转义符号表示的,只不过你不必直接输入这些转义字符,而是通过在表情列表框中选择表情,系统自动帮你输入这些符号。举例来说,用#R、#G、#B表示后面的文字分别以红、绿、蓝颜色显示,#b表示后面的文字闪烁,#n表示把后面的文字属性恢复到默认值,#加三个数字表示特定的表情符号,如#001表示一号表情,比如是一个笑脸。

    实现一个这样的聊天文本框对于程序员来说是一个不大不小的挑战。要解决的问题包括转义符号的解析,正确计算文本及表情宽度实现自动换行,在文字和表情不等高时正确计算行间距,在文本内容超过文本框所能显示的范围时正确显示视口内的文本部分,甚至要支持多种不等尺寸的字体和表情混排。

    本文不讨论实现这些特性的所有细节,只介绍支持这些特性的关键数据结构。

    文本框的内容由一组行对象组成,每个行对象代表文本框中的一行,行对象可以保存在链表或者动态数组中。行对象本身并不可见,它是保存一组可视对象的容器。可视对象分为两类,文本对象和表情对象,它们派生自同一个基类,它们只有一个共同属性就是自身所占的矩形区域。文本对象中保存了对应的字符串、文本颜色、是否闪烁等内容,更复杂的设计还可以包含字体信息。表情对象保存了表情ID,表情当前动画时间,用于计算动画帧。可视对象保存在行对象内,也可以通过链表或动态数组保存。行对象也有一个矩形区域的属性,这个区域是包括了行对象保存的所有可视对象矩形区域的包围盒。显然行对象的高度是由本行所有可视对象中高度最高的对象决定。可视对象的矩形区域都是相对于所在行对象的,并非是在屏幕上的绝对坐标,这也是界面元素表示坐标的通常做法,方便了控件移动,以及控件内容的滚动。

    这个系统最复杂的部分就是将加入文本框的文本串分解成行对象和行对象所包含的可视对象的过程。需要注意的是文本属性的每一次变化(如改变颜色、闪烁或者字体)都要生成一个单独的文本可视对象。这个过程由一个Build(...)函数处理全部的复杂性,它将一个新加入的文本字符串变成行对象和可视对象插入到系统中。有了上面介绍的数据结构,这个过程已经变得非常清晰。

图1:加入文本框的所有内容,可以看到有表情的行的高度被表情对象撑大了,没表情的行间距比较小。

图2:控件实际显示的内容,是控件全部内容被控件边框所裁减,显示在文本框视口内的内容,为所有内容的一个部分,可通过上下滚动浏览全部内容

图3:经Build(...)函数分解为行对象和可视对象的一段文字,黑色边框表示行对象,亮蓝色边框表示文本对象,亮紫色边框表示表情对象。
       同时可以看到,由于采用了比图1、图2大一点的字体和不同的控件宽度,自动换行的位置已经发生了变化,这同样影响到行对象和可视对象的分解。

图4:图3局部放大,更清晰地显示了行对象、文本对象和表情对象

图中被解析字符串解析前的内容如下:
“    新浪财经讯#001 20号晚间#G证监会#n突然召开新闻发布会,公布#Y《上市公司解除限售存量股份转让指导意见》#n#020,对备受市场关注的股改限售股解禁进行规范。#002
其中#001、#G、#n、#Y、#020、#002都是转义符号。

posted on 2008-04-21 22:46  cproom  阅读(3572)  评论(7编辑  收藏  举报