aburi6800のブログ

コンピュータのプログラミング、ゲームに関するニッチな情報を書いていくブログです。

【Obsidian】Obsidianのモバイルアプリを試してみた

f:id:aburi6800:20210725005439p:plain

Obsidianは動作が軽く使いやすい、マークダウン形式で記述するメモアプリだが、これまでモバイルデバイス向けのアプリケーションが存在しなかった。
そのため、個人的にはAndroidのGitJournalというアプリを使用してきたが、見た目や操作感が違うためあまり快適とは言えず、またまともに使うためには課金が必要(しかもサブスクのため払い続けなければならない)であるため、活用できていなかった。
しかし、ようやくObsidianのモバイルアプリが2021/7/12にリリースされた。
早速試してみたので、所感などを記しておく。

この記事は導入した時点でのものになります。
今後本格的に使用し、細かいことが判明次第、加筆修正していきます。

ファーストインプレッション

軽く触ってみた感想。あくまで個人的な感想です。

  • 動作も軽く、デスクトップ版の雰囲気そのままで使える。
  • ただし、操作が若干複雑。これは設定で何とかなるのか。
  • テンプレートの場所、日付書式、プラグインといった設定については、デスクトップアプリの設定を参考に設定しなおさなければならない。
  • 多言語対応がまだされていない。ただ、デスクトップアプリを使用していればそれほど困らず、そのうちサポートもされることだろう。
  • PCでObsidianを使っている人なら、データ同期の問題を何とかさせてでも使った方がいい。

データの同期について

「なんとかしてデータ同期させて」と書いたのは、Obsidianがローカルにデータを保持するアプリケーションであり、単体ではクラウドストレージに対応していない為である。
ここでは、現状選択肢として選択可能なクラウドストレージサービスと、簡単な概略を記載する。

Obsidianのモバイルアプリのみを使う人はこの限りではありません。 たとえばタブレット端末でしか使わない、というのもアリで、その場合は単純にValutを作成するだけになります。

obsidian sync

obsidianオフィシャルの同期サービス。
プラグインでサポートされているため、OSやデバイスを意識せずに使える。
また、Obsidian publishというWeb公開サービスも使用できる。
有料となっているが、ヘビーに使いたい場合は選択肢に入れても良いかもしれない。

git(github)

デスクトップ版では「Obsidian git」というサードパーティープラグインがあり、githubを介して複数PC間のデータ同期ができていた。
しかし、スマートフォン(自分の場合はAndroid)ではこのプラグインがサポートされていない。
また、gitクライアントアプリもあるが、手動でpush/popする必要があり、操作性に欠ける。
そのため、今回はgitの使用を見送ることとした。

手動でgitリポジトリからpopする運用で良ければ、この手段でも問題ないです。

google drive

PC(Windows)では、googleドライブアプリを入れることで、クラウドであることを意識せずに使える。
Androidでは、google製の「ドライブ」はクラウドストレージの中を見るだけでローカルとの同期は取れず、個別にファイルをダウンロードするしかない。
この目的を達成するものとしては「FolderSync」や「Autosync」というアプリがある。
なお、ubuntu(Linux)での使用については、google製のアプリがリリースされていないため環境駆逐の問題が残るのと、googleはサービス自体に突然大きな仕様変更を行う不安定さがあるのが難点。

Linuxでのgoogleドライブのマウントは、google-drive-ocamlfuseというアプリケーションでマウント可能になる模様。
これについては別記事にしようと思います。

OneDrive

PC(Windows)の操作感はgoogle Driveと同様、クラウドであることを意識せずに使える。
Androidは「FolderSync」というアプリでクラウド上(OneDrive)のファイルと端末のディレクトリ(任意指定可能)の同期をとることができるらしい。

らしい、というのは私がこのアプリ(FolderSync)を使用していないから。レビューを見ると不安定なようだったので、見送りました。

また、Microsoftのサービスであるためgoogleほどの不安は無いが、ubuntu(Linux)ではまだMicrosoft製のアプリがリリースされていないため、google driveと同様に環境構築の問題がある。

Dropbox

過去はクラウドストレージの筆頭となるサービスだったが、無料での利用台数が3台まで、他のストレージに比べて容量が少ないといった使い勝手の悪さと、有料の価格設定の高さから、ヘビーユーザーにはお勧めできない。
しかし、公式にubuntu(Linux)への対応を行っていること、モバイル端末でのアプリも様々なものがあるため、利用台数が少ない場合(PC1台、モバイル端末1台など)は、Dropboxを選択するのはアリだと思う。

その他

その他のサービスも同様で、使用しているOSとモバイルデバイスでのサポート状況を確認し、問題なければ使用できる。
問題がある、ないの判断は「ローカルとクラウドでデータが自動的に同期できるか」で良いと思う。

FAQ

Valut(書庫)を開こうとするとエラーが発生して開けない

SDカードのディレクトリをValutに指定したのが原因。
本体ストレージにディレクトリを用意すること。

バージョン 1.0.3時点。
恐らくSDカードへのアクセス権限付与漏れで、将来的に解消されると思われる。

エディタの文字サイズが大きい

プレビューは普通なのに、エディタに入ると文字が大きくなる。
これは設定メニュー(歯車のアイコン)から「Appearance」に入り「Font size」で指定できる。
指定後は、一度アプリを終了させること。

【Python】Pythonの仮想環境を使う

例えば、複数のアプリケーションを開発していて、導入パッケージがそれぞれ異なる場合、各アプリケーションで最低限必要なものだけを導入した環境が欲しくなることがある。
また、Pythonの基本的なバージョンは上げつつ、開発中のアプリケーションは特定のバージョンに固定したいことがある。
このようなときは、Pythonの仮想環境を使用し、Pythonのバージョンと導入パッケージをアプリケーションごとに固定する。
ここでは、Python標準機能として用意されているvenvを使用する。

仮想環境の作成

バージョンを指定せずに作成

プロジェクトのルートディレクトリで以下を実行する。 (以下は仮想環境名を.venvとした場合)

python -m venv .venv

こうすることで、パスが通ったPythonのバーションで作成される。

Linuxなどの場合は、pythonコマンドではなくpython3コマンドの場合があります。 ubuntu20.04だとpythonコマンドで大丈夫です。

仮想環境のバージョンを指定する(Windows

WIndowsの場合はpyコマンドがあるので、プロジェクトのルートディレクトリで以下を実行する。

py -3.6 -m venv .venv

最初の引数(-3.6)は、Pythonのバージョンとなる。

仮想環境のバージョンを指定する(macLinux

macLinuxの場合は、pyenvを使うのが良さそう。
githubに公開されているので、インストールする。
使い方などは以下を参照。(そのうち追記します)

参考

[https://www.mathpython.com/ja/ubuntu-python/:embed:cite]

仮想環境の使用

Windows(コマンドプロンプトPowerShell)の場合

プロジェクトのルートフォルダで以下を実行する。

./.venv/Scripts/activate

MacLinuxの場合

プロジェクトのルートディレクトリで以下を実行する。

source ./.venv/bin/activate

運用

仮想環境でパッケージをインストールする

以下コマンドを実行することで、その仮想環境にパッケージが導入される。

pip install [package name]

仮想環境に導入されているパッケージを確認する

仮想環境に切り替え後に以下コマンドを実行する。

pip freeze

仮想環境を配布する

venvしたディレクトリをそのまま渡すのではなく、各端末で仮想環境を作成しパッケージを導入する方法をとる。
まず、配布元で導入するパッケージのリストを作成する。

pip freeze > requirement.txt

作成されたrequirement.txtを配布し、構築する端末では以下コマンドでパッケージを導入する。

pip install -r requiments.txt

切り替え後のPythonのバージョンを確認する

仮想環境に切り替え後に以下コマンドを実行する。

python -V

Vは大文字

仮想環境を終了する

WindowsMacLinux共に、以下のコマンドを実行する。

deactivate

仮想環境を削除する

作成されたディレクトリを削除するだけ。

所感

pip freeze > requirements.txtをする際に余計なパッケージを含めたくないときなどは、同じpythonバージョンでも別環境を作った方が良い。
また、複数の環境が作れるので、例えば古いバージョンでバグ報告があった場合の検証環境も簡単に用意できる。
OSごとに若干操作方法が異なるが、標準で使えてお手軽だし、とても便利なので、個人開発でも積極的に使っていきたいと思う。

【Python】PyInstallerの警告に対する対処方法について

環境

発生した環境は以下。

発生事象

上記環境にて、pyxelpackagerでアプリケーションの単体実行ファイル生成時、以下警告が発生。
単体実行ファイルが作成されない。

12467 WARNING: Tcl modules directory /usr/share/tcltk/tcl8.6/../tcl8 does not exist.

原因

pyxelpackagerでは、引数(アセット、実行ファイル)を作成する処理のみを行い、PyInstallerに渡す。
単体実行ファイルを作成する処理はPyInstallerにて行われるが、このPyInstallerでのパスの指定がおかしい。
(tcl8ディレクトリはtcl8.6の下に存在しているが、その上の階層を参照しようとしている)

対処

~/.local/lib/python3.8/site-packages/PyInstaller/hooks/hook-_tkinter.py の 206行目に余計な引数が指定されているのを削除。

(修正前)

206    modules_path = os.path.join(tcl_root, "..", modules_dirname)

(修正後)

206     modules_path = os.path.join(tcl_root, modules_dirname)

その後、pyxelpackagerを実行すると、単体実行ファイルが作成された。

補足

venvで仮想環境を作成している場合、修正対象ファイル(hook-_tkinter.py)は以下に配置される。

./lib/python3.8/site-packages/PyInstaller/hooks/hook-_tkinter.py

なお、Macは手元に環境が無いため未確認だが、恐らく同様の原因だと思われる。

【ubuntu】ubuntu20.04にEPSON EP-10VAのドライバをインストールする

ubuntu20.04をインストール後、自動的にプリンタを検出して印刷できていたが、先日改めてLibreOffice Calcで印刷したところ、何やら化けた文字が印刷されてしまった。
原因が不明なので、改めて以下手順でドライバをインストールした。

ドライバの入手元

以下にアクセス。

http://download.ebz.epson.net/dsc/search/01/search/searchModule

製品名・型番に「EP-10VA」を入力、OSは「Linux」を選択して虫眼鏡アイコンをクリック。

f:id:aburi6800:20210220164314p:plain

プリンタドライバ

下記の画面で一番上の「Printer Driver」のDownloadボタンをクリック。

f:id:aburi6800:20210220164345p:plain

「同意する」ボタンを押すと下にファイルの一覧が表示されるので、「epson-inkjet-printer-escpr_1.7.9-1lsb3.2_amd64.deb」(上から4番目)の「ダウンロード」ボタンをクリック。

ubuntu以外を使っている場合は、使用しているディストリビューションに合わせて対象のファイルを選択する。

f:id:aburi6800:20210220164417p:plain

以下を実行し、必要なLSBパッケージをインストールする。

sudo apt-get install lsb

ダウンロードした.debパッケージを、以下のコマンドでインストールする。

sudo dpkg -i ./epson-inkjet-printer-escpr_1.7.9-1lsb3.2_amd64.deb

ユーティリティ

下記の画面で二番目の「Epson Printer Utility」のDownloadボタンをクリック。

f:id:aburi6800:20210220164345p:plain

「同意する」ボタンを押すと下にファイルの一覧が表示されるので、「epson-printer-utility_1.1.1-1lsb3.2_amd64.deb」(上から4番目)の「ダウンロード」ボタンをクリック。

f:id:aburi6800:20210220164537p:plain

ダウンロードファイルのあるディレクトリで以下を入力し、インストールする。

sudo dpkg -i ./epson-printer-utility_1.1.1-1lsb3.2_amd64.deb

スキャナドライバ

下記の画面で三番目の「Scanner Driver」のDownloadボタンをクリック。

f:id:aburi6800:20210220164345p:plain

「同意する」ボタンを押すと下にファイル(マニュアル)の一覧とダウンロードリンクが表示されるので、「Package Download Page」のリンクをクリック。

f:id:aburi6800:20210220164705p:plain

スキャナドライバダウンロードページに移動するので、使用しているディストリビューション(今回の場合、ubuntu 20.04(LTS))のDownloadボタンをクリック。

f:id:aburi6800:20210220164741p:plain

ダウンロードファイルのあるディレクトリで以下を入力し、インストールする。

tar -xvf ./imagescan-bundle-ubuntu-20.04-3.65.0.x64.deb.tar.gz
cd imagescan-bundle-ubuntu-20.04-3.65.0.x64.deb.tar.gz
./install.sh

シェルスクリプトでのインストールが失敗する場合は、マニュアルに従って手動でインストールすることも可能。

プリンタの設定

設定でプリンタの画面を開き、ウィンドウ上部の「追加」ボタンをクリック。
※この画面で表示されている「EPSON_E…A_Series」は自動的に登録されていたものだが、これがうまく動かなかった

f:id:aburi6800:20210220164837p:plain

EP-10VAを選択。

f:id:aburi6800:20210220164920p:plain

しばらく待つと登録が完了する。
登録された「EP-10VA」の詳細が以下の内容になっていればOK。

f:id:aburi6800:20210220164945p:plain

これをデフォルトプリンターに設定して完了。

【Obsidian】Obsidian gitプラグインのメモ

マークダウンエディタのObsidionは、ドキュメントの作成や思考の整理に適したツールですが、基本的に保存先はローカルドライブになります。
そのため、複数台のPCを使用していると、ファイルの同期を何らかの方法で行う必要があります。
また、バックアップも自己管理となります。
この問題を解消するため、サードパーティープラグインとして公開されている「Obsidian git」プラグインについて簡単に説明します。

2022/04/11 追記: この記事を記載後、プラグインのバージョンアップが進み、機能が充実しています。
設定項目もその分増えていますので、以下に2022/4時点で最新のプラグイン(1.24.1)をベースに記載した記事を投稿していますので、こちらを参照願います。 aburi6800.hatenablog.com

目次

Obsidian gitプラグインとは

  • ObsidianでGitリポジトリへのpush、pullを行えるサードパーティープラグイン
  • Githubなどのリモートリポジトリを介して複数端末からファイルを編集できるようになるので便利。(リモートリポジトリがバックアップにもなる)
  • 事前にGitのリモートリポジトリの作成とSSH接続の設定を行っておく必要があるので、若干敷居が高い。

    GithubとのSSH接続に関しては、Web上に解説記事があるので、そちらを参照ください。(気が向いたらこのブログにも書きます)

使用方法

Obsidianがインストールされている前提で、以下を行う。

  1. サードパーティープラグインから、Obisdian Gitプラグインをインストールする。
  2. 「別の保管庫を開く」から、事前にcloneしておいたディレクトリを保管庫として開く。
  3. 設定を行う。

設定

f:id:aburi6800:20210206235504p:plain
Obsidian gitの設定画面

  1. Valut Backup Interval (minutes):自動的にリモートリポジトリにpushする間隔を分で指定する。
  2. Commit message:リモートリポジトリへのコミットメッセージを指定する。{{date}}のフォーマットは次で指定可能。
  3. {{date}} placeholder format:コミットメッセージの{{date}}の書式を設定する。
  4. Preview commit message:上記で設定したコミットメッセージをプレビューする。
  5. Current branch:push先のブランチを指定する。(通常はmasterのままでOK)
  6. Pull updates on startup:Obsidian起動時にリモートリポジトリからpullするかを設定する。(ON推奨)
  7. Disable push:リモートリポジトリへのpushを禁止する。(通常はOFFでOK)
  8. Disable Notifications:通知表示をOFFにする。(右上の表示が鬱陶しい場合はONにする)

コマンド

ホットキーは初期設定時は割当なし。 以下は私の(今のところの)設定例です。

コマンド 説明 ホットキー
Obsidian git: Pull from remote repository リモートリポジトリからpullする [Ctrl]+[Shift]+[P]
Obsidian git: Commit all changes and push to remote repository 全ての変更ファイルをcommitし、リモートリポジトリにpushする [Ctrl]+[Shift]+[Enter]

※作業終了時に必ず[Ctrl]+[Shift]+[Enter]を叩く癖をつける

注意点

  • 競合が発生した場合、マージは手動で行う必要があるので注意。(=チームでの共同作業には向かないかも知れない)
  • .obsidian/workspace は各端末での画面の状態を保存しているファイルなので、.gitignoreに登録推奨。

総括

このプラグイン、説明ページにも使用方法が明確に書かれていなかったり(私が見落としただけ?)、機能が最低限のため競合が発生すると別手段での解消が必要になったりと、少々不親切な部分がありますが、1台のみでObsidianを使っていたとしてもGitリポジトリにバックアップが取れるので、Obsidianを使用しているなら試してみる価値はあります。

他にDropboxやOneDrive経由で同期する手段もありますが、Dropboxは無料アカウントでの制約が厳しくなったし、Linuxも併用するならGitが一番汎用的で使いやすいのではないでしょうか。

なお、スマートフォン/タブレットでは、AndroidではGitJournalというアプリで、Githubのリモートリポジトリへの接続やマークダウン形式のドキュメントを扱うことができます。(iPhoneは色々とあるようですが、持っていないので未調査)

なお、Obsidianのモバイルアプリが開発中、2021年中にリリースされる予定とのことなので、期待しています。


参考:
Obsidian
Github - Obsidian git

【VSCode】importで未解決の警告(import ~ could not be resolved)が出る問題の対策方法

 VisualStudioCodeを使ってPythonのソースを書くときに便利な拡張機能として、Pylanceがリリースされておりますが、ちょっとハマったことがあったので、記録として記事にしておきます。
 似たような事象に悩まされている方のお役に立てれば幸いです。
 

発生した事象

 今回作ったワークスペースは、以下のようなディレクトリ構成としました。

${WorkSpaceFolder}
└ source
 ├ module
 │ └ myModule.py
 └ main.py

 
 main.pyでは、以下のようにmoduleパッケージにあるユーザーモジュールmyModule.pyhogeクラスをimportしようとしています。

from .module.myModule import hoge

 
 すると、以下の警告が発生しました。

ImportError: attempted relative import with no known parent package

 
 なお、警告が出るだけで、実行は可能な状態です。(Python上では問題ない)
 

対処

 以下の手順で、先ほどの警告が出なくなるはずです。
(設定値のフォルダ名は合わせて適宜変更、複数ある場合はカンマで続けて記載していく)
 
① ワークスペースのルートディレクトリにある.vscode/ディレクトリにsettings.jsonファイルを作成し、以下の内容を記述する。

{
    "python.analysis.extraPaths": [
        "./source"
    ]
}

VSCodeの設定から拡張機能のPylanceを選択し、ワークスペースタブのPython > Analsys: Extra Pathsの「項目の追加」を押して、設定値を記載しても同じです。
※パスはワークスペースディレクトリからの相対パスで指定してください。${WorkSpaceFolder}/sourceのように絶対パスで指定するとうまくいかないようです。
 
② VSCodeを再起動する。
 
③ import文を以下のように修正する。

from module.myModule import hoge

※パッケージの先頭にあった「.」(ピリオド)を削除する
 

原因

 Pylanceでは、通常はワークスペースのルートディレクトリ(VSCodeで開いたディレクトリ)をユーザーモジュールのインポートのメインルートとして扱います。
 それ以外のディレクトリをユーザーモジュールのメインルートとした場合は、Pylanceは見つけることができないため、警告が出ていたということでした。
 なので、以下のようなディレクトリ構成だった場合は、特に対応する必要はなかったわけです。

${WorkSpaceFolder}
├ module
│ └ myModule.py
└ main.py

 

さいごに

 この事象の説明と対応は、以下のURL(PylanceのGitHubリポジトリにある、Trubleshootingドキュメント)にも記載がありますので、参考に貼っておきます。
https://github.com/microsoft/pylance-release/blob/master/TROUBLESHOOTING.md#unresolved-import-warnings  
 また、調査に協力いただいたHiromasaさん、本当にありがとうございました!

【Python】Pyxelでカナ文字を表示したい

 さて今回は、Pythonゲームエンジン「Pyxel」を使ったカナ文字表示処理を作った記事です。
 ちょっと長文になりますが、作成の過程を赤裸々に書いていますので、何かの参考になれば幸いです。
 
 なお、ここではPythonやPyxelのインストール等の細かい説明は割愛します。
 Pyxelについては、公開されているGitHubリポジトリにあるREADMEを参照してください。
(今後も更新される可能性があるため、他のサイトの記事よりも、こちらを参照することを推奨します)

github.com

事の経緯

 さて、Pyxelでゲームを作り始めたところ、標準のAPIでは英文字(大文字・小文字)と数字、記号の表示はできますが、カタカナ・ひらがなの表示ができませんでした。
 メッセージが重要でないゲームであればこのままで良いのですが、今作っているのはRPGで、メッセージを読ませるためにカナ文字を表示したいのです。
 そこで、自前でカナ文字の表示を実現しよう、というのが始まりでした。

まずは文字画像の素材から

 一言に「カナ文字を表示」と言っても、プログラムとしてやることは「文字の形に作った画像を表示する」です。
 普通のキャラクターの表示と変わりません。
 なので、まずは文字パターンの画像データを作りました。

f:id:aburi6800:20200613132801p:plain
ひらがな・カタカナの画像データ
 Pyxelの英数字は、3x6ドットと縮小されたものですので、これと合わせたときに違和感がないように、7x6ドットで書いています。
(さすがにこれ以上小さくするのは無理でした・・・(^^;)
 これを、一般的なドットエディタで256x256ドットのpngで保存して、Pyxelに同梱されているPyxelEditorに先ほど作った画像を取り込んでリソースデータにします。

最初の実装

 次に、プログラムで表示していきます。
 まずは、どのように実装するかですが、以下のnote記事を参考にさせていただきました。

note.com

 簡単に説明すると、Pythonの辞書型に、「あ」だったら「A」のようにキーとする文字と、文字パターン画像データの対応する座標を定義していくものです。
 具体的には、以下のようなコードになります。
 キーは、ひらがなは大文字(「A」、「SA」など)、カタカナは小文字(「a」、「sa」など)としました。
 長すぎるので一部抜粋していますが、これをすべての文字に対して定義します。

# -*- coding: utf-8 -*-
import pyxel

class PyxelUtil:

    KANA_DIC = {
        "A"  : [  0,   1],
        "I"  : [  8,   1],
        "U"  : [ 16,   1],
        "E"  : [ 24,   1],
        "O"  : [ 32,   1],
    :
    :
(以下、定義が続く)

 
 これを実際に表示する処理として、以下のようなコードを書きました。

    @staticmethod
    def text(x, y, txt, color=7):  

        for i in range(len(txt)):
            if txt[i][0] == "*":
                t = txt[i].replace("*", "")
                pyxel.text(x, y, t, color)
                x = x + 4 * len(t)
            
            else:
                font_xy = PyxelUtil.KANA_DIC[txt[i]]
                fontx = font_xy[0]
                fonty = font_xy[1]
                pyxel.pal(7, color)
                pyxel.blt(x, y - 1, 0, fontx, fonty, 7, 6, 0)

 
 Pyxelのtextメソッドと同じ名前にして、引数も同じ構成にしています。
 ただし、引数の「txt」はリストの形としており、カナ文字の場合は辞書のインデックスを指定します。
 英数字を含んだメッセージを表示したかったので、先頭に「*」を付けた要素はPyxelのtextメソッドでそのまま表示するようにしました。
 
 これを使って実際に文字表示をするコードは、次のようになります。

PyxelUtil.text( 16,  16, ["A", "I", "U", "E", "O", "*ABCDE12345"], 7)

問題その①

 さて、ここまでで想定した通りに文字が表示ができるようになりました。
 しかし、この処理構成には、大きな問題があります。
 「Pyxelのイメージバンクの一部を文字パターン画像データで消費している」という問題です。
 このため、他のプログラムでは流用しにくいものになっているのです。
 例えば、イメージバンクのすべてを使い切ったゲームの場合は、この文字パターン画像データをイメージバンクに入れることができないので、カナ文字を表示できないことになります。
 
 そこで、文字パターンデータをプログラムに直接持とう、と考えました。
 そこでまず、ドットのあるところは1、ないところは0として、次にように全てデータ化しました。(大変でした・・・)

    KANA_DIC = {
        "A"  : ["0010000", "0111100", "0010001", "1111110", "1010101", "0111001"],
        "I"  : ["0000000", "1000010", "1000001", "1010001", "0110001", "0010000"],
        "U"  : ["0011100", "0000000", "0111110", "1000001", "0000001", "0011110"],
        "E"  : ["0011110", "0000000", "1111111", "0000110", "0111000", "1100111"],
        "O"  : ["0001001", "0111101", "0001000", "0111110", "1001001", "0111001"],
    :
    :
(以下、定義が続く)

 
 次に表示ですが、システム用イメージバンクの表示スクリーン用に直接描いてはどうだろうか?、と考えました。
 そこで、以下のようにしました。

    @staticmethod
    def text(x, y, txt, color=7):  

        for idx in range(len(txt)):
            if txt[i][0] == "*":
                t = txt[i].replace("*", "")
                pyxel.text(x, y, t, color)
                x = x + 4 * len(t)
            
            else:
                data = copy.deepcopy(PyxelUtil.KANA_DIC[txt[idx]])
                for i in range(len(data)):
                    data[i] = data[i].replace("1", "{:1x}".format(color))                    
                pyxel.image(4, system = True).set(x, y, data)
                x = x + 8

 
 else以降が修正した部分です。
 ビットパターンに色を指定するために一時的に辞書のデータを書き換えるので、copyモジュールをimportしてdeepcopyしました。
(単純にdata = PyxelUtil.KANA_DIC[txt[idx]]とすると、元の辞書データも変更されてしまいました。Pythonのリストは参照渡しのようです。)  これをsetメソッドで、表示スクリーン用イメージに直接描画しています。
 
 これで試したところ、画面に直接、プログラムで定義したパターンが描画することができました。
(システムリソースにアクセスするための引数の書き方を、最初はimage(4, True)としていて動かず、しばらく悩みましたが・・・)
 
 ようやく汎用的な文字表示クラスが作れた!
 これでどんなゲームでもカナ文字が表示できる!
 と、喜んでいたのですが・・・

問題その②

 先の対応で、Pyxelのリソースデータを消費せずに、カナ文字を含めた文字表示ができるようになりました。
 しかし、色々試していたところ、Pyxelのtextメソッドとは描画される挙動がちょっと違っていたのです。
 
 たとえば、pyxel.textを使って文字を重ねて表示すると、次のような結果になります。

f:id:aburi6800:20200613122835p:plain
pyxelのtextメソッドで重ねて表示
 次に、今回作成したtextメソッドで文字を重ねて表示すると、次のような結果になりました。
f:id:aburi6800:20200613123145p:plain
今回作成したtextメソッドで重ねて表示
 
 このように、「背景色の透過がされていない」んですね。
 それもそのはず、データ上「0」とした部分は、透明ではなく黒ですからね・・・。
 この黒の部分も含めてすべてのデータを表示スクリーン用イメージに描いているのですから、透過されるわけがありません。
 Pyxelのbltメソッドで透過表示できるのは、恐らく内部的には、イメージバンクから表示スクリーン用イメージにコピーするときに指定された色を描画しないようにしているのだと考えます。
 
 であれば、データで「0」とした部分を描かず、「1」となっている部分に対して、指定された色でドットを打てば良いですね。
 Pyxelではpsetメソッドが用意されていますので、これを使います。
 psetメソッドは表示スクリーン用イメージに直接描画するようですので、何も考えずに以下のようなコードとしました。

    @staticmethod
    def text(x, y, txt, color=7):  

        for idx in range(len(txt)):
            if txt[idx][0] == "*":
                t = txt[idx][1:len(txt[idx])]
                pyxel.text(x, y + 1, t, color)
                x = x + 4 * len(t)
            
            else:
                try:
                    for row, data in enumerate(PyxelUtil.KANA_DIC[txt[idx]]):
                        for col in range(len(data)):
                            if data[col] == "1":
                                pyxel.pset(x + col, y + row, color)
                    x = x + 8
                except KeyError:
                    x = x + 8
                    continue

 
 for文を2重にし、外側は辞書の各文字に定義したビットパターンの配列に対してのループ、内側は各配列要素に対してのループになります。
 要するに、全部のビットパターンを精査して、「1」だったら指定された色でpsetする、という処理です。

 tryexceptで括ったのは、辞書に存在しないキーが指定されたときにエラーで止まらず空白を開けるようにするためです。(元から潜在していた不具合ですね・・・)
 また、単純に「*」をreplaceしていたため、文字としての「*」が表示できない不具合がありましたので、5~6行目も修正しています。
 
 では、実行してみます。

f:id:aburi6800:20200613130233p:plain
修正したtextメソッドで重ねて表示
 
 おおっ!無事に、カナ文字も重ねて表示できるようになりました!!
 処理速度的にも問題なさそうです。

最後に

 実際にわかってしまえば「なんでこんな処理に苦労したんだ?」となるような処理ですが、ここに辿り着くまでに苦労したんですよ・・・。
 おかげで、だいぶPythonもPyxelもわかってきました。
 
 なお、今回作ったモジュールは、以下のGithubリポジトリに公開しています。

github.com

 cloneしたらpyxelUtil.pyをコピーしてきて、importしたらそのまま使えます。
 使い方は、pyxelUtil.pyを実行するか、プログラムソースの後半を見ればすぐにわかるかと思います。
 また、必要最低限のパターンしか定義していませんが、記号などの追加も簡単にできるように、単純なソースにしています。
 ご自由にお使いいただければと思います。