やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

pyxelでPNG画像をビットマップフォントとして読込・表示する(日本語表示)

 クラス分けした。pyxelにおける日本語表示の集大成。

成果物

demo bitmapfont

 前回と同じに見えるが、コードが全然ちがう。

コード

1. run.sh

  1. 00FF © 2018 hicc 患者長ひっくからttfファイルを入手
  2. BitmapFontGenerator.py: TTF→PNG
  3. main.py

 以下のような構造。

ファイル 役割
run.sh 実行用スクリプト
BitmapFontGenerator.py TTFPNG
main.py PNGpyxel.blt→日本語を窓に表示

ファイル 役割
PyxelText.py ビットマップフォント出力APIdraw(x, y, s)。座標x,yに文字列sを表示する。sには平仮名と片仮名も指定できる。
x8y12pxTheStrongGamer.py ビットマップフォント固有データ。識別名と1文字あたりの幅と高さを持っている。
BitmapFontMapper.py 文字(Unicode番号)とPNG画像上の座標における対応表をつくる
BitmapFont.py TTFからPNGを作成する
PyxelSpec.py pyxelの仕様をまとめた(画像の最大サイズ等)

 別のフォントを使うときはx8y12pxTheStrongGamer.pyを参考にすればできるはず。(未確認)

使い分け

TTF→PNG

 TTFファイルからPNGファイルを作成したいとき。必要なファイルは以下。

pyxelで表示したいとき

 PNGがあればTTFは不要。これが今回のポイント。

要点

PNGがあればTTFは不要

 TTFファイルが無くともPNGがあれば表示できる。

 あとはPNGファイルを.pyxresにドラッグ&ドロップすれば.pyxresファイル1つに固めて配布できるはず。TTFを配布せずに済む。ピクセルデータだけで完結できる。

技術面のキモ

ピクセルデータ操作

 BitmapFont.pyにてピクセルデータを__dataに入れている。

self.__data = numpy.array(img.getdata()).reshape(PyxelSpec.Image.Size[0], PyxelSpec.Image.Size[1])

 PIL.Image.getdata()は、この画像のピクセル値をシーケンスで返す。内部PILデータ型のため特定のシーケンス操作のみ許容する。通常のシーケンスに変換するにはlist(img.getdata())する。今回のコードはnumpyで操作するためnumpy.array()している。

 numpy.arrayは配列を作成する。

 numpy.reshape()はデータを変更せずに配列に新しい形状を与える。numpy.arange(6).reshape((3, 2))すると[[0,1],[2,3],[4,5]]になる。

 __data[y][x]のように入っており、値は0,255のいずれか。0が背景色で、255が文字の部分。おそらくPNGはインデックスカラー。ここで取得された0255はパレットのインデックス番号と思われる。8bitカラーのインデックスカラーは256色まで。つまり0255。通常、0番は背景や透明色である。

 なぜ`__data[x][y]でなく__data[y][x]か。それはfor文で回すときに「左から右へ。上から下へ」の順でピクセル捜査できるから。以下のように。この方向は一般的なものなので踏襲する。

class PyxelText:
    ...
    def __load(self):
        img_bank = pyxel.image(self.__img)
        for y in range(PyxelSpec.Image.Size[1]):
            for x in range(PyxelSpec.Image.Size[0]):
                img_bank.set(x, y, self.__col if self.__font.Data[y][x] else 0) 

 0以外なら、pyxelパレット番号のうち指定した値self.__colに変換して画像を作成する。なお、__load()内でいう画像はPILの一般的な画像ではなく、pyxelの16色インデックスカラーな画像である。

課題

  • 他のフォントで試す
  • 文字の色を変える
  • 漢字も対象にする
  • メッセージウインドウの枠内で折り返す
  • 1文字ずつアニメーションし音を出す

所感

 とりあえず、日本語の表示は一旦ここまでにしよう。他にも課題は多いが、フォントだけに時間を取られてしまうとゲームがいつまでたってもできない。あとは必要に応じて都度やる。

情報源

 製作者、先駆者に感謝。

前回まで

対象環境

$ uname -a
Linux raspberrypi 4.19.97-v7l+ #1294 SMP Thu Jan 30 13:21:14 GMT 2020 armv7l GNU/Linux