HOWTO · Pygame

Pygame でテキストを表示する

Pygame でフォントを作成し、文字列をサーフェスに描画して、ゲームループ内で画面に表示する方法を、実行できる Python の例とともに解説します。

このページの内容

Pygame でテキストを表示するには、フォントを作成し、文字列をサーフェスにレンダリングしてから、そのサーフェスを blit() で画面に描画します。変化しないラベルなら、ゲームループの前に一度だけレンダリングします。各フレームでは画面を消去し、テキストを描画し、イベントを処理して、画面を更新します。以下の完全な例はウィンドウも作成するため、そのまま調整して使うことも、テキスト描画の手順だけを既存のゲームに組み込むこともできます。ウィンドウの最小構成を確認したい場合は、こちらの記事も参照してください。

Pygame でフォントを作成する

フォントオブジェクトの作成には、よく使われる方法が2つあります。pygame.font.Font はパスで指定したフォントファイルを読み込みます。第1引数に None を渡すと、Pygame 組み込みのデフォルトフォントを使います。独自のファイルを指定する場合、そのパスからプログラムが読み込めるフォントファイルが必要です。一方、pygame.font.SysFont は名前を指定して、システムにインストールされたフォントを探します。フォントファイルを同梱したくない場合に便利です。

どちらのコンストラクターでもサイズはポイント単位で指定します。たとえば、pygame.font.Font(None, 36) はデフォルトフォントを36ポイントで作成し、pygame.font.SysFont("arial", 36) は Arial がインストールされていればそれを36ポイントで指定します。どちらか一方を選び、返されたフォントオブジェクトを使います。完全な例では別のファイルを用意せずに済むよう、デフォルトフォントを使用します。

テキストをレンダリングしてゲームループで描画する

フォントオブジェクトの render() に、文字列、アンチエイリアスを有効にするかどうかを表す真偽値、色を渡します。たとえば、font.render("Score: 10", True, (255, 255, 255)) のように呼び出します。アンチエイリアスを True にすると、文字の縁が滑らかになります。色は RGB タプルで指定し、各チャンネルの値は0から255です。render() が作るのはテキストを含むサーフェスであり、この呼び出しだけではウィンドウに文字は表示されません。screen.blit(text_surface, (x, y)) を呼ぶと、サーフェスの左上が (x, y) にくるように描画できます。その後、画面を更新します。

変化しないテキストは、同じ文字列を毎フレームレンダリングしないよう、ループの外でサーフェスを作成します。表示する値が変わったときは新しいサーフェスをレンダリングし、各フレームではそのサーフェスを blit() します。テキストを中央に配置するには、レンダリングしたサーフェスの矩形を取得し、その中心を画面の中心に合わせます。このように、テキストの作成と描画を分けることで、同じサーフェスを効率よく再描画できます。

テキスト表示の完全な例を実行する

次の例は Pygame を初期化し、640×360ピクセルの画面を作成します。挨拶文は一度だけレンダリングして中央に配置し、暗い背景の上に描画しながらイベント処理と画面更新を行います。プレビューはウィンドウを閉じるか、5秒経過すると終了します。ゲームに組み込む場合はプレビュー用タイマーを削除し、プレイヤーが終了するまでループを続けてください。固定テキストはループの前に一度だけレンダリングします。

import os
import warnings

os.environ.setdefault("PYGAME_HIDE_SUPPORT_PROMPT", "1")
os.environ.setdefault("SDL_AUDIODRIVER", "dummy")
runtime_dir = os.environ.get("XDG_RUNTIME_DIR")
wayland_ready = bool(
    os.environ.get("WAYLAND_DISPLAY")
    and runtime_dir
    and os.path.isdir(runtime_dir)
    and os.access(runtime_dir, os.R_OK | os.W_OK | os.X_OK)
)
if os.name != "nt" and not wayland_ready and (
    not os.environ.get("DISPLAY")
    or os.environ.get("WAYLAND_DISPLAY")
    or not runtime_dir
    or not os.path.isdir(runtime_dir)
    or not os.access(runtime_dir, os.R_OK | os.W_OK | os.X_OK)
):
    os.environ.setdefault("SDL_VIDEODRIVER", "dummy")
warnings.filterwarnings(
    "ignore",
    message="Your system is avx2 capable.*",
    category=RuntimeWarning,
)

import pygame

pygame.init()
screen = pygame.display.set_mode((640, 360))
pygame.display.set_caption("Text in Pygame")
font = pygame.font.Font(None, 40)
text_surface = font.render("Hello, Pygame!", True, (255, 255, 255))
text_rect = text_surface.get_rect(center=screen.get_rect().center)
clock = pygame.time.Clock()
preview_done = pygame.USEREVENT
pygame.time.set_timer(preview_done, 5000)
running = True
while running:
    for event in pygame.event.get():
        if event.type in (pygame.QUIT, preview_done):
            running = False

    screen.fill((30, 30, 30))
    screen.blit(text_surface, text_rect)
    pygame.display.flip()
    clock.tick(60)
pygame.quit()
print("Text preview finished.")
Text preview finished.