自用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坑那么多,但是有什么办法,它就是屌啊(滑稽
酷