ユーザ用ツール

サイト用ツール


ハイハイスクールアドベンチャー_web版

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
ハイハイスクールアドベンチャー_web版 [2024/02/14 13:44] – [データベースとか] arakiハイハイスクールアドベンチャー_web版 [2024/02/16 10:12] (現在) – [PWA] araki
行 38: 行 38:
 [[https://www.wildtree.jp/~araki/HHSAdv/|ゲームはこちらから]] [[https://www.wildtree.jp/~araki/HHSAdv/|ゲームはこちらから]]
  
 +PWA対応なので、インストールして遊んでくれてもいいんだよ!
 +
 +{{::hhsadv:pwa_install.png?400|}}
 +
 +インストールはアドレスバーの右端にあるボタン、またはブラウザのメニューから。
 +
 +{{::hhsadv:game_screen.png?400|}}
 +
 +いうまでもないが、画面真ん中あたりの「どうする?」の隣にあるテキストボックスにコマンドを入れて enter である。
 ===== あれこれ ===== ===== あれこれ =====
  
行 169: 行 178:
  
 Save/Loadはある意味重要な機能((デバッグプレイするときにいちいち校舎の前からやってられないから。))なので、動くようになって捗った。 Save/Loadはある意味重要な機能((デバッグプレイするときにいちいち校舎の前からやってられないから。))なので、動くようになって捗った。
 +
 +=== トラブルシュート ===
 +
 +
 +原因はよくわからないがDBが壊れることがあるようである。
 +そんなときは、Chromeの系譜なら F12を押して DevTool を呼び出し、"Application"タブにある Storage の中から IndexedDBを選び、objectStore "hhsadvdb" を選んで削除すればいい。
 +
 +勿論データは失われてしまうが、以後、load/save はできるようになる。
 +
 +{{::hhsadv:devtool_storage.png?400|}}
  
 ==== PWA ==== ==== PWA ====
行 179: 行 198:
 あと、あまり触れられていないけれど、インストールされたアプリの顔となるアイコンに適切なサイズのものがないとインストールボタンが表示されないので、これも重要な要素である。((知らねーよ。そんなことどこの解説ページにも書いてなかったんだから!)) あと、あまり触れられていないけれど、インストールされたアプリの顔となるアイコンに適切なサイズのものがないとインストールボタンが表示されないので、これも重要な要素である。((知らねーよ。そんなことどこの解説ページにも書いてなかったんだから!))
  
 +=== Manifest ===
 +
 +PWAに不可欠なもので、アプリケーションとしてのウェブページの詳細を記述したものになる。
 +形式はJSON形式で、manifest.json とか xxx.webmanifest とかといった名前であることが多いようである。
 +
 +マニフェストファイルは、HTMLファイルの linkタグを使って次のようにマッピングする。
 +
 +<code>
 +<link rel="manifest" href="hhsadv.webmanifest" />
 +</code>
 +
 +そして、マニフェストファイルそのものの中には、とりあえず以下のような内容を記述する。
 +もっと詳細な仕様を記述できるが、詳しくは[[https://developer.mozilla.org/ja/docs/Web/Manifest|こちら]]などを参照してほしい。
 +
 +<code>
 +{
 +        "background_color": "black",
 +        "description": "High High School Adventure WEB",
 +        "display": "standalone",
 +        "icons": [
 +                {
 +                        "src": "icon/isako.png",
 +                        "sizes": "72x72",
 +                        "type": "image/png"
 +                },
 +                {
 +                        "src": "icon/isako144.png",
 +                        "sizes": "144x144",
 +                        "type": "image/png"
 +                }
 +        ],
 +        "name": "ハイハイスクールアドベンチャー",
 +        "short_name": "HHSAdv",
 +        "start_url": "index.html"
 +}
 +</code>
 +
 +=== Service Worker (JavaScript) ===
 +
 +PWAを構成するもうひとつの要素が Service Workerになる。
 +JavaScriptで、Service Workerを登録してやる必要がある。
 +
 +色々、凝った挙動などをさせることもできるようだが、とりあえず、アプリになればいい、というような向きには、最低限の内容でよさそうである。
 +
 +なお、キャッシュアイテムについては、相対パスでも絶対パスでもフルのURIでも構わないが、取得できない((404とか403のエラーを返す))ようなものがあると、インストールに失敗するので必ずすべてのアイテムがアクセス可能なことを確認すること。
 +
 +Service WorkerもHTMLファイルから登録してやる必要がある。
 +
 +<code>
 +if ('serviceWorker' in navigator)
 +{
 +    navigator.serviceWorker.register('sw.js');
 +}
 +</code>
 +
 +Service Worker本体((ここでは js/sw.js))も最低限だと以下のようになる。
 +
 +<code>
 +// cache
 +var CACHE_NAME = 'hhsadv-caches';
 +var urlsToCache = [
 +        'ending.html',
 +        'game.html',
 +        'index.html',
 +        'opening.html',
 +        'css/default-style.css',
 +        'data/data.dat',
 +        'data/highd.com',
 +        'data/map.dat',
 +        'data/rule.dat',
 +        'data/thin.dat',
 +        'js/UserData.js',
 +        'js/dictionary.js',
 +        'js/ga.js',
 +        'js/graphics.js',
 +        'js/message.js',
 +        'js/zSystem.js',
 +        'js/database.js',
 +        'js/engine.js',
 +        'js/global.js',
 +        'js/map.js',
 +        'sw.js'
 +];
 +
 +// install
 +self.addEventListener('install', (event) =>
 +        event.waitUntil(
 +                caches.open(CACHE_NAME)
 +                .then((cache) => cache.addAll(urlsToCache))
 +        )
 +);
 +
 +// refresh
 +self.addEventListener('fetch', (event) => {
 +        event.respondWith(
 +                caches.match(event.request)
 +                .then((res) => {
 +                        return res ? res : fetch(event.request);
 +                })
 +        );
 +});
 +</code>
 +
 +要はキャッシュを登録しているだけである。
 +これでオフラインでも使えるようになるらしい((そのように作られていれば))が、やってみていないのでわからない。
 +
 +なお、キャッシュされるオブジェクトの指定は、sw.jsのある場所からの相対パスまたは絶対パス、URIなどで、これを間違うとエラーをはいてキャッシュに失敗する。
 +
 +ブラウザによってはsw.jsがエラーを出しているとインストールボタンを表示してくれない厳格なやつもいたりするので、よく確認してほしい。
 +
 +=== トラブルシュート ===
 +
 +Manifest周りに問題がありそうなときは、Chromeの系譜であれば F12で DevToolを呼び出し、Applicationのタブから Manifestを選んで、エラーや Warningがないか、そもそも読み込まれているのかを確認するといい。
 +上記のアイコンの問題もここに「デスクトップだったら144x144以上のサイズのアイコンがないとだめ」って出てたので問題を認識・解決できた。
 +
 +{{::hhsadv:devtool_manifest.png?400|}}
 +
 +==== 音とか ====
 +
 +PalmOS、Android、そして Qtでは音がある場面では音が鳴るようになっている。
 +Web版を再公開したときに、「誰か解けたのか?」というようなことをつぶやくと「校歌は歌った」というような返事があった。
 +そういえばWeb版では音のことをすっかり失念していた。
 +
 +HTML5ではaudioコンポーネントがあり、JavaScriptに Audioクラスが実装されている。
 +そしてほとんどすべてのモダンなブラウザでMP3形式の音源を鳴らすことができる。
 +
 +=== 音を鳴らせ ===
 +
 +HTMLで audio 要素を配置してもいいのだが、別に画面上に何かがいる必要はないので、適宜動的に確保する方向で実装する。
 +動的に確保された Audio のインスタンスは再生が終わったらガベージコレクションの対象になるって書いてあるので、音を鳴らすときに確保して、鳴らしたら勝手に消えることを期待する。
 +
 +<code>
 +var m = new Audio();
 +m.src = this.base_uri + "/data/" + ZAudio.sources[n] + ".mp3";
 +m.load();
 +m.volume = 1.0;
 +m.loop = false;
 +m.play();
 +</code>
 +
 +ボリュームは1.0が100%になる。
 +
 +=== 音を鳴らすな ===
 +
 +多分、音鳴ったら困る環境の人も少なくないだろう。
 +いきなり、ハイハイスクールの校歌が流れたらびっくりするだろうし、大体が、この校歌結構長尺で鳴り出すと止まらないのだ。
 +
 +なので、ミュート機能はつけておいた方がいいと判断した。
 +まあ、PCなり、スマホなりでミュートできるだろうけれど。
 +どっちかというと、ミュートというよりデフォルトでミュートしておいて、鳴らしたい人だけ解除するイメージだ。
 +
 +まあ、単純にチェックボックスを一個置いておけばいいのだが、今時のインターフェイスとしてはちょっとカッコ悪い。
 +そもそもこの昭和レトロなアドベンチャーゲームに何をいっているんだという向きもあるだろうが、せっかくなので、今風のスライドスイッチにしておきたい。
 +
 +Safariなら、そういう要素がサポートされているらしいが、多くのブラウザでは未サポート((2024年2月現在))なので、別の方法でやることにする。
 +
 +世の中には優れた人が多くいて、既にCSSを駆使して、そういうものをチェックボックスに付加してくれているので、まるっとそれをいただくことにする。
 +
 +<code>
 +<label for="mute" class="switch_label">
 + <div class="switch">
 + <input type="checkbox" id="mute" checked="true" />
 + <div class="circle"></div>
 + <div class="base"></div>
 + </div>
 + <span class="title">MUTE</span>
 +</label>
 +</code>
 +
 +チェックボックスがスイッチの本体だが、チェックボックスを消して、代わりに circleと baseでスイッチを構成する。
 +この部分はすべてCSSに記述されている。
 +
 +<code>
 +.switch {
 + position: relative;
 +}
 +
 +.switch_label {
 + display: flex;
 + align-items: center;
 +}
 +
 +.switch input[type='checkbox'] {
 + position: absolute;
 + width: 0;
 + height: 0;
 +}
 +
 +.switch .base {
 + width: 28px;
 + border-radius: 8px;
 + height: 16px;
 + background-color: #ddd;
 +}
 +
 +.switch .circle {
 + position: absolute;
 + top: 2px;
 + left: 2px;
 + width: 12px;
 + height: 12px;
 + border-radius: 6px;
 + background-color: white;
 + transition: 0.5s;
 +}
 +
 +.title {
 + margin-left: 4px;
 +}
 +
 +.switch input:checked ~ .base {
 + background-color: rgb(219, 234, 254);
 + transition: 0.5s;
 +}
 +
 +.switch input:checked ~ .circle {
 + transform: translateX(100%);
 + background-color: blue;
 +}
 +</code>
 +
 +なお、実際に使用しているスタイルシートは、レスポンシブデザインっぽく、px使わないでサイズを指定しています。
 +
 +==== 設定 ====
 +
 +基本的には、特に設定項目はなかったのだが、音を鳴らすことにしたら、Qt版同様に、音を鳴らすのかどうかを覚えておいた方がいいような気がしてきた。
 +
 +まあ、毎回 Mute ONにしてしまうでもいいような気もしたが、将来何かの設定を追加したときに、それも覚えておいた方がいいような気がしたので、保存できるようにした。
 +
 +ゲームデータ保存用objectStoreはIndexedDBに作ってあったので、バージョンを2にして、設定用のobjectStoreも作るようにした。
 +DBのアップグレードとかしないと思ってたが、いきなりすることになるとは先見の明がなさ過ぎた。
 +
 +<code>
 +const req = indexedDB.open(Database.DBNAME,Database.VERSION);
 +req.onupgradeneeded = (event) =>
 +{
 + const db = event.target.result;
 + const oldver = event.oldVersion;
 + const newver = event.newVersion;
 + const migrations = {
 + "1": () => {
 + db.createObjectStore(Database.STORENAME, {keyPath:'id'});
 + },
 + "2": () => {
 + db.createObjectStore(Database.PREFSTORE, {keyPath:'pref'});
 + }
 + }
 + for (var v = oldver + 1 ; v <= newver ; v++)
 + {
 + if (migrations[v]) migrations[v]();
 + }
 +};
 +</code>
  
 +バージョン更新のやり方は、どこかで見かけたのを参考にした。
ハイハイスクールアドベンチャー_web版.1707885891.txt.gz · 最終更新: 2024/02/14 13:44 by araki