前回のキャンバス ゲーム シリーズへようこそ: 《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 を応援してください。 以下もご興味があるかもしれません:
|
<<: MySQLクエリステートメント内のユーザー変数のコード分析
>>: VMware での Linux CentOS6.9 インストール グラフィック チュートリアル
ミニネットMininet は軽量のソフトウェア定義ネットワークおよびテスト プラットフォームです。軽...
MySQL には多くのデータベース管理ツールがあります。作業効率の向上に役立つ優れた GUI ツール...
この記事の例は MySQL 5.0 以降で実行されます。ユーザー権限を付与するための MySQL コ...
1. ダウンロードリンクをダウンロードするダウンロードをクリックします。Oracle アカウントにロ...
このコレクションには、あなたのデザインアイデアにインスピレーションを与える、輝いて光沢のある、優れた...
1. データベースのタイムゾーンを確認する '%time_zone' のような変数を...
rpmインストールパッケージを使用してmysqlをオフラインでインストールします。参考までに準備:公...
序文この記事は主にMySQLメタデータ生成Hiveテーブル作成ステートメントコメントスクリプトに関す...
以前、動的フォームを記述しているときに落とし穴に遭遇しました。インデックスの添え字をキーとして使用す...
目次1. Lvsの紹介2. Lvs負荷分散モード2.1 NAT 2.2 ターン2.3 DRモード3....
li はブロックレベル要素であり、デフォルトで 1 行を占めるため、水平方向の配置を実現する場合は、...
まず、404 とソフト 404 とは何でしょうか? 404: 簡単に言えば、ユーザーが存在しないペー...
この記事では、WeChatミニプログラムの具体的なコードを共有し、左にスワイプしてリスト項目を削除す...
目次効果ドキュメント最初のステップステップ2ステップ3ソースコード効果ドキュメント最初のステップta...
MySQL のデフォルトの varchar 型は大文字と小文字を区別しません (insensitiv...