RPGツクールMVでPWAゲームを開発することはできるか

RPGツクールMVで作ったアプリって HTML 形式でデプロイされますよね。

ところで今年は WWW 界隈で PWA (Progressive Web App) というのが話題になってますね。

聞けば PWA はネイティブアプリのように全画面表示が可能で、オフラインで動かすこともできるそうじゃないですか。
これは…ツクール作品を PWA 化したら楽しいかも? 
と思ったので、いろいろ試してみようと思います。

(PWA が何なのかという説明は[別の方が記事を書いてくださっています](https://qiita.com/edwardkenfox/items/4c0b9550ffa48c1f0445)ので、適宜ググってください。)

**忙しい方は「結論」まで読み飛ばしてください。**

# 目標

以下の疑問の答えを見つけること。

- RPGMV 作品を PWA にすることは可能か否か
- RPGMV 作品を「ホーム画面に追加」させることは可能か否か
- RPGMV 作品を横向きの全画面に固定できるか否か
- RPGMV 作品をオフラインプレイに対応できるか否か
- 上記の各機能に必要なものは何か
- 上記の各機能はIT専門外のツクラーでも実装可能にできるのか
- ぶっちゃけ普通にプレイするのと比べ UX に違いはあるのか

「PWA化」そのものではなく「PWA化により特定の機能を実装する方法の説明」を最終目標とします。

# 用意するもの

- マシン
    - MacBookAir2013later (Windows10 & macOS High Sierra)
    - SOV36 (Android8.0)
    - iPad mini 2 (iOS12)
- RPGツクールMV: Steam版 ver. 1.6.1
- Visual Studio Code
- ~~node.js~~ 結局使いませんでした
- GitHub リポ (成果はここに置きます)

# おためし

## いきなり Lighthouse に診断してもらう

最近の Chrome には [Lighthouse](https://developers.google.com/web/tools/lighthouse/) という便利ツールがあります。
これを使うと、 UX の良し悪しや PWA 化の具合を数値化してくれます。

試しに localhost に置いて診断してもらいました。

![0てんテスト.png](https://qiita-image-store.s3.amazonaws.com/0/99321/0784083a-76c2-023d-c533-ba99d90bfb34.png)
Progressive Web App 0点（　＾ω＾）・・・

## とりあえず Lighthouse の指摘事項を可能な限り改善する

![対応後ローカルでaudits.png](https://qiita-image-store.s3.amazonaws.com/0/99321/21118e83-ac72-98dc-aa4e-8c3e057460fa.png)

&darr; こちらの対応で58点まで上がりました。
https://github.com/TkoolerLufar/rpgmv-pwa-test/compare/190ebe394278259d6aed84c8e03e04a569538d3c...f5874fab3afe1e6d4c14f9c1329077fc7353cee2

~~まだ指摘事項が残ってますが、これは「HTTPS にしろ」っていうの[^1]と「軽くしろ」っていうの[^2]です。~~
&uarr; GutHub に上げてシークレットモードで[^3] audits したら100点になりました:+1: (2018/12/26 測定)

[^1]: 当時 localhost で作業していましたが、 GitHub に上げれば直るのでこの場では放置します。
[^2]: ロード前に一言メッセージ入れるようにもしてみましたが点は伸びませんでした。 minify とかしないと改善しないかも…。
[^3]: シークレットモードにした理由は Chrome 拡張機能が評価を下げていたからです。

## Lighthouse 対応にあたりハマったところ

対応中、**ネットつながってるはずなのにエラーでページが表示されない**…という現象に見舞われました。

僕が書いた Service Worker のバグでエラーをキャッシュしていたのが原因でした。
こんな深刻なバグを起こしてしまうとは… IT 専門外のツクラーに「これコピペすれば PWA になるから」って軽々しく渡すのは危なっかしいですね。
だって、**もし Service Worker のバグでプレイ不能になったら「永遠に遊べないプレイヤー」は必ず現れる[^4]**ので。

[^4]: 万一このような状況に陥った場合、 Service Worker を修正しプレイヤーにブラウザーの再起動を促せば解決します。ちなみに[再読み込みでは直らないそうです。](https://qiita.com/propella/items/6500f76c9c1521878a6b)

# 機能検証

## ホーム画面にアイコンを追加

![Screenshot_20181222-041416.png](https://qiita-image-store.s3.amazonaws.com/0/99321/ef5112d0-ac7e-f285-0eea-265c68928661.png)


こんな感じでプレイヤーの端末にインストールさせることができます。
~~商用ゲームのアイコンがいっぱい置いてあるところに自作ゲームのアイコンが混ざってる[^5]ところを想像すると、わくわくしませんか?~~
プレイヤー的にも、ブクマ機能まで手を伸ばさずにショートカットを置けるので手軽にゲームを保存できるという利点があります。

[^5]: iOS では前からできた? PWA の本気は次節からです。

## 横画面

マニフェスト設定したら横向きのフルスクリーンでツクールのゲームが動きました!

![IMG_0480.JPG](https://qiita-image-store.s3.amazonaws.com/0/99321/0292be2b-d2c5-5f83-7353-49d1f27164fb.jpeg)

manifest.json 書き換えただけなので、詳しい説明は省いていきます。 (詳細は "PWA manifest" でググってください。)
とりあえず正しく PWA をセットアップすればこういうこともできます。

## オフラインプレイ

ゲーム全体が 50MB 未満[^6]なら、なんとオフラインプレイが実装できるんですねー!
[^6]: 2018年現在の Safari におけるキャッシュの制約です。ちなみに Chrome は端末次第だそうで、例えば空き容量 1GB ならその内 60MB まで使える模様です。 (参考: https://developers.google.com/web/fundamentals/instant-and-offline/web-storage/offline-for-pwa?hl=ja 2018年12月20日閲覧)

オフラインプレイを実装するには、必要なファイルを Service Worker でキャッシュする必要がります。
今回の[検証用リポに上がってるの](https://tkoolerlufar.github.io/rpgmv-pwa-test/)は最低限のキャッシュしかしてませんが、全部キャッシュすればオフラインでも動きます。

…というのは理論上の話で、実際にツクると 50MB なんて簡単に突破してしまうかもしれません。
まあ PWA の初期キャッシュは App Shell[^7] を保持する程度のものなので、丸ごとゲーム1本を蓄えるのには不向きかもしれません。

[^7]: App Shell というのは、かいつまんで説明するとアプリのレイアウトやその他必要最低限の機能の総称です。

むしろ PWA のキャッシュは「**一度ダウンロードしたファイルは圏外でも読める**」ようにしたりするのが標準的な使い方のようです。

# 結論

冒頭の疑問の答えです。

- RPGMV 作品を PWA にすることは可能か否か
  … 可能。 PWA の機能を RPGMV に持たせることができるため、 PWA 化できます。[^8]
[^8]: 何を以って PWA と見なすかの明確な基準は調べましたが見つかりませんでした。ので、それらしい機能を導入できたらおkってことにしてます。

- RPGMV 作品を「ホーム画面に追加」させることは可能か否か
  … はい。規定サイズのアイコンと Service Worker を開発し必要最低限の機能を実装すれば「ホーム画面に追加」できるようになります。詳細は Lighthouse が教えてくれます。

- RPGMV 作品を横向きの全画面に固定できるか否か
  … できる。 上記「ホーム画面に追加」できるようにし、さらにマニフェスト（後述）を正しく設定すれば横向きの全画面に固定されます。

- RPGMV 作品をオフラインプレイに対応できるか否か
  … できるけどミニゲーム限定。サイズ制限が厳しいため、手の込んだ長編 RPG ではまず不可能でしょう。その代わり、圏外でもレベリングには支障なくプレイできるようにすることが可能です。

- 上記の各機能に必要なものは何か
  … 結構数が多いので次節で詳説いたします。

- 上記の各機能はIT専門外のツクラーでも実装可能にできるのか
  … 後述の「必要なもの」を全て揃えれば実装可能です。ただし、失敗するとプレイヤーが泣くのでプラグイン屋さんに監修または実装を依頼した方が安全です。

- ぶっちゃけ普通にプレイするのと比べ UX に違いはあるのか
  … 横画面固定の全画面にできるので、誤って終了するのを防ぎつつ画面をフル活用できます。

# 実際に PWA 化する

## 必要なもの

以下のファイルを落とし、所定の場所に置きます。

- Service Worker スクリプト: [service_worker.js](https://github.com/TkoolerLufar/rpgmv-pwa-test/blob/master/service_worker.js)
    - index.html の隣に置いてください。
- マニフェスト: [manifest.json](https://github.com/TkoolerLufar/rpgmv-pwa-test/blob/master/manifest.json)
    - index.html の隣に置いてください。
    - 略称と正式名称の部分はご自身のゲームに合わせ適当に書き換えてください。略称は全角5字までが目安です。
- ゲームのアイコン: [icon](https://github.com/TkoolerLufar/rpgmv-pwa-test/tree/master/icon)/*.png
    - ２つ必要です。お好みで自作
    - １つは 192x192 のホーム画面用アイコン launcher.png
    - もう１つは 512x512 で、ホーム画面から起動した時に表示される splash.png です。
    - icon というフォルダーに入れてください。
- 魔改造された [index.html](https://github.com/TkoolerLufar/rpgmv-pwa-test/blob/master/index.html)
    - ツクールのバージョンが 1.6.1 でないか、または既に別の用途で改造済みの場合は[プロジェクト作成直後との違い](https://github.com/TkoolerLufar/rpgmv-pwa-test/compare/190ebe394278259d6aed84c8e03e04a569538d3c...master#diff-eacf331f0ffc35d4b482f1d15a887d3b)を参考に手動で改変してください。
- Service Worker を読み込ませるプラグイン: https://github.com/TkoolerLufar/rpgmv-pwa-test/blob/master/js/plugins/RegisterServiceWorker.js
    - 他のプラグインと同じように導入して ON にしたら完了!
- https (TLS) でのアクセスに対応した Web サーバー
    - IT エンジニアなら GitHub Pages がお手軽なんですが、それ以外だとどこがいいだろう…?
    - 念のため書いておくと、物理的なサーバーを調達するのではなくレンタルサーバーを利用するのが一般的です。
    - ちなみに CGI や PHP, Rails といった機能はツクールMV作品には不要です。

## 方法

1. 上記「必要なもの」を一通り揃えます。
1. ついでにゲームフォルダーに css というフォルダーを作り、 [JavaScript 無効時に使うCSS](https://github.com/TkoolerLufar/rpgmv-pwa-test/blob/master/css/like_rpg_windows.css)[^9] を配置します。
1. Web サーバーにアップロードし、外部から https で遊べるようにします。
1. 完成!

[^9]: RPGMV 風はネタですが、とにかく読める文字で「JavaScript有効にしてね」って表示するのに必要です。

# サンプル

https://tkoolerlufar.github.io/rpgmv-pwa-test/

# 総評

今回、PWA を知らないツクラーを意識しながら「RPGMV作品をPWA化すると何が起きるか」「RPGMV作品はどうすればPWA化できるのか」を調査・説明してみました。
技術調査もですが、専門外の人を意識して説明するのは大変ですね。少しでも理解していただければ幸いです。