PYXEL GUIDE / TEXT

Pyxelで日本語を表示する方法

公開日: / Pyxel 2.9.9 の公式ドキュメントとソースで確認

pyxel.text(10, 10, "こんにちは", 7) と書いても、画面には何も表示されません。エラーも出ないので、迷いやすいところです。日本語フォントを読み込めば、Pyxelでも日本語を表示できます。

結論
pyxel.Font で日本語フォントを読み込み、pyxel.text の5番目に渡す
使えるフォント
BDF・OTF・TTF・TTC 形式
確認したバージョン
Pyxel 2.9.9
日本語の文字が表示されたPyxelのゲーム画面
このサイトの講座「ことばの橋」の元の完成版。Pyxelの画面に、日本語の説明や操作方法を表示しています(元の完成版を自動操作したPyxel描画)。

なぜ日本語が表示されないの?

Pyxelには、最初から1つのフォント(標準フォント)が入っています。1文字が横4×縦6ドットの小さなフォントで、収録されているのは半角の英数字と記号(ASCII)だけです。

標準フォントにない文字は、エラーにならずに読み飛ばされます。そのため、日本語の部分だけが表示されない、という状態になります。

標準フォントで描いた場合
# 表示される
pyxel.text(8, 8, "SCORE 100", 7)

# 何も表示されない
pyxel.text(8, 16, "こんにちは", 7)

# 「HP:3 」だけが表示される
pyxel.text(8, 24, "HP:3 ハート", 7)

日本語を表示するには、日本語の文字が入ったフォントファイルを読み込み、「このフォントで描く」と指定します。手順は次の3つです。

  1. 日本語フォントのファイルを用意する
  2. pyxel.Font でフォントを読み込む
  3. pyxel.text の5番目に、読み込んだフォントを渡す

日本語フォントを用意する

いちばん手軽なのは、Pyxelの公式サンプルに入っている日本語フォントを使う方法です。サンプルをコピーするコマンドを実行すると、pyxel_examples/assets フォルダーに、次のフォントが入ります。

公式サンプルに入っている日本語フォント
ファイル名形式文字の大きさ
umplus_j10r.bdfBDF(ドット絵のフォント)10ドット
umplus_j12r.bdfBDF12ドット
PixelMplus10-Regular.ttfTTF10ドット向け
PixelMplus12-Regular.ttfTTF12ドット向け

ここでは、いちばん扱いやすい umplus_j10r.bdf を使います。

手順

まず、はじめる準備と同じように、新しいフォルダー(例:jp_game)に .venv を作って Pyxel を入れます。そのフォルダーでターミナルを開き、次のコマンドを1行ずつ実行します。1行目でサンプルをコピーし、2・3行目で assets フォルダーを作ってフォントをコピーします。

Windows(PowerShell)
.venv\Scripts\python.exe -m pyxel copy_examples
mkdir assets
copy pyxel_examples\assets\umplus_j10r.bdf assets\
macOS / Linux
.venv/bin/python -m pyxel copy_examples
mkdir assets
cp pyxel_examples/assets/umplus_j10r.bdf assets/

コピーは、エクスプローラーや Finder で行ってもかまいません。次のような形になっていれば準備完了です。

フォルダーの形
jp_game/
├─ .venv/
├─ main.py            ← これから作るファイル
├─ assets/
│  └─ umplus_j10r.bdf ← コピーした日本語フォント
└─ pyxel_examples/    ← 公式サンプル(フォントをコピーしたら削除してよい)
コピーが終わったら、サンプルのフォルダーは消してよい

pyxel_examples フォルダーは、フォントを取り出すためのコピー元です。残したままゲームを pyxel package でまとめると、サンプルのファイルまで一緒に入ってしまいます。フォントをコピーしたら、エクスプローラーや Finder で pyxel_examples フォルダーを削除しましょう。また、copy_examples をもう一度実行すると pyxel_examples フォルダーは作り直されるので、中のファイルを書きかえて使うのはやめましょう。

フォントを読み込んで表示する

jp_game フォルダーに main.py を作り、次の全文を貼り付けて保存します。

main.py / 全文
import pyxel


def text_with_border(x, y, s, col, border_col, font):
    for dx in (-1, 0, 1):
        for dy in (-1, 0, 1):
            if dx != 0 or dy != 0:
                pyxel.text(x + dx, y + dy, s, border_col, font)
    pyxel.text(x, y, s, col, font)


class App:
    def __init__(self):
        pyxel.init(160, 120, title="Japanese Text")
        self.font = pyxel.Font("assets/umplus_j10r.bdf")
        pyxel.run(self.update, self.draw)

    def update(self):
        pass

    def draw(self):
        pyxel.cls(1)
        pyxel.text(8, 8, "こんにちは", 7)
        pyxel.text(8, 24, "こんにちは、Pyxel!", 7, self.font)
        message = "まんなかに表示"
        w = self.font.text_width(message)
        pyxel.text((pyxel.width - w) // 2, 56, message, 10, self.font)
        text_with_border(8, 88, "ふちどり文字", 7, 0, self.font)


App()
Windows
.venv\Scripts\python.exe main.py
macOS / Linux
.venv/bin/python main.py
できた目印紺色の画面に、白い「こんにちは、Pyxel!」、黄色の「まんなかに表示」、黒いふちの付いた「ふちどり文字」が出れば成功です。いちばん上の行には何も表示されません。

ポイント

  • pyxel.Font("assets/umplus_j10r.bdf") でフォントを読み込みます。BDF形式は文字の大きさが決まっているので、大きさの指定はいりません。
  • 読み込みは pyxel.init のあとに書きます。Pyxelは init のときに、作業する場所をそのPythonファイルがあるフォルダーに切りかえます。init のあとなら、"assets/..." のように、ファイルの場所からの相対パスで指定できます。
  • フォントは毎フレーム読み込まず、__init__ で1回だけ読み込んで self.font に入れておきます。
  • 描くときは pyxel.text(x, y, 文字, 色, self.font) のように、5番目にフォントを渡します。
  • 1行目の pyxel.text(8, 8, "こんにちは", 7) はフォントを渡していないので、何も表示されません。比べるために残しています。

中央寄せ・ふちどり・改行

中央に表示する

self.font.text_width(文字) で、その文字を描いたときの幅(ドット数)がわかります。画面の幅から文字の幅を引いて2で割ると、中央に置くための x になります。

main.py の中央寄せの部分
message = "まんなかに表示"
w = self.font.text_width(message)
pyxel.text((pyxel.width - w) // 2, 56, message, 10, self.font)

このフォントでは、ひらがなや漢字は1文字10ドットですが、英数字はそれより細くなります。文字数に10をかけて計算するのではなく、text_width を使いましょう。

ふちどりを付ける

text_with_border は、まわり8方向に1ドットずつずらしてふちの色で描き、最後に真ん中へ本来の色で描きます。絵の上や明るい背景の上でも、文字が読みやすくなります。公式サンプルの 13_custom_font.py でも、同じ方法を使っています。

改行する

文字の中に \n を入れると、そこで改行します。行の高さは、フォントに合わせて決まります。

改行の例
pyxel.text(8, 40, "1行目\n2行目", 7, self.font)

画面の右はしまで来ても、自動では折り返しません。長い文章は、自分で改行を入れましょう。

TTF・OTFのフォントを使うとき

TTF・OTF・TTC形式のフォントも読み込めます。この場合は、2番目に文字の大きさ(ドット数)を指定します。

TTFフォントを12ドットで読み込む
self.font = pyxel.Font("assets/PixelMplus12-Regular.ttf", 12)

Pyxelは、フォントの輪郭をなめらかにぼかさず(アンチエイリアスをかけず)、点を打つか打たないかの2通りで描きます。そのため、パソコン用のふつうのフォントを小さく使うと、線が欠けたり、ガタガタに見えたりすることがあります。

ドット絵用に作られたフォント(公式サンプルの PixelMplus など)を、そのフォントが想定している大きさで使うと、きれいに表示されます。

文字が出ない・欠けるときのチェック

何も表示されない

pyxel.text の5番目に、フォントを渡し忘れていないか確かめます。文字の色が背景と同じ色になっていないかも見てみましょう。

「Failed to open file」というエラーが出る

フォントのファイルを開けていません。ファイル名とフォルダー名のつづり、assets フォルダーの場所を確かめます。pyxel.init より前でフォントを読み込んでいないかも確認しましょう。

一部の文字だけ消える

使っているフォントに、その文字が入っていません。たとえば公式サンプルの umplus_j10r.bdf では、波ダッシュ「〜」、半角カタカナ「ア」、絵文字は表示されません。「〜」は、見た目が似ている全角チルダ「~」に置きかえると表示できます。

文字が重なる・画面からはみ出す

Pyxelは自動で折り返さないので、\n で改行するか、text_width で幅を確かめて位置を決めます。

文字がガタガタ・細い線が消える

TTF・OTFのフォントを、そのフォントに合わない大きさで使っている可能性があります。ドット絵用のフォントを、想定された大きさで使ってみましょう。

フォントを入れて配るときの注意

フォントには、それぞれ配布の条件(ライセンス)があります。ゲームと一緒にフォントのファイルを配るときは、フォントの配布元で条件を確認し、必要ならライセンスの文書も一緒に入れましょう。

ゲームを pyxel package で .pyxapp ファイルにまとめると、ゲームのフォルダーの中にあるフォントも一緒に入ります。フォントは、ゲームのフォルダーの中(例:assets フォルダー)に置いておきましょう。反対に、pyxel_examples のようなゲームに使わないフォルダーは、まとめる前に外へ出すか削除しておきます。まとめ方はPyxelで作ったゲームを公開する方法で説明しています。

このサイトの教材の場合

5ステップの教材は、フォントを用意しなくても動くように、画面の文字を英語にしています。元の完成版は、一緒に入っている assets フォルダーの素材を使って日本語を表示しています。権利の表示は出典・権利・検証範囲にまとめています。

この記事で確認したこと

Pyxel 2.9.9 のAPIリファレンス(text・Font・Font.text_width)、公式サンプル 13_custom_font.py、フォントを描くソースコードで、標準フォントの文字の範囲・読み飛ばし・改行・アンチエイリアスの扱いを照合しました。umplus_j10r.bdf に入っている文字は、フォントファイルを直接調べて確かめています(「〜」「ア」・絵文字は未収録、「~」は収録)。

main.py は、Pyxelの代わりに描画命令を記録する模擬モジュールで、フォントの読み込み・中央寄せの位置・ふちどりの描く順番を確かめています。実際のPyxelのウィンドウでの表示確認は、この記事の作成時には行っていません。