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 インストール グラフィック チュートリアル

推薦する

テキストの両側に水平線を描くための CSS のサンプルコード

この記事では、テキスト中央の両側に水平線を引く効果を実現する CSS のサンプルコードを紹介し、皆さ...

大規模な MySQL テーブルに対する count() の実装を最適化しました

以下は、B+ ツリーのデータ構造と実験結果からの推測に基づいた私の判断です。間違いがあればご指摘くだ...

Uniappがスライディングスコアリング効果を実現

この記事では、スライディングスコアリングを実装するためのuniappの具体的なコードを参考までに共有...

8 JSのreduce使用例とreduce操作方法

reduceメソッドは配列の反復メソッドです。 mapやfilterとは異なり、 reduceメソッ...

MySQL テーブルパーティションの使用法と基本原理の詳細な説明

目次パーティションテーブルとはパーティションテーブルの適用シナリオパーティションテーブルの制限パーテ...

js を使用して数字推測ゲームを実装する

先週、先生が私に数字当てゲームをするちょっとした宿題を出しました。とても面白いと思ったので、適当に書...

MySQLの使い方の詳細な説明

目次1. はじめに2. 本文2.1 Where句の位置2.2 演算子2.3 NULL値1. はじめに...

jsフェッチ非同期リクエストの使用の詳細な例

目次非同期を理解するフェッチ(url)レスポンス.json() asyncとawaitを組み合わせる...

MySQL の分離レベル、ロック、MVCC の紹介

この記事の目的は、これらの概念とその機能の関係を明らかにすることです。 Mysql がトランザクショ...

Linux と最もよく使用されるコマンドの紹介 (習得は簡単ですが、問題の 95% 以上を解決できます)

Linux は現在最も広く使用されているサーバー オペレーティング システムです。Unix をベー...

IISMonitor を使用して Web ページを監視し、IIS を自動的に再起動します。

目次1. ツールの紹介2. ワークフロー3. 操作インターフェースとパラメータ設定(1)監視と再起動...

MySQL ストアド プロシージャで case ステートメントを使用する詳細な例

この記事では、例を使用して、MySQL ストアド プロシージャでの case ステートメントの使用方...

Javascript ツリー メニュー (11 項目)

1. dhtmlxツリー dHTMLxTree は機能豊富なツリー メニュー コントロールです。豊...

MySQL の自動増分 ID (主キー) が不足した場合の解決策

MySQL で使用される自動インクリメント ID には多くの種類があり、各自動インクリメント ID ...

ブラウザの自動フォーム入力によるウェブページのスタイル損失の原因の分析と解決

バックエンドからフロントエンドまで、なんと悲劇なのでしょう。他の人の CSS を自分の jsp We...