フェーズ 10 パッケージ化して Web で公開する

2 つのコマンドで HTML 1 枚にまとめ、GitHub Pages に置く

トップページstep1 概要 / フェーズ 10

ゴール

完成した Candy Hunt を、インストールなしでブラウザから遊べる形にして公開します。 これで step1 は完了です。

手順は step0 の Star Voyager でやったものと同じです。 やり方そのものは step0 フェーズ 8 にくわしく書いてあるので、 このページは手順を短くおさらいし、step1 で新しく出てくることだけを厚く扱います。

step1 で新しく出てくるのは、この 3 つだけですフォルダの中身が丸ごと公開される(余計なファイルが混ざっていないか)/ ② 音のあるゲームを Web に出すときの決まり(クリックするまで鳴らない)/ ③ 2 本目の作品をリポジトリに足すときのリンクの張り方。

1. 考え方

1-1. 2 つのコマンドが、何をしているか

pyxel packagepyxel app2html は、 フォルダ → 1 つのファイル → 1 枚の HTML と、順にまとめていくコマンドです。 実際に step1 で実行して、できたファイルの中身と大きさを確かめました。

step1/ フォルダ candy_hunt.py(10,190 バイト) + candy_hunt.pyxres(589 バイト) pyxel package step1 step1/candy_hunt.py step1.pyxapp 4,308 バイト 中身は ZIP。フォルダの中身+「どれで起動するか」の 13 バイトのメモ pyxel app2html step1.pyxapp step1.html 5,956 バイト 上の .pyxapp を文字列にして埋め込んだもの。ゲーム本体は 1 枚に収まっている 名前を作品名に変えて置く(名前がそのまま URL になる) docs/site/step1/candy_hunt.html push すれば、数分後には公開 URL で遊べる ※ 大きさは Pyxel 2.9.9 で実際にパッケージ化して測った値
ゲーム本体は 6 KB ほど。絵も音もコードも、この 1 枚に入っています
HTML 1 枚で完結——ただし、ネットは必要です できた HTML の 1 行目は、こうなっています。
<script src="https://cdn.jsdelivr.net/gh/kitao/pyxel@2.9.9/wasm/pyxel.js"></script>
ゲーム(6 KB)は埋め込まれていますが、Pyxel 本体は毎回ネットから読み込みます。 だからオフラインでは動きません。そしてバージョンが 2.9.9 と書き込まれているので、 あとで Pyxel を新しくしても、この HTML は作ったときのバージョンで動き続けます。

1-2. フォルダの中身は、全部そのまま公開される

pyxel package は、指定したフォルダの中身を丸ごと詰め込みます。 「起動スクリプトと、それが読むファイルだけ」を選んでくれるわけではありません。

実際に step1 フォルダをパッケージ化したら、中身はこうなりました。

入ったもの大きさこれは?
step1/candy_hunt.py10,190ゲーム本体。当然入る
step1/candy_hunt.pyxres589絵と音。当然入る
step1/.pyxapp_startup_script13Pyxel が作るメモ。 中身は candy_hunt.py という文字列だけ。どれで起動するかを記録している
step1/tempCodeRunnerFile.py67 これは要りません。VS Code の拡張機能が作った一時ファイルです
身に覚えのないファイルが、そのまま世界に公開されます tempCodeRunnerFile.py は、動作には影響しません。 ただし公開する HTML の中に、そのまま入って配られます
試し書きのメモ、書きかけの別バージョン、他人からもらった素材—— そのフォルダに置いたものは全部ついていくと考えてください。 パッケージ化の前に、フォルダを見て掃除するのを習慣にします。
なお __pycache__ フォルダ(Python が自動で作る中間ファイル)は Pyxel が自動で除いてくれます。これは気にしなくて大丈夫です(実測で確認)。
.gitignore に書いてあっても、パッケージには入ります このリポジトリの .gitignore には、すでに tempCodeRunnerFile.py が書いてあります。 それでもパッケージには入りました(実測)。
.gitignoreGit に対する「これは記録しなくていい」という指示であって、 ファイルを消すものではありません。pyxel package.gitignore を まったく見ていません。ディスクにあるものは、そのまま入ります。
「Git に無視させる」と「フォルダから消す」は別のこと—— ここは混同しやすいので、覚えておいてください。

1-3. 音のあるゲームを Web に出すときの決まり

ブラウザには、ユーザーが 1 度も操作していないページから音を出してはいけない という共通のルールがあります。広告が勝手に鳴り出すのを防ぐためのものです。

Pyxel はこれに合わせて、始める前に CLICK TO START をはさむ作りになっています。 このクリックが「ユーザーの操作」になるので、そのあとは自由に音を鳴らせます。

ページを開く 音は出せない CLICK TO START まだゲームは動かない クリック = ユーザーの操作 ゲーム起動 音が出せる クリックの前に音が鳴らないのは、故障ではなく仕様です。 Pyxel 側でこの画面が用意されているので、こちらで直すことは何もありません。
この 1 クリックがあるおかげで、コードを書き換えずにそのまま公開できます
Candy Hunt は、たまたま Web と相性のよい作りになっています BGM を鳴らし始める pyxel.playm() は、 フェーズ 9 で start_game() の中に置きました。 タイトル画面で Enter を押してから鳴り始めるということです。
Web で遊ぶ人から見ると、クリック → タイトル → Enter → 音が鳴ると進むので、 音が出るころにはとっくに操作が済んでいます。 「操作してから音を鳴らす」設計は、そのまま Web でも安全という覚え方ができます。

2. 使うコマンド

コマンドすること
pyxel package APP_DIR STARTUP_SCRIPT フォルダを .pyxapp 1 つにまとめる。 出力名はフォルダ名で決まる
pyxel play FILE.pyxapp できた .pyxapp を手元で動かして確かめる
pyxel app2html FILE.pyxapp .pyxapp を HTML 1 枚にする
python -m http.server 手元で Web サーバーを立てて、公開前の HTML を確かめる
出力名はフォルダ名で決まります pyxel package step1 step1/candy_hunt.py なら step1.pyxapp ができます(candy_hunt.pyxapp ではありません)。 1 つのフォルダに作品を 2 つ入れると名前がぶつかって上書きされます。 くわしくは備忘録の 1 つのフォルダに複数の作品があるにまとめてあります。

3. 手順

3-1. フォルダを掃除する

まず step1/ の中を見て、ゲームに要らないファイルを消します.gitignore に書いてあるかどうかは関係ありません(上の警告のとおりです)。

step1/
├── candy_hunt.py         ← 要る
├── candy_hunt.pyxres     ← 要る
├── tempCodeRunnerFile.py ← 消す(VS Code の拡張が作った一時ファイル)
└── __pycache__/          ← 消さなくてよい(Pyxel が自動で除く)

3-2. パッケージ化する

リポジトリのいちばん上step1 フォルダが見える場所)で実行します。

pyxel package step1 step1/candy_hunt.py

成功すると、追加されたファイルが 1 行ずつ表示され、 step1.pyxapp ができます。 ここに表示された一覧が、そのまま公開される中身です。目を通してください。

3-3. 手元で動かして確かめる

pyxel play step1.pyxapp

ブラウザにする前に、ここで必ず確かめます。 ここで動かなければ HTML にしても動きません。 とくに pyxel.load("candy_hunt.pyxres") のパスが合っているかは、 この段階で分かります。

3-4. HTML にする

pyxel app2html step1.pyxapp

step1.html ができます。

3-5. ブラウザで確かめる

python -m http.server

そのまま http://localhost:8000/step1.html を開きます。

HTML をダブルクリックで開いても動きません ファイルを直接開くと file:// という開き方になり、 ブラウザが wasm の読み込みを断ります。 必ず python -m http.server 経由(http://)で開いてください。 真っ黒のまま何も起きないときは、たいていこれです。

確かめること:

3-6. 公開する場所へ置く

step1.htmldocs/site/step1/candy_hunt.html という名前で置きます。 ファイル名がそのまま URL になるので、step1 ではなく作品名にします。

https://mrgarita.github.io/learning_pyxel/site/step1/candy_hunt.html
コピーではなく「移動」します pyxel app2html は、リポジトリの直下step1.html を作ります。 コピーで済ませると、直下にも 1 枚残ります。
.gitignore にある step1/*.htmlstep1 フォルダの中だけが対象なので、 直下の step1.html には効きません。 そのままにすると、git status に毎回顔を出します。 移動して、直下には残さないのがいちばん簡単です。
解説ページと同じフォルダに置きます docs/site/step1/ には phase1.htmlphase10.html が並んでいます。 そこに作品の HTML を 1 枚足す形です。 step0 も docs/site/step0/star_voyager.html と、同じ置き方をしています。

3-7. 全画面ボタンを足す

app2html が出す HTML には、全画面にする仕組みが入っていませんF11 も効きません(Pyxel がキー入力を横取りするため)。 ボタンを自分で足します。コードは備忘録の Web に公開した Pyxel 作品を全画面にしたい にあります。

HTML を作り直すたびに、足し直しになります pyxel app2htmlまっさらな HTML を上書き出力します。 手で足したボタンは毎回消えます。 ゲームを直して公開しなおすたびに、この作業が発生する——ということを覚えておいてください。 先に docs/site/step1/ へ置いてから、そこで足すと混乱しません。

3-8. リンクを張る

2 か所です。step0 のときに作った並びに、1 行足す形になります。

3-9. コミットして公開を確かめる

step1.pyxappstep1.htmlリポジトリの外に置いたままにします.gitignore*.pyxapp を書いてあります)。 コミットするのは docs/ の中に置いたほうです。

push して数分待つと、公開 URL で遊べるようになります。 古い内容が出るときは CtrlF5 で強制再読み込みしてください。

4. うまくいかないときは

公開まわりのトラブルは、step0 フェーズ 8 の一覧が そのまま使えます。ここではstep1 で新しく出るものだけ挙げます。

症状見るところ
公開した HTML に、身に覚えのないファイルが入っている pyxel packageフォルダを丸ごと詰めます。 掃除してからパッケージ化しなおします
CLICK TO START の前に音が鳴らない 仕様です。ブラウザは、操作されていないページから音を出しません
クリックしたのに、まったく音が鳴らない ① タブがミュートになっていないか(タブのスピーカーアイコン)。 ② .pyxres を保存してからパッケージ化したか。 保存前の .pyxres を詰めていると、手元では鳴るのに Web で鳴りません
矢印キーで動かない ゲーム画面を 1 度クリックします。 ブラウザは、選ばれている場所にしかキー入力を送りません
git statusstep1.html が出てくる リポジトリ直下に残っています。docs/site/step1/移動したか確認します (.gitignorestep1/*.html は直下のファイルには効きません)
全画面ボタンが消えた app2html をやり直したためです。手で足し直します(3-7)
ゲームを直したのに、公開版が古いまま package → app2html → 置きなおすの 3 つを全部やり直す必要があります。 .py を直しただけでは公開版は変わりません

5. step1 をふりかえる

10 フェーズで、1 本のゲームが最後まで通りました。 身についたことを並べておきます。

フェーズできるようになったこと
1・2ドット絵を描いて動かす。絵はコードではなくエディタで作る
3当たり判定と乱数。関数に切り出して戻り値を返す
4スコアの表示。数を覚えておく変数
5追いかける動き。相対位置による場合分け
6・7画面遷移。状態を変数で持ち、処理を振り分ける
8リストで複数を管理する。class の使いどころ
9。チャンネルの割り当て、鳴らすタイミングの設計
10公開。人に遊んでもらえる形にする
いちばん大きいのは「手ざわり」を直せるようになったこと 当たり判定を 4 に縮め、お化けの速さを動く回数で調整し、 出現時に点滅させ、音を重ならないように鳴らし分ける—— どれも「動く/動かない」ではなく、「気持ちいい/気持ちよくない」の調整です。 step1 で時間をかけたのは、ほとんどここでした。

6. 次の step

step2 は「倉庫番」です。10 ステージ制とタイトル画面をつけます。 step1 と大きく変わるのは、次の 2 点です。

step1 で作った土台——シーンの切り替え、当たり判定、リストでの管理、音の鳴らし分け——は、 そのまま step2 でも使います