VUE+Canvasは、インゴットを受け取る富の神のゲームを実装します

VUE+Canvasは、インゴットを受け取る富の神のゲームを実装します

前回のキャンバス ゲーム シリーズへようこそ:

《VUEがFlappy Birdを実装しました〜〜〜》

単語当てゲーム

《VUE+Canvas がデスクトップ ピンボール ブロック崩しゲームを実現》

《VUE+Canvasでサンダーファイターのタイピングゲームを実装》

タイトルの通り、誰もがプレイしたことがある、どこでも見かけるゲームです。左右の方向キーを使って富の神の動きをコントロールし、空から落ちてくる金塊をキャッチします。時間切れになるとゲームは終了します。まずは効果を見てみましょう:

弾丸を発射して飛び交う前回のサンダーファイターと比べると、今回のエレメントの移動軌跡は非常にシンプルで、宝石は垂直に、富の神は水平に動きます。前回のコードと同様に、重要な手順は次のとおりです。

1. キーボード操作で富の神が水平方向に移動する

これは非常にシンプルで、「デスクトップ ピンボール ブロック除去ゲームを実現する VUE+Canvas」のスライダーの制御に似ています。

描画カイシェン() {
      _this = this とします。
      _this.ctx.save();
      _this.ctx.drawImage(
        _this.caishenImg、
        _this.caishen.x,
        _this.caishen.y、
        120,
        120
      );
      _this.ctx.restore();
},
移動Caishen() {
      this.caishen.x += this.caishen.dx;
      if (this.caishen.x > this.clientWidth - 120) {
        this.caishen.x = this.clientWidth - 120;
      } それ以外の場合 (this.caishen.x < 0) {
        this.caishen.x = 0;
      }
}

2. 空から降ってくる宝石

これも非常にシンプルですが、宝石の初期 x 値を 0 から clientWidth までランダムに取ることはできないことに注意してください。宝石が重なり合ってゲームのプレイアビリティに影響を与える可能性があるためです。そのため、宝石は異なるトラックに散在させるのが最適です。ここでは、キャンバスの幅を 5 つのトラックに分割します。宝石が最初に描画されるときに、トラックに散在させ、y 値を一定の高さにランダムに設定して、ずらした外観を作成します。次に、新しく生成された宝石は、宝石が密集しないように、トラックの分布に従って生成されます。

宝物を生成する() {
      _this = this とします。
      _this.treasureArr.length < MaxNum の場合 {
        ランダム = Math.floor(Math.random() * TreasureNames.length);
        チャンネルを_this.getRandomArbitrary(1, 5);とします。
        _this.treasureArr.push({
          x: _this.channelWidth * (1 / 2 + (チャンネル - 1)) - 30,
          y: 0,
          名前: TreasureNames[ランダム],
          速度: _this.getRandomArbitrary(2, 4)
        });
      }
},
フィルター宝物(アイテム) {
      _this = this とします。
      もし (
        item.x <= _this.caishen.x + 110 &&
        item.x >= _this.caishen.x &&
        アイテム.y > _this.caishen.y
      ){
        // 富の神との接触範囲を決定する_this.score += _this.treasureObj[item.name].score;
        false を返します。
      }
      if (item.y >= _this.clientHeight) {
        false を返します。
      }
      true を返します。
},
宝物を描く() {
      _this = this とします。
      _this.treasureArr = _this.treasureArr.filter(_this.filterTreasure);
      _this.treasureArr.forEach(item => {
        _this.ctx.drawImage(
          _this.treasureObj[アイテム名].src,
          アイテム.x、
          アイテム.y、
          60,
          60
        );
        アイテムのy + = アイテムの速度;
      });
},
getRandomArbitrary(最小値, 最大値) {
      Math.random() * (max - min) + min を返します。
}

ここでは、フィルター関数を使用して、消えるはずの宝石をフィルターします。for+splice+i-- メソッドを使用すると、ジッターが発生します。

そして、各宝石にランダムな移動速度を与え、宝石が富神の画像範囲に入ると、対応するスコアが蓄積されます。

3. カウントダウンリング

カウントダウンを 30 秒に設定します。次に、requestAnimationFrame コールバックで、現在の時刻と最後のタイムスタンプの差が 1000 ミリ秒より大きいかどうかを計算して秒数を計算します。次に、別のタイムスタンプを取得して進行状況を累積し、リングのスムーズな動きを実現します。

描画カウントダウン() {
      // 進捗リングを描画します。let _this = this;
      _this.progress += Date.now() - _this.timeTag2;
      _this.timeTag2 = Date.now();
      _this.ctx.beginPath();
      _this.ctx.moveTo(50, 50);
      _this.ctx.arc(
        50,
        50,
        40,
        数学.PI * 1.5、
        Math.PI * (1.5 + 2 * (_this.progress / (countDownInit * 1000)))、
        間違い
      );
      _this.ctx.closePath();
      _this.ctx.fillStyle = "黄色";
      _this.ctx.fill();
 
      // 塗りつぶされた円を描画します_this.ctx.beginPath();
      _this.ctx.arc(50, 50, 30, 0, Math.PI * 2);
      _this.ctx.closePath();
      _this.ctx.fillStyle = "#fff";
      _this.ctx.fill();
 
      // 入力 text_this.ctx.font = "bold 16px Microsoft YaHei";
      _this.ctx.fillStyle = "#333";
      _this.ctx.textAlign = "center";
      _this.ctx.textBaseline = "中央";
      _this.ctx.moveTo(50, 50);
      _this.ctx.fillText(_this.countDown + "s", 50, 50);
    }
(関数animloop() {
        _this.ctx.clearRect(0, 0, _this.clientWidth, _this.clientHeight);
        _this.loop();
        アニメーションID = window.requestAnimationFrame(animloop);
        _this.countDown === 0 の場合
          _this.gameOver = true;
          window.cancelAnimationFrame(アニメーションID);
        }
        Date.now() - _this.timeTag >= 1000 の場合 {
          _this.countDown--;
          _this.timeTag = Date.now();
        }
})();

この時点で、富の神が金塊をキャッチするという非常に単純なゲームが完成しました。もちろん、難易度を上げるために、爆弾を連続して落とすセグメントを設定することもできます。原理は宝石の動きと同じです。

以下に参考用の完全なコードを示します。

<テンプレート>
  <div class="caishen">
    <canvas id="caishen" width="1200" height="750"></canvas>
    <div class="container" v-if="ゲームオーバー">
      <div class="ダイアログ">
        <p class="once-again">おめでとうございます! </p>
        <p class="once-again">このラウンドの宝物: {{ score }} ポイント</p>
      </div>
    </div>
  </div>
</テンプレート>
 
<スクリプト>
定数TreasureNames = [
  「元宝」、
  「トンチアン」、
  「ジンティアオ」、
  "shuijin_red",
  "shuijin_blue",
  「ふだい」
];
アニメーションIDをnullにします。
countDownInit = 0 とします。
定数MaxNum = 5;
エクスポートデフォルト{
  名前:「CaiShen」、
  データ() {
    戻る {
      スコア: 0,
      ctx: null、
      caishenImg: null、
      クライアント幅: 0,
      クライアントの高さ: 0,
      チャネル幅: 0,
      財神:
        x: 0,
        y: 0,
        速度: 8,
        度: 0
      },
      進捗: 0,
      カウントダウン: 30,
      時間タグ: Date.now(),
      timeTag2: Date.now(),
      treasureArr: [],
      ゲームオーバー: false、
      宝物オブジェクト: {
        元宝:
          スコア: 5,
          ソース: null
        },
        トンチェン:
          スコア: 2,
          ソース: null
        },
        ジンティアオ:
          スコア: 10,
          ソース: null
        },
        shuijin_red:
          スコア: 20,
          ソース: null
        },
        shuijin_blue: {
          スコア: 15,
          ソース: null
        },
        府代:
          スコア: 8,
          ソース: null
        }
      }
    };
  },
  マウント() {
    _this = this とします。
    コンテナを document.getElementById("caishen");
    _this.ctx = コンテナ.getContext("2d");
    _this.clientWidth = コンテナの幅;
    _this.clientHeight = コンテナの高さ;
    _this.channelWidth = Math.floor(_this.clientWidth / 5);
    _this.caishenImg = 新しい画像();
    _this.caishenImg.src = require("@/assets/img/caishen/财神爷.png");
 
    _this.initTreasures();
    countDownInit = _this.countDown;
    _this.caishen.x = _this.clientWidth / 2 - 60;
    _this.caishen.y = _this.clientHeight - 120;
    document.onkeydown = 関数(e) {
      キーを window.event.keyCode とします。
      (キー === 37) の場合 {
        //左 button_this.caishen.dx = -_this.caishen.speed;
      } そうでない場合 (キー === 39) {
        //右ボタン_this.caishen.dx = _this.caishen.speed;
      }
    };
    document.onkeyup = 関数(e) {
      _this.caishen.dx = 0;
    };
    _this.caishenImg.onload = 関数() {
      (関数animloop() {
        _this.ctx.clearRect(0, 0, _this.clientWidth, _this.clientHeight);
        _this.loop();
        アニメーションID = window.requestAnimationFrame(animloop);
        _this.countDown === 0 の場合
          _this.gameOver = true;
          window.cancelAnimationFrame(アニメーションID);
        }
        Date.now() - _this.timeTag >= 1000 の場合 {
          _this.countDown--;
          _this.timeTag = Date.now();
        }
      })();
    };
  },
  メソッド: {
    宝物を初期化する() {
      _this = this とします。
      Object.keys(_this.treasureObj).forEach(キー => {
        _this.treasureObj[キー].src = 新しいイメージ();
        _this.treasureObj[
          鍵
        ].src.src = require(`@/assets/img/caishen/${key}.png`);
      });
      (i = 0; i < MaxNum; i++) の場合 {
        ランダム = Math.floor(Math.random() * TreasureNames.length);
        _this.treasureArr.push({
          x: _this.channelWidth * (1 / 2 + i) - 30,
          y: _this.getRandomArbitrary(0, 20)、
          名前: TreasureNames[ランダム],
          速度: _this.getRandomArbitrary(2, 4)
        });
      }
    },
    ループ() {
      _this = this とします。
      _this.drawCountDown();
      _this.drawCaishen();
      _this.moveCaishen();
      _this.generateTreasure();
      _this.drawTreasure();
      _this.drawScore();
    },
    描画カイシェン() {
      _this = this とします。
      _this.ctx.save();
      _this.ctx.drawImage(
        _this.caishenImg、
        _this.caishen.x,
        _this.caishen.y、
        120,
        120
      );
      _this.ctx.restore();
    },
    移動Caishen() {
      this.caishen.x += this.caishen.dx;
      if (this.caishen.x > this.clientWidth - 120) {
        this.caishen.x = this.clientWidth - 120;
      } それ以外の場合 (this.caishen.x < 0) {
        this.caishen.x = 0;
      }
    },
    スコアを描画する() {
      _this = this とします。
      _this.ctx.beginPath();
      _this.ctx.fillStyle = "#fff";
      _this.ctx.textAlign = "center";
      _this.ctx.textBaseline = "中央";
      _this.ctx.fillText(_this.score + "分", 30, _this.clientHeight - 10);
      _this.ctx.closePath();
    },
    描画カウントダウン() {
      // 進捗リングを描画します。let _this = this;
      _this.progress += Date.now() - _this.timeTag2;
      _this.timeTag2 = Date.now();
      _this.ctx.beginPath();
      _this.ctx.moveTo(50, 50);
      _this.ctx.arc(
        50,
        50,
        40,
        数学.PI * 1.5、
        Math.PI * (1.5 + 2 * (_this.progress / (countDownInit * 1000)))、
        間違い
      );
      _this.ctx.closePath();
      _this.ctx.fillStyle = "黄色";
      _this.ctx.fill();
 
      // 塗りつぶされた円を描画します_this.ctx.beginPath();
      _this.ctx.arc(50, 50, 30, 0, Math.PI * 2);
      _this.ctx.closePath();
      _this.ctx.fillStyle = "#fff";
      _this.ctx.fill();
 
      // 入力 text_this.ctx.font = "bold 16px Microsoft YaHei";
      _this.ctx.fillStyle = "#333";
      _this.ctx.textAlign = "center";
      _this.ctx.textBaseline = "中央";
      _this.ctx.moveTo(50, 50);
      _this.ctx.fillText(_this.countDown + "s", 50, 50);
    },
    フィルター宝物(アイテム) {
      _this = this とします。
      もし (
        item.x <= _this.caishen.x + 110 &&
        item.x >= _this.caishen.x &&
        アイテム.y > _this.caishen.y
      ){
        // 富の神との接触範囲を決定する_this.score += _this.treasureObj[item.name].score;
        false を返します。
      }
      if (item.y >= _this.clientHeight) {
        false を返します。
      }
      true を返します。
    },
    宝物を描く() {
      _this = this とします。
      _this.treasureArr = _this.treasureArr.filter(_this.filterTreasure);
      _this.treasureArr.forEach(item => {
        _this.ctx.drawImage(
          _this.treasureObj[アイテム名].src,
          アイテム.x、
          アイテム.y、
          60,
          60
        );
        アイテムのy + = アイテムの速度;
      });
    },
    ランダムに取得(最小値, 最大値) {
      Math.random() * (max - min) + min を返します。
    },
    宝物を生成する() {
      _this = this とします。
      _this.treasureArr.length < MaxNum の場合 {
        ランダム = Math.floor(Math.random() * TreasureNames.length);
        チャンネルを_this.getRandomArbitrary(1, 5);とします。
        _this.treasureArr.push({
          x: _this.channelWidth * (1 / 2 + (チャンネル - 1)) - 30,
          y: 0,
          名前: TreasureNames[ランダム],
          速度: _this.getRandomArbitrary(2, 4)
        });
      }
    }
  }
};
</スクリプト>
 
<!-- CSS をこのコンポーネントのみに制限するために "scoped" 属性を追加します -->
<スタイル スコープ lang="scss">
#財神
  背景色: #b00600;
  背景画像: url("~assets/img/caishen/brick-wall.png");
}
。容器 {
  位置: 絶対;
  上: 0;
  右: 0;
  下部: 0;
  左: 0;
  背景色: rgba(0, 0, 0, 0.3);
  テキスト配置: 中央;
  フォントサイズ: 0;
  空白: ラップなし;
  オーバーフロー:自動;
}
.コンテナ:後{
  コンテンツ: "";
  表示: インラインブロック;
  高さ: 100%;
  垂直位置合わせ: 中央;
}
.ダイアログ{
  幅: 400ピクセル;
  高さ: 300px;
  背景: rgba(255, 255, 255, 0.5);
  ボックスの影: 3px 3px 6px 3px rgba(0, 0, 0, 0.3);
  表示: インラインブロック;
  垂直位置合わせ: 中央;
  テキスト配置: 左;
  フォントサイズ: 28px;
  色: #fff;
  フォントの太さ: 600;
  境界線の半径: 10px;
  空白: 通常;
  テキスト配置: 中央;
  .もう一度-btn {
    背景: #1f9a9a;
    境界線: なし;
    色: #fff;
  }
}
</スタイル>

これで、VUE+Canvas で富神インゴット獲得ゲームを実現した記事は終了です。Vue インゴット獲得ゲームの関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援してください。

以下もご興味があるかもしれません:
  • VueはCanvasを使用してランダムなサイズで重なり合わない円を生成します
  • Vueはキャンバスを使用して画像圧縮アップロードを実現します
  • vue+canvasでタイムラインを描く方法
  • VUE+CanvasはシンプルなGobangゲームの全プロセスを実現します
  • VUE と Canvas を使用して Thunder Fighter タイピング ゲームを実装する方法
  • VUE+Canvasはデスクトップピンボールブロック破壊ゲームのサンプルコードを実装します
  • Vueはマウスを使ってキャンバス上に四角形を描きます
  • Vueはキャンバスを使用してモバイル手書き署名を実装します
  • Vue+canvasでパズルゲームを実現
  • Vueはキャンバスの手書き入力を使用して中国語を認識します

<<:  MySQLクエリステートメント内のユーザー変数のコード分析

>>:  VMware での Linux CentOS6.9 インストール グラフィック チュートリアル

推薦する

Ubuntu 16.04.4LTS に mininet をインストールする際に発生する問題と解決策

ミニネットMininet は軽量のソフトウェア定義ネットワークおよびテスト プラットフォームです。軽...

データベース管理に役立つ 5 つの MySQL GUI ツール

MySQL には多くのデータベース管理ツールがあります。作業効率の向上に役立つ優れた GUI ツール...

MySQLの認証コマンドgrantの使い方

この記事の例は MySQL 5.0 以降で実行されます。ユーザー権限を付与するための MySQL コ...

写真とテキストによる MySQL 8.0.21 インストール チュートリアル

1. ダウンロードリンクをダウンロードするダウンロードをクリックします。Oracle アカウントにロ...

光沢のある輝くウェブサイトデザインの感動的なデザイン例

このコレクションには、あなたのデザインアイデアにインスピレーションを与える、輝いて光沢のある、優れた...

MySQLのタイムゾーンを表示および設定する方法

1. データベースのタイムゾーンを確認する '%time_zone' のような変数を...

CentOS 6.4 で rpm を使用して MySQL をオフラインでインストールする

rpmインストールパッケージを使用してmysqlをオフラインでインストールします。参考までに準備:公...

MySQL メタデータで Hive テーブル作成ステートメントのコメント スクリプトを生成する方法

序文この記事は主にMySQLメタデータ生成Hiveテーブル作成ステートメントコメントスクリプトに関す...

React antdはフォームの動的な増減を実現します

以前、動的フォームを記述しているときに落とし穴に遭遇しました。インデックスの添え字をキーとして使用す...

Lvs+Nginx クラスターを使用して高並列アーキテクチャを構築する例

目次1. Lvsの紹介2. Lvs負荷分散モード2.1 NAT 2.2 ターン2.3 DRモード3....

CSS を使用して ul と li の水平配置を実現する 2 つの方法

li はブロックレベル要素であり、デフォルトで 1 行を占めるため、水平方向の配置を実現する場合は、...

ソフトウェア 404 と 404 エラーとは何か、またそれらの違いは何ですか

まず、404 とソフト 404 とは何でしょうか? 404: 簡単に言えば、ユーザーが存在しないペー...

WeChatアプレットは左にスワイプしてリスト項目を削除する効果を実現

この記事では、WeChatミニプログラムの具体的なコードを共有し、左にスワイプしてリスト項目を削除す...

JavaプログラミングでJavaScriptの超実用的なテーブルプラグインを書く

目次効果ドキュメント最初のステップステップ2ステップ3ソースコード効果ドキュメント最初のステップta...

MySQLのデフォルトのソートルールに基づく落とし穴

MySQL のデフォルトの varchar 型は大文字と小文字を区別しません (insensitiv...