移植性の高いミニゲームライブラリを目指すぞ

PyBadge crisp-game-lib-portable screenshot

ミニデバイス向けミニゲームライブラリcrisp-game-lib-portableがM5StickC PLUSに加えてAdafruit PyBadgeでも動くようになった!2つのデバイスで動くので移植性が高い!完成!

とは言えないのは分かっている。そもそもM5StickC PLUSもPyBadgeも同じ Arduino IDEでビルドできるし、画面周りも LovyanGFXが両デバイスに対応しているので、移植自体難しくないんだよね。せめてArduino IDEを使わないほかのデバイスで……とか考え始めるとマイコンボード沼に片足突っ込みそうで怖い。実機は無くともPlaydate SDKに移植・ビルドできるか、くらいはやってみても面白いかも。

crisp-game-lib-portableはライブラリ本体ゲームのコードはブラウザを含むすべてのデバイス向けで共通、デバイス向けには最小限の個別コードを書けば対応できる、というのを目指している。M5StickCPlus向けはcglpM5StickCPlus.ino、PyBadge向けはcglpPyBadge.inoがそのコードに当たる。

バイス個別コードで書かないといけない処理は、

  • バイスの初期化処理(Arduinoならsetup())とそこからのinitGame()の呼び出し
  • フレームの更新処理(Arduinoならloop())とそこからのsetButtonState()呼び出しによるボタン状態の通知とupdateFrame()の呼び出し
  • machineDependent.hで定義された描画や音周りの処理

だけ。なので両デバイスとも必要な実装はC言語で250行程度だ。

音回りの実装はmd_playTone(float freq, float duration, float when)で特定の周波数を、特定の期間、特定の開始時間で鳴らすことを要求していて、これが一番面倒かもしれない。PyBadgeみたいなブザー音量をanalogWrite()で設定できるだけ、みたいなデバイスだと、音のタイミング管理をしつつ、矩形波を自力で生成しないといけない。まあ面倒だったら全部Not Implementedで音が出ないようにしてしまえばいいんだけど。

md_drawCharacter(unsigned char grid[CHARACTER_HEIGHT][CHARACTER_WIDTH][3], float x, float y, int hash)でドット絵を表示して、もちょっと面倒かも。最後にハッシュ値が付いているのは、毎回ドット絵のパターン定義をパース・描画するのではなくて、ハッシュ値でキャッシュしておいてそれを使ってね、という要求なので、そのロジックを書かないといかん。LovyanGFXがあるならLGFX_Spriteハッシュ値をペアで保存しておいて、それを取り出してpushSprite()するだけなので比較的簡単。

どちらかというと各デバイス固有の開発環境を整備するほうが面倒だよね。Arduino IDEがかなり広範なマイコンボードをサポートしてくれているのはとてもありがたいが、Arduino IDE自体の使い勝手がいまいちな気がする。ビルドに必要なファイル一式が同一ディレクトリに入っていることを要求するところとか、ビルドが遅いところとか。ビルドスピードはCcacheの導入か、PlatformIO IDEへの乗り換えで改善されるようだ。

こういった移植性を考えながらコードを書くことは、いろんなデバイスを相手にしたライブラリでないとできないことなので、なかなか楽しい経験ではある。あまたあるマイコンボードに対して、Arduino IDEなどの共通な開発環境、Adafruit ArcadaやLovyanGFXなどの多デバイス対応ライブラリを駆使しつつ独自のゲームライブラリを作るのは、PCやスマホをターゲットとしたゲームライブラリとはまた違った面白さがあり、おススメします!

いや、いにしえの教えを思い出したぞ!ライブラリを作るなゲームを作れ!やっぱりおススメしません!