[C++] 247 SDL : 画面に記号を表示する ChatGPT

[M1 Mac, Monterey 12.6.3, clang 13.0.0, SDL 2.26.2, ChatGPT Plus, NO IDE]

SDLアプリの初期画面に”Press □ to start”を表示させようとすると文字化けしてしまいます。

ChatGPTの回答の通りフォントを変えたりUnicode表記に変えても解決に至らなかったのですが、質問の仕方を変えてヒントを導き出しました。

TTF_RenderText_Blended()関数をTTF_RenderUTF8_Solid()関数に書き換えるだけでした。

ゲームコントローラーに関するコードを書かせてもデタラメだらけでしたが、公式ドキュメントがしっかりしているカテゴリーについてはそれなりのコードを書いてくれますね。

所要時間は30分程度でした。Google検索活用だったら2,3時間、下手したら半日以上掛かっていたかもしれません。

修正前
修正後
void Renderer::DrawText( const char* text, int x, int y, uint32_t rgba /*= 0xffffffff */ )
{
	SDL_assert( text );

	SDL_Color color = MakeSDL_Colour( rgba );

	SDL_Surface* pSurface = TTF_RenderUTF8_Solid(mFont, text, color);
	// SDL_Surface* pSurface = TTF_RenderText_Blended( mFont, text, color ); 旧コード

	SDL_Texture* pTexture = SDL_CreateTextureFromSurface( m_pSdlRenderer, pSurface );
	int width, height;
	SDL_QueryTexture(pTexture, NULL, NULL, &width, &height);
	SDL_Rect dstRect = { x, y, width, height };
	SDL_RenderCopy( m_pSdlRenderer, pTexture, nullptr, &dstRect );
	SDL_DestroyTexture( pTexture );
	SDL_FreeSurface( pSurface );
}

ChatGPT調査
Q1: SDLアプリの画面に□を文字化けさせずに表示させる方法を教えてください

SDLアプリで正しくUnicodeテキストを表示させるためには、以下の手順を行う必要があります。

  1. 必要なフォントをインストールする
  2. フォントをロードする
  3. テキストを描画する

まず、必要なフォントをインストールする必要があります。□を含むテキストを表示させるためには、Unicodeの範囲に含まれるフォントを使用する必要があります。例えば、Noto Sansフォントは多言語対応のフォントで、Unicodeの範囲に含まれる多くの文字をサポートしています。このフォントをインストールすることをお勧めします。

次に、フォントをロードする必要があります。SDL_ttfライブラリを使用して、フォントをロードできます。フォントをロードするには、まずTTF_Init()関数を使用してライブラリを初期化し、TTF_OpenFont()関数を使用してフォントファイルを開きます。以下は、フォントをロードするためのサンプルコードです。

if (TTF_Init() == -1) {
    printf("TTF_Init failed: %s\n", TTF_GetError());
    return false;
}

TTF_Font* font = TTF_OpenFont("path/to/font.ttf", 24);
if (!font) {
    printf("TTF_OpenFont failed: %s\n", TTF_GetError());
    return false;
}

最後に、テキストを描画する必要があります。TTF_RenderUTF8_Solid()関数を使用して、テキストをサーフェスにレンダリングし、それをテクスチャに変換してレンダラーに描画することができます。以下は、テキストを描画するためのサンプルコードです。

SDL_Surface* surface = TTF_RenderUTF8_Solid(font, "□", { 255, 255, 255 });
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_Rect rect = { 0, 0, surface->w, surface->h };
SDL_RenderCopy(renderer, texture, NULL, &rect);
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);

このコードでは、□をサーフェスにレンダリングし、それをテクスチャに変換してレンダラーに描画しています。

なお、フォントをロードする際に、フォントファイルのパスを正しく指定することが重要です。また、描画する前に、描画色を適切に設定する必要があります。

Q2: SDL_Surface* surface = TTF_RenderUTF8_Solid(font, “□”, { 255, 255, 255 }); SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); 
と以下のコードを統合させてください。
renderer.DrawText( “Press □ to start”, renderer.GetLogicalWidth()/2 – 100, renderer.GetLogicalHeight()/2, 0xffffffff );

以下のように、DrawText関数の内部に上記のコードを追加することができます。

void Renderer::DrawText(const std::string& text, int x, int y, Uint32 color)
{
    SDL_Surface* surface = TTF_RenderUTF8_Solid(m_font, text.c_str(), { 255, 255, 255 });
    SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer, surface);

    SDL_Rect dstRect = { x, y, surface->w, surface->h };

    SDL_SetTextureColorMod(texture, color >> 16, (color >> 8) & 0xff, color & 0xff);

    SDL_RenderCopy(m_renderer, texture, nullptr, &dstRect);

    SDL_DestroyTexture(texture);
    SDL_FreeSurface(surface);
}

このようにコードを変更すると、DrawText関数を呼び出すときに”Press □ to start”のように□を表示することができます。