自用Gamemaker小脚本:关键词超链接
最近开始继续写一些诺娃模拟的东西,其中包括一个终端聊天系统,然后遭遇一个需求:关键词超链接。效果是在一段文本中,给一些特殊设定的关键词加个超链接或者悬停效果。这个东西在网页里头很常见,在很多悬疑推理类AVG(提取文本资料中的线索)里也有应用。
在gamemaker里肯定没这个原生功能。很简单地搜索了一下也没指望能找到现有的解决方案,毕竟这个功能很小,所以就自己写一个简单的,也许以后准备做avg还能用上(并不。
大概实现思路是,在文本中插入“$”类似的占位符,在设置关键词的时候用来定位,实际打印的时候就无视。定位了关键词的首尾位置之后就可以得到实际绘制以后这个关键词所在的相对位置[1]。之后就可以根据此来设置一个感应按钮。这个感应按钮直接在step里判断鼠标碰撞,里面的内容包括相对位置和关键词的所有信息。我这里用了一个map结构来做词典,拿到关键词以后就能得到关键词的所有信息。我简单的实现了鼠标悬停出注释,实际上还可以有更多用法。
[1]:具体方法见代码(不一定好读懂。因为使用draw_text_ext的时候,gm会自动强制换行,所以先用末尾定位行数,然后往前找到换行处,得到所在行的位置
最后是一个简单的实现效果(对话系统是自用的一个简单事件跳转系统,avg里估计用不上,主要是用来发系统通知用的)。:
下面是参考代码
///@function string_set_hyperlink var lx = argument0; var ly = argument1; var str = argument2; var sep = argument3; var w = argument4; while (string_pos("$",str)!=0){ //偏差值,根据实际字体酌情修改 var offset_x = 6; var offset_y = 10; //定位关键词首尾的占位符位置 var p1 = string_pos("$",str); str = string_replace(str,"$",""); var p2 = string_pos("$",str)-1; str = string_replace(str,"$",""); //利用关键词首尾在文本中位置,计算其绘制的相对位置 var x1 = 0; var y1 = string_height_ext(string_copy(str,1,p2),sep,w); var tempp = p2; while (tempp>0 && string_height_ext(string_copy(str,1,--tempp),sep,w)==y1){}; if (string_height_ext(string_copy(str,1,p1),sep,w)==y1){ x1 = string_width_ext(string_copy(str,tempp+1,p1-tempp),sep,w)-string_width_ext(string_copy(str,p1,1),sep,w); } y1 -= offset_y; var keyword = string_copy(str,p1,p2-p1+1); var x2 = x1 + string_width_ext(keyword,sep,w); var y2 = string_height_ext(string_copy(str,1,p2),sep,w); //debug的时候可以画一个识别框,用来根据字体进行微调 //draw_rectangle_color(lx+x1,ly+y1,lx+x2,ly+y2,c_dkgray,c_dkgray,c_dkgray,c_dkgray,true); var link_inst = instance_create_layer(0,0,"Hyperlink",obj_message_hyperlink); with (link_inst){ self.x1 = lx+x1; self.y1 = ly+y1; self.x2 = lx+x2; self.y2 = ly+y2; self.keyword = keyword; self.twin = noone; self.desc = global.kwdic[? string_lower(keyword)] } }
然后是文本数据和相应字典的格式参考
"Hello, $captain$. How can I help you today?" "$Nova 9000$." "$IDNV Spirit Director X-927$. $Sol System$." "Indienova is based in China and trying to help $indiegame$ developers from all over the world to publish their games to Chinese market." dic[? "captain"] = "oh captain, my captain" dic[? "nova 9000"] = "special assistant of this spaceship" dic[? "idnv spirit director x-927"] = "spaceship for making indiegames, owned by indienova" dic[? "indiegame"] = "indiegame is indiegame" dic[? "sol system"] = "The Solar System is the gravitationally bound system comprising the Sun and the objects that orbit it, either directly or indirectly Of those objects that orbit the Sun directly"
总结一下,gms的gui实现是个大坑,自己做的时候还是应该结合项目量力而为。主要很多很小很特殊的功能,可能用别的引擎的时候没什么难度,进到gms可能就会很麻烦。像这个关键词超链应该大部分人想想就能写出来不同的实现,但是实际上就比较浪费时间,我也是之前踩了一个draw_text_ext的坑之后才改对的。所幸gms的体量很小,所以多么鬼畜的实现途径基本都是可以容忍的。
虽然gms坑那么多,但是有什么办法,它就是屌啊(滑稽
[ 分享 ]写轮眼小作业·最近在GMS2里写的一个几何动画系统雏形
INSPIRATION:不愿意透露姓名的船长上个礼拜在精董群里发了一个https://aidn.jp/mikutap/,是H5实现的一个按键音+MG动画,看完之后就想通过GMS2来实现一下,上个礼拜花了周六一天督促团队的程序做了个简单的原型。
首先看看GMS的基础图形绘制系统,只有线,三角,矩形,圆,很是寒酸,唯一有用的是自带的着色系统。既然直图(折线,多边形)和弯图(圆)两个系统肯定是分开做的(实际上弯图远比直图简单),下面先分析一下需要哪些参数。
直线形主要是:锚点,顶点集合,大小,角度,颜色(含透明度),线宽,这几个都是数值上直接改变直线形的参数。还有两个参数,一个是outline(轮廓),就是区分是否是一个填充的图形;另一个是connect(连接),就是点集的第一个点和最后一个点是否相连。
那么就开始写,笃笃笃笃笃笃笃笃笃笃笃笃,写完了。
然后研究了一下图形,发现还缺少两个系统。首先是修建路径(就是线条嗖嗖嗖过去像画画一样),这个需要定义一个线条的开始比例和结束比例,然后通过变化开始比例和结束比例就能画出一条线条的一部分。其次是仅仅用一个角度来定义物体的旋转是不够的,因为这个旋转只是旋转中心在物体中心的特殊情况,所以需要另外一个旋转动作数组,每一个旋转动作包括旋转中心(相对锚点)和旋转角度。
之后就是很麻烦的迭代,但是逻辑上是没难点的,继续笃笃笃笃笃笃笃笃笃笃笃笃。顺便插一句,我在做的过程中,线条的开始结束比例都是可以大于1的(本身按比例的话,应该是(0,1)范围内),在处理的时候再单独判断。这是因为之后处理帧渐变的时候,需要考虑一个特殊情况,比如一个线段从0.2的部分开始,转一圈,那么结束的位置应该是1.2,也就是从(0.2,0.2)到(0.2,1.2)。写的有点啰嗦,不过这是一个简化操作的手段,如果有人看了想写可能也会想到这个问题。
直系都做完了,弯系就没有难点了。除了一些位置参数可以复用直系以外,弯系的主要点就是弧度(也就是画扇形和圆弧)。我找了半天发现GMS是没有自带画扇形圆弧的函数的,所以就只能自己写,方法就是很简单的割圆,GMS绘图的特殊性,我一开始割了360,出现了因为线窄间隙宽导致的花图,后来就割了1800。另外,我判断了一下弧度,如果画的是整圆,就还是用自带的函数,因为割圆绘图在GMS效率极低,同时出现6-7个就卡的不行,所以这里的弧度变换一般就只给一个扇面顺逆时针效果。
之后就是最激动人心的k帧环节。用ds map写了一套关键帧系统,基本上包括了上述的参数的变换,然后新建一个object,每一个step放进去关键帧的变换,齐活。关于动画曲线我直接抄了一个git库:https://github.com/zhangxinxu/Tween,实际上平时用一下线性的就差不多够了。
中间很多几何必需的小函数也写了点,但是都是很基础的,远没有求xxx的xxx,求xxxx和xxx的xxx这种需求这么麻烦。
如果要再强化的话,比如路径位移(目前只是锚点之间线性移动),碰撞处理什么的都是有生之年。不过实际上GMS的绘图小水管,让我对它画这个东西效率很是疑惑,如果再加入碰撞,那就更糟心了。
后来程序又用u3d的mesh实现了一套一样的,在u3d里实现碰撞效果可能简单一些。
至于这个系统开发的用处,可能聪明的你早就想到了,对,没有错,这是外包的一个儿童早教系统,专门教3-5岁的学龄前小朋友认识图形和颜色。
三流独立做打架,二流独立做啪啪,一流独立做爸妈,为自己鼓掌。
[ 求助 ]一个小水坑
今天在Gamemaker Studio 2 H5平台上踩的一个小水坑。一般我都会用int64取整,但是在H5里执行后int64是无效的,所以最好用floor,round来取整,他们是有效的。