ユーザ用ツール

サイト用ツール


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

文書の過去の版を表示しています。


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

あらすじ

2019年神奈山県立ハイ高等学校は 地盤が弱く校舎の老朽化も進んだため、 とうとう廃校にする以外方法がなく なってしまった。

ところで大変な情報を手に入れた。 それは、

「ハイ高校にATOMIC BOMBが仕掛けられている。」

と、いうものだ。 どうやらハイ高が廃校になった時、 気が狂った理科の先生がATOMIC BOMBを 学校のどこかに仕掛けてしまったらしい。

お願いだ。我が母校のコナゴナになった 姿を見たくはない。 早くATOMIC BOMBを取り除いてくれ……!!

行動は英語で、“<動詞>” 或いは、“<動詞>”+“<目的語>“のように入れていただきたい。 例えば、”look room”と入れれば部屋の様子を見ることが出来るという訳だ。

それでは Good Luck!!!…………

概要

PalmOS版を作ったときに、勢いで、HTML5バージョンを作ってしまえ、と、当時1)はやり始めていた HTML5に対応したバージョンを作成し始めた。

当時は、JavaScriptによるオブジェクトの取り扱いなどが今2)とは大きく異なっていたため、現在のバージョンとは全くと言って異なるコードになっていた。

しかも当時の Canvas への描画は遅く、ダブルバッファなどの使い方を追求する気もさらさらなかったため、グラフィックスの描画はサーバ側に置いたCGIで行い、JavaScriptからはこのCGIへのパラメータを生成してリクエストを投げるだけというスタイルで動作していた。

その後放置していたら、CGIが使用している Boost::Gil の仕様が変わっているわ、JavaScriptも大きく変わっているわで全く動かなくなってしまった。

そのまま放置でもいいかな、と思ったが、ググってみると旧Twitter3)これに言及している人がいたのを見つけてしまったので、なんとなく動かさないといけないような気がして、一気にコードを修正した。

なお、今現在4)、ゲームのセーブとロードに使っていた WebSQLが廃止されていたために、コードの修正中でセーブとロードが行えない。5)

また、画面に関するエフェクトも後回しにしている。6)7)

細かなバグが残っていて突然振り出しに差し戻されてしまうこともあるような気がする。 AsIs でシャレの分かる人のみプレイしてみてほしい。

ゲームはこちらから

あれこれ

画面の描画

上にも書いた通り、画像の生成には HTML5 の canvas 要素を使用している。 そもそも2012年ごろ公開したバージョンでも、実は、描画用のコード自体は存在していたのだが、テストしたらあまりに遅くて使い物にならなかったので、使用を取りやめて CGI方式にした。

とはいえ、ブラウザに搭載されたJavaScriptエンジンも高速化し続けているので、そろそろ行けるんじゃないかと思ったけれど、そのままでは行けなかった。

書き込みはそこそこいける。

正直ハイハイスクールアドベンチャーくらいのゲームなら十分だ。

だが、読み出しが入るとどうにもならないくらい遅くなる。 このゲームの画像描画の肝はペイントルーチンにあるといっても過言ではない。

そのペイントは境界検出のために画面データをなめまくるのだ。 じゃあ、メモリ上に置いといて、書き込みは処理が終わってまとめてやればいいんじゃないかということになるが、画像を RGBA形式で保持していると、結局読み出しが遅いのだ。

そもそもそんなに色数使わないので、8bitのインデックスを作ってペイントバッファとしてそれを使えばいいんじゃないかということに気づいてそのようにした。

なお、当初は、普通に一枚の canvasでやりくりしてたし、速度的には十分だったが、下に書くように、画面の表示領域をネイティブのサイズより大きくしたかったので、画面の canvas要素へ拡大転送するための canvasを作成して、ネイティブサイズ8)の画像はそこに描画されている。

画像を拡大せよ

このゲームのネイティブな画像サイズは 256×152 ピクセルしかない。 昔のPCなら十分な広さだ。 だが、今時のPCの画面にはさみしすぎる。 せめて倍で表示させたい。9)

ウェブページ上に 512×30410)で canvasを用意して、プログラム中ではネイティブサイズのダミーの canvas に書き込みを行い、倍サイズの表示領域に拡大転送することでこれを実現している。

this.zctx = document.getElementById("HHSAdv").getContext('2d');
this.zctx.imageSmoothingEnabled = true;
this.zctx.mozImageSmoothingEnabled = true;
this.zctx.webkitImageSmoothingEnabled = true;
this.zctx.msImageSmoothingEnabled = true;

this.width = 256;
this.height = 152;
this.canvas = document.createElement("canvas");
this.canvas.width = this.widht;
this.canvas.height = this.height;
this.bitmap = new Bitmap(this.width * this.height); // 描画用バッファ
...
this.context.putImageData(this.bitmap, 0, 0); // バッファの内容をネイティブサイズの canvasに書いてから
this.zctx.drawImage(this.canvas, 0, 0, this.width, this.height, 0, 0, this.zctx.canvas.width, this.zctx.canvas.height); // それを拡大して画面に書き込む

クラスとかラムダ式とか

2011年ごろの JavaScript によるオブジェクト指向プログラミングというと、クラスも何もなくて、普通の変数の宣言を利用してやっていたのが実態であった。

var Klass = function()
{
    this.member = "abc";
    this.hello = function()
    {
        console.log("Hello World!");
    };
}

var k = new Klass();
k.hello();

こんな感じのコードで、まあコードの管理も大変だった。 しかも、いつの間にかエラー吐いて動かなくなっちゃったし。

今時は普通に class を使うということなので全面的に書き直した。

なお、もうひとつ大きな変更としてはXMLHttpRequestが非推奨になっちまってたこと。 基本的にデータファイルも、CGIで描画させた画像もこの枠組みを使ってやりとりしていたので、これも大きかった。

var req = new XMLHttpRequest();
req.open('GET', 'cgi/loadB64.rb?name=" + name, true);
req.onload = function()
{
...
};
req.send();

みたいなことをしていたのだが、今時はこれも fetch()でやるのが正しいらしいのでそのようにする。 しかも、xxx = function(){} みたいなのも古いらしい。 これはラムダ式を使うのが今風なんだと。

fetch('data/xxx.dat').then((res) => res.blob()).then((blob) => blob.arrayBuffer()).then((abuf) => {
    var buf = new Uint8Array(abuf); // arrayBuffer型はそのままでは利用できないので適当な形式にする。
...
});

みたいなコードになる。 本当は resを受け取ったら、res.ok かどうかを検証するべきなんだけれど、ファイルの読み取りエラーはなしってことでサボってる。 .then().then() って続いているのは、それぞれ、非同期通信になるので、値がちゃんとやってきてから次段へ進むためにこうなってる。 全部をひとまとまりでやろうとするとうまく動かない。

fetch('data/xxx.dat').then((res) => {
    if (res.ok)
    {
        var blob = res.blob();
        var abuf = blob.arrayBuffer();
        var buf = new Uint8Array(abuf);
        ...
    }
});

このコードは同期がとれてないので動かない。 というかbufに中身は入ってこないのだ。

データベースとか

このゲームのデータはサーバ側には保存されない。 最初の版では Web SQLを使って、ブラウザ内のdbに保存していたが、ぼーっとしている間に、HTML5に入れなかった Web SQLは廃止されてしまった。

廃止されてしまったので、代わりを探さなければならない。 代わりになるものは indexedDBで、ハッシュを保存できるようだ。

とりあえず実装してみたが、どうも保存データの上書きがうまくいってないような気がする。

データをDBに格納する際に、objectStore.add(data) とすると、挿入のみ可能で、データがあると失敗するが、objectStore.put(data) とすれば、挿入または置換が可能となる。

最初、add()でやってたが、もちろん put()に直して、上書きもきちんとされるようになった。

1)
2011年ごろ
2)
2024年
3)
X
4)
2024年2月13日
5) , 7)
2024年2月13日実装済み
6)
ゲームオーバーや電池が少なくなったりしない限りは遭遇しないが
8)
256×152ピクセル
9)
QTはそのままで放置しているが?
10)
要するに倍のサイズ
ハイハイスクールアドベンチャー_web版.1707861110.txt.gz · 最終更新: 2024/02/14 06:51 by araki