何かの箱

07.ゲームにする

上:t, 下:b, 左:f, 右:h *操作が反映されない場合、画面部分を一度クリックしてみてください

ゲームにする

自機が動かせるようになりました。敵が動きながら弾を発射してきます。狙いが甘いのでなかなか当たりませんが、とりあえず避けていられたフレーム数をそのままスコアにしてしまいましょう。 弾の当たり判定は、テキストということもあり自機の座標に特定の文字があるかどうかで判断します。 そのため弾の文字を変えました。 今回はタイトル画面とかゲームオーバーとかのシーンを用意していませんので、ゲームを止めるかわりに確認ダイアログを利用しました。 その後初期化しています。
        /* 前略 */
        let score = 0;
        /* 中略 */
                createMoveObject(createImageData(['+']), this.x + 1, this.y + 1, function () {
        /* 中略 */
        function gameFrame() {
          let loop = true;
        /* 中略 */
          if (screen.getData(Math.floor(myship.x) + Math.floor(myship.cx), Math.floor(myship.y) + Math.floor(myship.cy)) == '+') {
            loop = confirm(`score:${score}\nreplay ?`);
            score = 0;
            bullets = [];
            screen.key.evStat = 0;
          }
          if (loop) {
            screen.setData(0, 0, "" + (++score));
            const delta = performance.now() - t;
            setTimeout(gameFrame, spf - delta);
          }
        /* 以下略 */
      
cs,cyという変数はこれまで用意していませんでした。前回にちょっと言及した中心点というかそういう感じの座標補正です。 当たり判定というか、もう画面上の座標の文字だけで判定しています。テキストゲームあるあるです。
        /* 前略 */
        function createMoveObject(imgData, px = 0, py = 0, moveFunction, cx = 0, cy = 0) {
          const moveObject = Object.create(imgData);
          return Object.defineProperties(moveObject, {
            move: {value: moveFunction},
            type: {value: 0, writable: true}, // 将来的に何かに使えるかも
            x: {value: px, writable: true}, y: {value: py, writable: true},
            cx: {value: cx, writable: false}, cy: {value: cy, writable: false},
        /* 以下略 */
      
これに合わせて、位置情報の取得も少し変更します。
        /* 前略 */
        function getPosInfo(base, target) {
          const dx = (target.x + target.cx) - (base.x + base.cx);
          const dy = (target.y + target.cy) - (base.y + base.cy);
        /* 以下略 */
      

難易度を動的に変更する

ゲームにするので、徐々に難易度を上げていくことにします。 スコアによって変えていくことにしましょう。
        /* 前略 */
        const enemy = createMoveObject(
        /* 中略 */
            this.counter = 30 - (score / 30);
        /* 以下略 */
      
これで徐々に弾を発射する間隔が短くなり、最終的にはフレーム単位で毎回発射するレベルになるでしょう。 その他、速度などは実際に遊んで見ながら調整すればよさそうです。

ひとまず一段落

ざっくりではありますが、ゲームのかたちにはなりました。 スコアが高まるにつれで弾数が増え、textarea利用でも意外と処理できるものだなと実感しました。

リソース

gconsole.css gconsole2.js g07.js

関連

00.画面表示 01.文字出力 02.無限ループ 03.画像出力 04.キー操作 05.速度を調整 06.敵の配置 08.ゲームパッド