2026年1月18日日曜日

スクリプト要素~eventpaint関数とshippai関数~

 どうも、東京経済大学のさいがやんです。

前々回から、おまつりゲームのソースコードのscript要素の中身について書いています。script要素の中では、最初にグローバル変数を定義し、init関数、fieldkeydown関数、fieldpaint関数、eventpaint関数、shippai関数があります。

今回は、eventpaint関数とshippai関数を紹介します。また、別のHTMLファイルにある関数も紹介します。🙂


eventpaint関数

前回紹介したfieldkeydown関数は、主人公の移動先によってはfieldpaint関数を呼んだり、さらにeventpaint関数を呼んだりします。ここで紹介するeventpaint関数は、人に話しかけるときなどに会話を表示させるための関数です。例えばこのような画面を出すものです。


ソースコードを見てみましょう。

function eventpaint(evnum) {
            window.removeEventListener("keydown", fieldkeydown);
            setTimeout(ugoku, 800);
            function ugoku() { window.addEventListener("keydown", fieldkeydown); }
▲まず、会話するマスにたどり着いた時に、0.8秒間そのマスから動けなくします。ゲーム開発当初はこの設定をしていなかったのですが、それだと遊ぶときにキーを長押しや連打していると会話が一瞬しか見られないことが分かったため、少し止めるようにしました。

 kaka.play();
 gc.fillStyle = "Black";
 gc.fillRect(200, 20, 400, 400);
 gc.fillStyle = "White";
 gc.font = "12px meiryo";
▲次に、「カカッ」というような音声を再生して、黒い正方形で背景を描画します。文字は白の12px、メイリオに設定します。

  switch (evnum) {
      case 22: //やぐひだり
          gc.drawImage(kuchikiki, 325, 30, 150, 150);
          if (flag08 == false) {
              flag08 = true;
              gc.fillText("ひと 「ふたりとも、おどってくれてありがとうな。", 250, 200);
              gc.fillText("かきごおりやさんに くちききしてやるから、", 285, 230);
              gc.fillText("たべて いきなよ。」", 286, 260);
              gc.fillText("みずほ「いいの? ありがとう!!」", 250, 330);
              gc.fillText("ぼく 「ありがとうございます!」", 250, 360);
          }
          else if (flag08 == true && flag09 == false) {
              gc.fillText("ひと 「かきごおり たべていってね」", 250, 200);
              gc.fillText("みずほ「うん!」", 250, 230);
          }
          else if (flag09 == true) {
              gc.fillText("ひと「また おどりに きてくれたんだね」", 250, 200);
          }
          break;
▲switch文で、マスにふられた番号ごとに、描画する画像や会話内容を書いていきます。(会話内容をbody要素に書く方法もあるのですが、私はscript要素に書いています。)上記のコードは、やぐらで踊っている左側の人に話しかけたときの内容です。ストーリーがどこまで進んだかによって会話内容を変えます。この人はストーリー展開のきっかけになる人なので、flag変数の切り替えも含まれています。

ちなみに、クレープ屋さんは唯一ゲームオーバーになりうるポイントです。
case 44: //クレープ
                   
        //(中略)

          else if (flag01 == true && flag02 == false && flag03 == true && flag04 == false) {
              pay++;
              if (pay < 3) {
                  flag04 = true;
                  gc.drawImage(crape, 325, 30, 150, 150);
                  gc.fillText("600えんで もういちどクレープをかった", 250, 200);
              }
              else { shippai() }
          }
          else if (flag02 == true && flag05 == false) {
              pay++;
              if (pay < 3) {
                  flag05 = true;
                  gc.drawImage(mizuho, 325, 30, 150, 150);
                  gc.drawImage(crape, 330, 70, 60, 60);
                  gc.fillText("みずほ  「クレープください!」", 250, 200);
                  gc.fillText("てんいん「はい、600えんね。どうぞ」", 250, 230);
                  gc.fillText("みずほは クレープをたべて うれしそうだ」", 250, 290);
              }
              else { shippai() }
          }
                   
        //(中略)

          break;
▲主人公がクレープ屋さんに支払おうとした回数が3回以上(つまり残高不足)になるとshippai関数を呼びます。

shippai関数

shippai関数は、クレープを買えなくなってゲームオーバーになったとき用の関数です。このような画面を出すものです。


ソースコードを見てみましょう。

function shippai() {
            gc.fillStyle = "Black";
            gc.fillRect(200, 20, 400, 400);
            gc.fillStyle = "White";
            if (flag02 == false && pay == 3) { //ぼくだけ
                gc.font = "36px serif";
                gc.fillText("GAME OVER", 280, 100);
                gc.font = "14px meiryo";
                gc.fillText("てんいん「ざんだかが たりません。」", 250, 290);
                gc.fillText("ぼく  「えっ・・・」", 250, 320);
                gc.fillText("1200えんを むだにしてしまった", 250, 360);
                gc.drawImage(bikuboku, 300, 85, 200, 190);
                window.removeEventListener("keydown", fieldkeydown);
            }
▲ぼくが単独でいるときにゲームオーバーになる場合のコードです。eventpaint関数での描画のしかたと大差ありません。

seikou関数

ゲームクリアの画面を表示するためにseikou関数を作ったのですが、同じHTMLファイルの中に置くと、キーダウンされた時にもとの画面に戻ってしまうため、ファイルを分けました。seikou関数は別のHTMLファイルのscript要素の中にあります。以下がソースコードです。

function seikou(){

gc.fillStyle = "rgba(180, 180, 180, 1)";

gc.fillRect(200, 0, 400, 440);

gc.fillStyle = "rgba(255, 255,0,1)";

gc.font = "50px pop";

gc.fillText("帰宅成功!", 290, 80);

gc.fillStyle = "black";

gc.font = "18px meiryo";

gc.fillText("ぼく&みずほ「ただいま~!」", 290, 415);

gc.drawImage(ie, 250, 90, 300, 300);


そして、この画面が出ます。
ファイルが切り替わる時に一瞬画面が消えますが、それは許容範囲だと思って放置しています。


おそらくこれが最後の投稿だと思います。見てくださった方、ありがとうございました!!

<参考文献>
・田中賢一郎『ゲームで学ぶ JavaScript 入門』インプレス、2015年
・田中賢一郎『ゲームを作りながら楽しく学べる HTML5+CSS+JavaScript』インプレス、2017年
・田中賢一郎『ゲームで学ぶ JavaScript 入門 増補改訂版~ブラウザゲームづくりでHTML&CSSも身につく!』インプレス、2022年

2026年1月16日金曜日

スクリプト要素~fieldpaint関数とfieldkeydown関数~

どうも、東京経済大学のさいがやんです。

前回から、おまつりゲームのソースコードのscript要素の中身について書いています。script要素の中では、最初にグローバル変数を定義し、init関数、fieldkeydown関数、fieldpaint関数、eventpaint関数、shippai関数があります。

今回は、fieldpaint関数とfieldkeydown関数を紹介します。ついでに、ストーリーに合わない仕様を直したことを記録します。


fieldpaint関数

fieldpaint関数はマップや主人公を描画します。init関数やfieldkeydown関数の中でfieldpaint関数が呼び出されます。

function fieldpaint() {
            gc.fillStyle = "rgba(160, 160, 150, 1)";
            gc.fillRect(0, 0, 800, 440);

▲fieldpaint関数ではまず、キャンパス全体を灰色っぽくしています。これがそのまま、校庭の色になります。


            var y, x;
            for (y = 0; y < map[stage].length; y++) {
                for (x = 0; x < map[stage][y].length; x++) {
                    var mpt = map[stage][y][x];
                    if (mpt ==01) { //もん
                        gc.drawImage(mon, x * 40, y * 40, 40, 40);
                    }
                    else if (mpt ==02) { //き
                        gc.drawImage(ki, x * 40, y * 40, 40, 40);
                    }
                    else if (mpt ==04) { //ちゃり
                        gc.fillStyle = "rgba(150, 220, 240, 1)";
                        gc.fillRect(x * 40, y * 40, 40, 40);
                        gc.drawImage(chari2, x * 40, y * 40, 40, 40);
▲次に、表示するステージ(マップ0~5のどれか)の配列の要素番号が格納されるものをy、さらにその中の配列の要素番号が格納されるものを変数xとします。for文とif文を使って、色や画像をつけた40px四方のマスを、横20個×縦11個描画していきます。

            if (flag01 == true && flag02 == false) {  //主人公
                gc.drawImage(boku, px * 40, py * 40, 40, 40);
            }
            else {
                gc.drawImage(shujinkou2, px * 40, py * 40, 40, 40);
            }
▲主人公を描画します。

for (y = 0; y < map[stage].length; y++) {  //暗闇
                for (x = 0; x < map[stage][y].length; x++) {
                    var mpt = map[stage][y][x];
                    if (mpt ==03 || mpt == 31 || mpt == 51 || mpt == 52 || mpt == 68 || mpt == 73) {
                        gc.fillStyle = "rgba(50, 50, 40, 0.65)"; //かげ
                        gc.fillRect(x * 40, y * 40, 40, 40);
                    }
                }
            }
▲校庭の暗闇部分を半透明の暗い灰色で描画します。暗闇にいる主人公を見えにくくするため、主人公の後に上から描画します。

fieldpaint関数は以上です。

fieldkeydown関数

init関数でキーダウンイベントが登録されたので、キーが押されるとfieldkeydown関数が実行されます。fieldkeydown関数は、主人公が移動するための関数です。
function fieldkeydown(e) {
            var dx = px, dy = py;
            switch (e.keyCode) {
                case 37: dx--; break;
                case 38: dy--; break;
                case 39: dx++; break;
                case 40: dy++; break;
            }
▲変数dx,dyは、主人公の移動先候補を表します。switch文で、上下左右のキーと、x,y座標の増減を対応させます。

var mpt = map[stage][dy][dx];
            if ((mpt == 20 || mpt == 21 || mpt == 23) && flag07 == true) {
                px = dx;
                py = dy;
                fieldpaint();
            }
            else if (mpt == 22 && flag07 == true) {
                px = dx;
                py = dy;
                fieldpaint();
                eventpaint(mpt);
            }
▲移動先候補の座標を、移動先の座標に入れて、fieldpaint関数に描画を頼みます。さらに、移動先のマスでキャラクターと話したりする場合はeventpaint関数も呼びます。

しかし、移動先候補のマスが木や壁のときは特に何もしませんし、画面遷移が必要なときはまた別の処理をします。そのコードの記載は省略します。

修正箇所

関数の説明とは無関係ですが、ぼくが一人でいるときに正門から出ようとすると、こんな画面が出てきてしまうことを発見しました。
これでは、みずほが瞬間移動して正門にきていることになってしまい不自然です。場面によっては、トイレにいるみずほが、瞬間移動で正門に来てトイレに戻る、ということにもなりえます。これではよろしくないので、変えました。
この画面を新しく追加し、解決しました。

<参考文献>
・田中賢一郎『ゲームで学ぶ JavaScript 入門』インプレス、2015年
・田中賢一郎『ゲームを作りながら楽しく学べる HTML5+CSS+JavaScript』インプレス、2017年
・田中賢一郎『ゲームで学ぶ JavaScript 入門 増補改訂版~ブラウザゲームづくりでHTML&CSSも身につく!』インプレス、2022年

2026年1月12日月曜日

スクリプト要素~グローバル変数とinit関数~

  (※2026/01/17更新…変数mapの配列の長さを書き直しました。誤「5」→正「6」)

どうも、東京経済大学のさいがやんです。

今回からは、おまつりゲームのソースコードのscript要素の中身について書きます。script要素の中では、最初にグローバル変数を定義し、init関数、fieldkeydown関数、fieldpaint関数、eventpaint関数、shippai関数があります。

今回は、グローバル変数とinit関数を紹介します😄


グローバル変数

script要素では初めにグローバル変数を定義しています。

定義するグローバル変数は、以下の通りです。

・map…map0, map1, map2, map3, map4, map5の6つの要素で構成されます。map0~5それぞれでは、11個の要素が縦方向に並んだ配列があり、さらにその中でに20個ずつの要素が横方向に並んだ配列があります。

・cv…キャンバスを描画するのに使う変数です。

・gc…二次元描画ツールを使えるようにするための変数です。

・stage…map0~5の数字部分にあたります。画面遷移のときに使います。

・px, py…主人公がいる場所のマスを表す変数です。

・pay…初期値が0で、ぼくがクレープ屋さんに代金を支払う場面の度に1ずつ増えます。3回目に買おうとするとpayが3になり、ゲームオーバーとなります。


以下はflag変数です。全部で9つありますよ。

・flag01…falseのとき、校舎のドアの前にいるこどもに話しかけるとtrueに切り替わります。このタイミングで、みずほがトイレに行き、ぼくの単独行動が始まります。

・flag02…flag01がtrueになった後、ひとりでいるぼくみずほと合流したらflag02がtrueに切り替わります。合流場所は、2階のトイレか、暗闇かの2パターンあります。

・flag03…flag01がtrueで、flag02がまだfalseのとき、ぼくが初めて単独でクレープを購入するとflag03がtrueに切り替わります。このタイミングで、みずほと校舎前にいたこどもは、暗闇に行って鬼ごっこを始めます。

・flag04…このflag変数だけ、初期値はtrueです。flag02がfalse、flag03がtrue、かつflag04がtrueであるときに限って、ぼくが単独でクレープを持っている状態になります。その状態のときにみずほと合流しようとすると、鬼ごっこの鬼にぶつかられてクレープを落とし、flag04がfalseに切り替わります。みずほと合流する前にまた単独でクレープを買うと、flag04がtrueに戻ります。

・flag05…flag02がtrueで、変数payが2以下のとき、ふたりでクレープを買ってみずほが食べると、flag05がtrueになります。ここからは、みずほがかき氷を欲しがるようになります。

・flag06…flag05がtrue、flag06がfalseのとき、やぐらの左のほうで踊っている人に声をかけると、flag06がtrueになります。

・flag07…flag06がtrue、flag07がfalseのとき、やぐらを作った職人に話かけると、flag07がtrueになります。また、このタイミングで、主人公がやぐらに上れるようになります。

・flag08…flag07がtrueで、flag08がfalseのとき、やぐらの上にいる人と話すと、flag08がtrueに切り替わります。この人が口利きしてくれたことによって、かき氷屋でかき氷ひとつ無料でもらえるようになります。

・flag09…flag08がtrueで、flag09がfalseのとき、かき氷を貰うとflag09がtrueになります。これでみずほが満足し、おまつりから帰れるようになります。


グローバル変数は以上です。flag変数だらけですね🙄


init関数

お次は、init関数です。init関数では、おまつりゲームの開始画面を表示したり、fieldpaint関数を実行させたり、キーを押すイベントを登録したりします。

何をしているか細かく見ていきます。

cv = document.getElementById("field");    ←キャンバス要素をcvに代入。


gc = cv.getContext("2d");  ←二次元描画ツールを取得。


gc.fillStyle = "Black";  ←黒で、

gc.fillRect(0, 0, 800, 440);  ←背景を描画する。


gc.drawImage(shujinkou2, 550, 100, 240, 240);  ←主人公ふたりを描画。


gc.fillStyle = "White";  ←白で、

gc.font = "18px meiryo";  ←18pxのメイリオで、以下を描画する。

gc.fillText("ぼくは、むすめの”みずほ”に つれられて おまつりにきた。", 100, 200);

gc.fillText("ぼくは いま、こうつうけいICしか もっていない。", 100, 240);

gc.fillText("みずほを まんぞくさせて、いえに かえりたい。", 100, 280);


window.addEventListener("keydown", kaishi);  ←キーを押せば関数kaishiを実行するイベントを登録。


ここまでの段階で出る画面がこちら。(黒背景よりも下に書いてある説明書きは、body要素の中のp要素で書きました。)


そして、この画面のときにキーを押すと、関数kaishiが実行されます。

function kaishi(a) {  ←関数kaishi。aにはキー押下の情報が入っています。

window.removeEventListener("keydown", kaishi);  ←イベント削除。

setInterval(function(){taiko.play()}, 410);  ←音源を0.41秒ごとに再生。

fieldpaint();  ←関数fieldpaintを呼ぶ。

window.addEventListener("keydown", fieldkeydown);  ←キーを押せば関数fieldkeydownを実行するイベント登録。

}    ←関数kaisihi終了


ちなみに、関数kaishiで関数fieldpaintが呼び出されて実行された段階で表示される画面はこうなります。

この時の画面はmap3です。主人公の位置は、一番左・上のマスを0だとして、左から7マス目、上から9マス目です。これらは、グローバル変数で定義したstage=3, px=7, py=9 に対応していますね。


次回は、おまつりゲームの中の、他の関数を紹介します!

<参考文献>
・田中賢一郎『ゲームで学ぶ JavaScript 入門』インプレス、2015年
・田中賢一郎『ゲームを作りながら楽しく学べる HTML5+CSS+JavaScript』インプレス、2017年
・田中賢一郎『ゲームで学ぶ JavaScript 入門 増補改訂版~ブラウザゲームづくりでHTML&CSSも身につく!』インプレス、2022年

スクリプト要素~eventpaint関数とshippai関数~

 どうも、東京経済大学の さいがやん です。 前々回から、おまつりゲームのソースコードのscript要素の中身について書いています。script要素の中では、最初にグローバル変数を定義し、init関数、fieldkeydown関数、fieldpaint関数、eventpaint関...