VUEはFlappy Birdゲームのサンプルコードを実装します

VUEはFlappy Birdゲームのサンプルコードを実装します

Flappy Bird は、誰もがアプリでプレイしたことがある非常にシンプルな小さなゲームです。ここでは、娯楽用に VUE を使用して Flappy Bird のシンプルな PC バージョンを実装します~~~~~

このゲームを実現するには、まずゲーム インターフェースのどの部分をアニメーション化する必要があるかを分析しましょう。

1. 最初のものはもちろん上下に動く鳥です。

2. 背景画像が水平に動くため、鳥が水平に飛んでいるように見えます。

3. 画面右側から入ってくるパイプの列。

これは非常に明確です。上記の 3 つの部分をルールに従って動かし、ルールの境界判断とスコアリングを追加すれば、完全なゲームが得られます。では一つずつ解決していきましょう。

まず、いくつかの定数と変数を定義しましょう。

let rafId = null; // requestAnimationFrame ID
startSpeed ​​= 1とします。
const SPEED = 0.04; // 加速度 const UP = 5.0; // 速度累積の上限 const UP_SUM = 30; // 1回のジャンプの高さ const BIRD_WIDTH = 50; // 鳥の絵の幅 50px
const PIPE_DISTANCE = 350; // パイプ間の水平距離 let id = 0; // パイプの一意の ID。カウントは 0 から始まります...
 
データ() {
    戻る {
      開始: false、
      クライアント幅: 0,
      クライアントの高さ: 0,
      spaceHeight: [240, 200, 160], // 上部のパイプと下部のパイプの間の距離pipeArr: [], // パイプ配列score: 0, // ScorejumpSum: 0, // 現在のジャンプの相対高さjumpFlag: false, // true-スペースバーを押すと上昇ステージでジャンプします。false-自由落下ステージdropBirdImg: require("@/assets/img/bird/bird0_0.png"),
      flyBirdImg: require("@/assets/img/bird/bird0_2.png"),
      gameOver: false, // ゲームの失敗を示すフラグ。アニメーション フレームを停止するために使用されます};
},

1. 上下に動く鳥

鳥とパイプの位置をそれぞれ制御するために、要素はposition: absoluteを使用して配置されます。

鳥自体は div + 背景画像であり、インターフェース内での初期位置を定義します。

<div class="bird" id="bird" ref="bird"></div>
 
 #鳥 {
      高さ: 50px;
      幅: 50px;
      境界線の半径: 50%;
      背景: url("~assets/img/bird/bird0_1.png") 繰り返しなし center/contain;
      // 鳥の初期位置 position: absolute;
      左: 300ピクセル;
      上: 300px;
}

その後、何も操作しなくても、鳥は最初の位置から「落下」を始めます。鳥はどんどん速く落下します。ここでは、重力加速の物理的な式は使用せず、単に曲線加速プロセスをシミュレートしました。これは連続アニメーションなので、このアクションをアニメーションフレーム、つまりrequestAnimationFrameに配置し、各フレームの関数はloop()として定義します。

そのため、ループ関数では、親要素の offsetTop と clientHeight を使用して、鳥が画面の上限と下限に触れたかどうかを判断します。触れた場合はゲームが終了し、触れていない場合は style.top を増やして鳥を落下させます。

ループ() {
      _this = this とします。
      if (_this.jumpFlag) {
        // 鳥はジャンプします_this.jump();
      }
      top = _this.$refs.bird.offsetTop とします。
      _this.clientHeight がトップ > BIRD_WIDTH の場合、トップ <= 0 になります。
        //境界に達するとゲームが終了します_this.resetGame();
      } それ以外の場合 (!_this.jumpFlag) {
        _this.$refs.bird.style.background = `url('${_this.dropBirdImg}') 繰り返しなし center/contain`;
        _this.$refs.bird.style.top = top + startSpeed ​​* startSpeed ​​+ "px"; // 加速落下をシミュレートする if (startSpeed ​​< UP) {
          開始速度 + = 速度;
        }
      }
      _this.pipesMove(); // パイプラインの移動}

ゲーム内でプレイヤーがスペースバーを押すと、鳥が一定距離ジャンプします。この状態はthis.jumpFlag[true/false]で記録されます。押されたらtrueに設定されます。ループ関数内で鳥がジャンプします()。一定距離ジャンプした後、jumpFlagがfalseに設定され、鳥が落下し始めます。

したがって、ジャンプ関数は簡単に実装できます。

ジャンプ() {
      _this = this とします。
      _this.$refs.bird.style.background = `url('${_this.flyBirdImg}') 繰り返しなしの center/contain`;
      _this.jumpSum > UP_SUMの場合{
        // top_this.jumpFlag に到達すると落下します。false;
        _this.jump合計 = 0;
        開始速度 = 1;
      } それ以外 {
        _this.$refs.bird.style.top = _this.$refs.bird.offsetTop - 8 + "px";
        _this.jump合計+=8;
      }
}

2. 水平方向に移動する背景画像

これは比較的簡単です。無限ループで background-position を切り替えるだけです。位置は、ダウンロードした背景画像素材の幅によって決まります。

アニメーション: bgMove 8s 線形無限;
      @keyframes bgMove {
        0% {
          背景位置: 805px 0;
        }
        100% {
          背景位置: 0 0;
        }
}

これら 2 つの手順を実行すると、飛んでいる鳥が表示されます。以下に示すように、document.onkeydown を使用してスペース バーをリッスンし、jumpFlag を切り替えます。

3. 右から左へ移動してパイプに入る

パイプラインは 2 つの div で構成されており、それぞれの div の中央には、異なる top: -xx と bottom: -yy のギャップがあります。

まず、pipeArr オブジェクト配列に格納されるランダムギャップパイプを生成する関数を実装します。

パイプIDを追加します
      obj = {} とします。
      top_num = this.sum(10, 170) とします。
      高さを this.spaceHeight[ とする
        Math.floor(Math.random() * this.spaceHeight.length)
      ]; // ギャップ値をランダムに選択 let bottom_num = height - top_num;
      obj.top = トップ番号;
      obj.id = id;
      obj.right = -(PIPE_DISTANCE / 2);
      obj.bottom = ボトム番号;
      this.pipeArr.push(obj);
},
合計(m,n) {
      // nm 間の乱数 return Math.floor(Math.random() * (m - n) + n);
}

次に、パイプを移動する必要があります。つまり、loop() 内のパイプ移動関数 pipesMove() です。関数全体は次のように実装されます。

パイプ移動() {
      _this = this とします。
      _this.pipeArr.length === 0 の場合 {
        戻る;
      }
      right0 = _this.pipeArr[0].right;とします。
      右0 > this.clientWidth + 300の場合{
        シフト関数
      }
      right_last = _this.pipeArr[_this.pipeArr.length - 1].right とします。
      (右端 >= PIPE_DISTANCE / 2)の場合{
        id++;
        this.addPipe(id);
      }
      (i = 0 とします; i < _this.pipeArr.length; i++) {
        // 鳥がパイプに触れたかどうかを判定します。鳥は 50*50、左: 300px、パイプの幅は 100px、パイプの進入範囲の右は width-450 から width-300 です。
        もし (
          _this.pipeArr[i].right >= _this.clientWidth - 450 &&
          _this.pipeArr[i].right <= _this.clientWidth - 300
        ){
          // パイプが鳥の接触範囲に入りました。let bird_top = _this.$refs.bird.offsetTop;
          // 12は、上下に空白がある鳥の画像素材です(
            bird_top <= _this.clientHeight / 2 - _this.pipeArr[i].top - 12 ||
            鳥トップ >=
              _this.clientHeight / 2 + _this.pipeArr[i].bottom - BIRD_WIDTH + 12
          ){
            // pipe_this.resetGame() を実行します。
            戻る;
          }
        }
        if (_this.pipeArr[i].right === _this.clientWidth - 300 && _this.pipeArr[i].right === _this.clientWidth - 301) { // パイプが鳥のすぐ左側にある場合、鳥はパイプを通過したことがわかります。パイプの ID に基づいて鳥のスコアを計算します _this.score = _this.pipeArr[i].id + 1;
        }
        _this.pipeArr[i].right = _this.pipeArr[i].right + 2; // パイプはフレームごとに2ピクセル移動します
      }
}

ここでは 5 つのことが行われます:

(1)パイプが左画面から出た後、左端のパイプをshift()する。

(2)右端のパイプが画面右側から一定の距離を離れた後、新たなパイプが追加される。

(3)ループ中に、鳥が特定のパイプの範囲内に入ったかどうか、また鳥の上部が上下のパイプに触れているかどうかを判定します。触れている場合は負けです。

(4)鳥の左側にパイプがある場合は、鳥は無事に通過したことを意味し、得点は+1となる。

(5)各チャンネルは2pxピクセルずつ移動し、その値が右属性に記録されます。

DOM:style を正しく設定することで、パイプを水平方向に移動できるようになります。

<section class="pipes-wrap" ref="パイプ">
          <div
            クラス="パイプアイテム"
            v-for="(item, index) in pipeArr"
            :key="アイテムID"
            :id="'パイプ' + インデックス"
            :style="'right:' + item.right + 'px;'"
          >
            <div
              class="pipe パイプトップ"
              :style="'top:-' + item.top + 'px;'"
            </div>
            <div
              クラス="パイプ パイプ下部"
              :style="'bottom:-' + item.bottom + 'px;'"
            </div>
          </div>
</セクション>
 
.パイプラップ{
        位置: 相対的;
        高さ: 100%;
        オーバーフロー: 非表示;
        .パイプアイテム{
          位置: 絶対;
          高さ: 100%;
          幅: 100ピクセル;
          .パイプ{
            幅: 100%;
            高さ: 50%;
            位置: 相対的;
          }
          .パイプトップ{
            背景: url('"~assets/img/bird/pipe_down.png') 繰り返しなし;
            背景サイズ: 100px;
            背景位置: 下;
          }
          .パイプボトム{
            背景: url('"~assets/img/bird/pipe_up.png') 繰り返しなし;
            背景サイズ: 100px;
            背景の位置: 上;
          }
        }
} 

上記は、合計 200 行を超えるコードを含む、Vue による Flappy Bird の実装のアイデアとコア コードです。私の意見では、難しさは主にパイプの動き、タッチの決定、スコアの計算にあります。もちろん、コードにはまだ最適化できる欠点がたくさんあります。お互いに励まし合いましょう~~

以下もご興味があるかもしれません:
  • フラッピーバードゲームのサンプルコードを実装するための純粋なJavaScript
  • シンプルな Flappy Bird の C++ バージョン
  • フラッピーバードゲームのC言語簡易版
  • Python が Flappy Bird のソースコードを実装
  • C言語でフラッピーバードゲームを実装する
  • Unity が Flappy Bird ゲーム開発手法を実装
  • Flappy Bird ゲームのソースコードの Java 実装
  • C言語でFlappy Birdゲームを実装する
  • Pygame を使って Flappy Bird ゲームを書く
  • Pygame オブジェクト指向の飛ぶ鳥の実装 (Flappy bird)

<<:  CentOS7 systemdにカスタムシステムサービスを追加する方法

>>:  MySQL 5.7 における部分テーブルのデュアルマスター同期の実装プロセスの詳細な説明

推薦する

Vueコンポーネントの再利用と拡張の詳細な説明

目次概要延長は必要ですか?スロットJavaScript ユーティリティ関数拡張コンポーネントの複数の...

動的な背景グラデーション効果を実現するCSS3

CSS3 を学ぶということは、新しい機能と基本的な理論に慣れることを意味します。この記事では、ケー...

Vueはタブナビゲーションバーを実装し、左右のスライド機能をサポートしています

この記事では主に、Vue を使用してタブ ナビゲーション バーを実装し、flex レイアウトを使用し...

マークアップ言語 - リスト

標準化されたデザインソリューション - マークアップ言語とスタイルマニュアルWeb 標準ソリューショ...

CSS での配置の使用方法の詳細な研究 (要約)

CSS における位置指定の概要position属性は英語で位置を意味し、 CSSでの主な機能は要素...

アイデアを war パッケージにパッケージ化し、tomcat にデプロイしてアクセス パスの問題 (図とテキスト)

Web プロジェクトを war にパッケージ化するアイデアにとって最も重要なことは、アトリフィカを...

60件のページング事例と優れた実践例を推奨

<br />構造と階層により複雑さが軽減され、読みやすさが向上します。記事やサイトが整理...

Alibaba Cloud Server Tomcatにアクセスできません

目次1. はじめに2. 解決策2.1 ファイアウォールを設定してポートを開く2.3 ポートを確認し、...

ウェブサイトのAboutページの紹介コンテンツの書き方

公式、電子商取引、ソーシャル ネットワーキング、個人のいずれの Web サイトでも、訪問者に貴重な時...

特定の MySQL テーブルの完全データと増分データをメッセージ キューに同期する - ソリューション

目次1. 当初の需要2. 解決策3. 運河の導入と設置運河の仕組み建築インストール4. 検証1. 当...

MySQL SELECT実行順序の簡単な理解

SELECT ステートメントの完全な構文は次のとおりです。 (7)選択 (8) DISTINCT ...

CSS の 4 つのインポート方法と優先順位の簡単な分析

第一に: CSSを導入する4つの方法CSS を導入する方法には、インライン スタイル、埋め込みスタイ...

MySQL 5.7.10 winx64 のインストールと設定方法のグラフィック チュートリアル (win10)

MySQL は比較的使いやすいリレーショナル データベースです。今日は、win10 システムを再イ...

Robots.txtの詳細な紹介

Robots.txt はプレーンテキスト ファイルであり、Web サイト管理者は、ロボットによるアク...