字符串逐字刷新

开发日志系列(十五)

在做游戏剧情展示的时候遇到一种需求把游戏对话逐字显示给玩家,效果如下:

malu

实现这种效果的方式就是把一个字符串逐个中文取出来刷新到屏幕上,研究了各种编码之后发现UTF8的编码非常简单 也很容易逐个/中文/英文/符号 读取.首先看看UTF8非常简单的编码方式:

  1. 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
  2. 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

UTF8编码规则

Unicode符号范围 UTF-8编码方式
(十六进制) (二进制)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

按照规则可以使用如下算法算出一个中文所占的字符:

/// 获取utf8字符长度
int getUtf8Length( const char* pszutf8 )
{
    if( pszutf8 == NULL )
    {
        return 0;
    }

    for( int i = 8; i > 0; --i )
    {
        unsigned char c = 1 < < (i - 1);
        if( ( pszutf8[0] & c ) != c )
        {
            if( i == 8 )
            {
                return 1;
            }
            else
            {
                return 8 - i;
            }
        }
    }

    return 1;
}

void Main()
{
    std::string strSrc = "我在马路边";
    if( strSrc.empty() )
    {
        return;
    }
    size_t size = strSrc.length();
    for( size_t i = 0; i < size; )
    {
        const unsigned char c = strSrc.at(i);
        int len = getUtf8Length((const char*)&c);

        i += len;

        std::string strTemp = strSrc.substr( 0, i );
        printf("%s\n",strTemp.c_str());
        
    }
}

打印出来可以看到:

我
我在
我在马
我在马路
我在马路边

基本实现想要的展示效果.但是要求是必须输入的字符串是UTF8格式..

参考文章

  1. 字符编码笔记:ASCII,Unicode和UTF-8
  2. 字符编解码的故事
  3. 纯LUA的UTF8字符串截断方法

《字符串逐字刷新》有一个想法

crazyit进行回复 取消回复

邮箱地址不会被公开。 必填项已用*标注