3

我有一个游戏要求我允许玩家通过网络互相聊天。一切都很好,除了玩家可以输入 Unicode 输入的部分。

所以,这个问题可以分为两部分:

  • 当玩家打字时,我如何捕捉输入?我之前通过游戏输入处理(轮询)完成了此操作,但是,它不如 Windows 窗体之类的响应速度快。

  • 将输入捕获到字符串后,如何使用 TrueType 字体输出?我问这个的原因是因为通常我会在游戏开始时从游戏中使用的所有文本构建位图字体。但是使用 unicode 输入,需要将近 10k 个字符,这在游戏开始时是完全不可能构建的。

PS 我的目标输入语言更具体为中文、韩文和日文。

4

5 回答 5

8

对于输入

  1. 使用SDL_EnableUNICODE启用 unicode 输入处理
  2. 像往常一样接收SDL_KeyboardEvent
  3. 使用SDL_keysymunicode的成员 获取 unicode

用于渲染

如果所需的字体大小相当小,比如 16 像素,您实际上可以将其全部渲染为单个纹理,您可以在该大小的 1024x1024 纹理上放置至少 4096 个字形,当您将它们紧密打包时会更多(参见fontgen例如代码)。这对于普通聊天应该足够了,但不足以适应 TTF 文件的所有字形。

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

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

于 2009-09-10T13:37:22.027 回答
0

当玩家打字时,我如何捕捉输入?

这取决于你用什么我猜。我对 SDL 不熟悉。在 Linux 上,您可以使用标准的 X 函数和事件循环,它运行良好(例如在 Quake 中使用;所以它应该足够反应)。

将输入捕获到字符串后,如何使用 TrueType 字体输出?

你应该看看 FreeType2 库。它允许您加载 TrueType 字体,并检索任何字符的字形(图像)。

但是使用 unicode 输入,需要将近 10k 个字符,这在游戏开始时是完全不可能构建的。

我也有同样的问题。我猜一个带有 MRU(最近使用的)字符的缓存管理器可以解决问题。不过,我比简单的静态位图要复杂一些。

于 2009-09-10T05:45:42.660 回答
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/

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

于 2009-09-10T10:33:16.657 回答
0

我自己没有做过游戏开发,所以我对那里的工作方式只有一个模糊的概念,但这是我的 2 美分:

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

于 2009-09-10T12:18:14.347 回答
0

就显示而言,我对本教程中描述的缓存系统非常幸运,音译为 C++。

对于字体,GNU Unifont具有完整的BMP字形覆盖,以方便的 TTF 形式提供。

于 2009-09-10T14:24:29.163 回答