gamemaker吧 关注:13,580贴子:94,369
  • 13回复贴,共1

gms2 中文文本自动换行实现

只看楼主收藏回复

今天在做对话框的时候,想要实现一个文本超长自动换行的效果。结果试了半天,发现gms2的draw_text_ext()函数的换行居然是基于空格实现,对中文极度不友好。去git找了半天也没找到啥中文能用的、好用的扩展或者脚本。无奈只好自己造轮子了。
暂时想不到更好的办法,权当抛砖引玉了。
以下是代码:
=====================分隔符=========================
// 绘制文本且自动换行
function draw_txt_ext(_x, _y, _text, _sep, _width) {
// 文本高度
var _text_h = 0;
// 文本长度
var _len = string_length(_text);
// 截取长度
var _j = 1;
//
var _i = 1;
repeat _len {
var _cut = string_copy(_text, 1, _j);
// 循环结束,绘制剩余文本
if _i == _len {
draw_text(_x, _y + _text_h, _text);
_text_h += _sep;
}
// 处理换行符
else if string_count("\n",_cut) > 0 {
_cut = string_replace(_cut, "\n", "");
draw_text(_x, _y + _text_h, _cut);
_text = string_delete(_text, 1, _j);
_text_h += _sep;
_j = 1;
}
// 文本超长时。
else if string_width(_cut) > _width {
var _pre_j = _j - 1;
while is_letter(string_ord_at(_cut, _pre_j)) {
if _pre_j == 0 break;
_pre_j--;
}
if _pre_j == 0 _pre_j = _j - 1;
_j = _j - _pre_j;
_cut = string_copy(_text, 1, _pre_j);
draw_text(_x, _y + _text_h, _cut);
_text = string_delete(_text, 1, _pre_j);
_text_h += _sep;
}
_j += 1;
_i += 1;
}
// 返回最终文本高度
return _text_h;
}
// 判断字符是否是英文字母
function is_letter(_byte) {
return (_byte >= string_byte_at("a",1) && _byte <= string_byte_at("z",1))
|| (_byte >= string_byte_at("A",1) && _byte <= string_byte_at("Z",1));
}
========================分隔符========================
姑且实现了中文换行,英文分词,以及超长英文单词的短横杆连接。
以下是效果图



IP属地:四川1楼2024-04-12 03:41回复
    中文换行貌似是个很复杂的工程,之前看过WORD还是啥的开发介绍过里边的水有多深。
    原文没有提到的是怎样防止一个字的两个字节中间拆开,特别是半角/全角混用的时候;//只要不是逐字节读取再找字表的模式,应该不再涉及这个问题
    第一件事是标点不能放在一行的开始,例外是引号/书名号这类成对出现标点的左半边,它们不能出现在行尾;//这个麻烦一些,不过应该还能在GM里写
    第二件事是当一行确实刚好堆满字的时候,是多折一个字到下一行还是让当前行紧凑一点塞下半个字符宽度的标点的选择;//这个会更麻烦,要判定本行有没有可以挤一挤的标点什么的,很费力但不是完全不能做
    第三件事是怎样避免逻辑上的一个整词被换行给拆开;//要实现这个基本就需要词库/校对工具之类的东西做支持了
    比起这个,咱倒是构思过文本显示的打字机特效,怎样防止一个字先打在行尾,又在增加了一个逗号的时候被一起切到了下一行,好像没想出啥有效的方案就想别的模型去了。


    IP属地:北京2楼2024-04-12 13:44
    收起回复
      gms2还自带换行的嘛
      为了实现富文本效果用的是for循环逐字打印,很多自带文本功能都用不了


      IP属地:上海来自Android客户端3楼2024-04-14 12:00
      收起回复