游戏中的Unicode输入处理

3

我有一个游戏需要允许玩家通过网络相互聊天。一切都很好,但是当玩家输入Unicode字符时会有问题。

因此,这个问题可以分成两个部分:

  • 当玩家输入时,我如何捕获输入? 我之前通过游戏输入处理(轮询)已经实现过这个功能,但是它不像Windows Forms那样响应迅速。

  • 在将输入内容转化为字符串后,如何使用TrueType字体输出? 我问这个问题的原因是通常情况下,我会在游戏开始时从所有使用的文本构建位图字体。但对于Unicode输入,几乎需要10k个字符,这几乎无法在游戏开始时构建完成。

P.S. 我的目标输入语言更加具体,包括中文、韩文和日文。

5个回答

8

输入处理

  1. 使用SDL_EnableUNICODE来启用Unicode输入处理。
  2. 像往常一样接收SDL_KeyboardEvent
  3. 使用SDL_keysym中的unicode成员来获取Unicode字符。

渲染处理

如果所需字体尺寸相对较小,例如16px,您可以将所有文本都渲染到单个纹理上。在此尺寸下,您可以在1024x1024的纹理上装载至少4096个字形,当您密集地打包它们时,可以获得更多空间(参见fontgen的示例代码)。这应该足够满足常见聊天需求,但不足以适应TTF文件中的所有字形。

如果您不想使用更大的纹理尺寸,则必须按需生成字形纹理,只需像往常一样创建纹理,然后使用glTexSubImage2D将新的字形上传到纹理即可。

另一种选择是不使用字形纹理,而是使用文本本身的纹理。这样您就可以避免字形生成产生的所有麻烦。但对于非静态可编辑文本来说,这可能不是一个好主意。


非常感谢!我已经思考了很长时间了。干杯! - Roy

0

这里有一些代码展示如何使用SDL捕获键盘输入。

首先,您需要通过调用EventPoll从SDL查询键盘输入。 您可以在准备处理输入时或定期以固定间隔执行此操作,并将键和键盘状态存储在内部表中。

void EventPoll (ulong mask)
{
SDL_Event event;
while (SDL_PollEvent (&event)) {
   switch(event.type) {
      case SDL_KEYDOWN:
         KeyHandler (reinterpret_cast<SDL_KeyboardEvent*> (&event));
         break;
      case SDL_KEYUP:
         KeyHandler (reinterpret_cast<SDL_KeyboardEvent*> (&event));
         break;
      // handle other events
      }
   }
}

void KeyHandler (SDL_KeyboardEvent *event)
{
   SDLKey      keySym = event->keysym.sym;
   wchar_t     unicode = event->keysym.unicode;
   int         keyState = (event->state == SDL_PRESSED);

// process key info, e.g. put key into a buffer and 
// store keyboard state 
}

这里有一个链接,描述了使用OpenGL渲染文本的方法:http://www.opengl.org/resources/features/fontsurvey/

你可能想要做的是捕获键盘输入,并使用预加载的正确字体实时渲染它。


0
当玩家输入时,我该如何捕获输入?
这取决于你使用什么。我不熟悉SDL。在Linux上,您可以使用标准的X函数和事件循环,它运行良好(例如在Quake中使用;因此应该足够响应)。
将输入捕获到字符串后,如何使用TrueType字体输出?
您应该查看FreeType2库。它允许您加载TrueType字体,并检索任何字符的字形(图像)。
但是对于Unicode输入,需要近10k个字符,这几乎不可能在游戏开始时构建。
我有同样的问题。我想MRU(最近使用)字符缓存管理器会起到作用。比简单静态位图复杂一些。

0

我自己没有进行过游戏开发,所以对于那里的工作原理只有一个模糊的概念,但是这是我的两分钱意见:

不要在程序开始时缓存所有字形。相反,当您需要显示聊天字符串时,即时将整个字符串渲染到一些新纹理中。将此纹理保留在内存中,直到不太可能再次需要它为止(例如,在聊天窗口关闭后)。也许当聊天窗口更新时,您可以重新渲染整个聊天窗口 - 那么您只需要担心一个纹理。


0
就显示而言,我在这个教程中描述的缓存系统方面运气非常好,它被转换成了C++。
对于字体,GNU Unifont具有完整的BMP字形覆盖范围,并以便捷的TTF格式提供。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接