JSはスネークゲームを実装する

JSはスネークゲームを実装する

ページ効果:

Snake ゲームは、メディエーター モデルを使用して開発されます。Snake のケースは、以前のように 1 つの HTML ファイルに記述されるのではなく、クラスに分割されます。個別の js が各クラスを表し、メディエーター クラスは Game クラスです。

1. 初期化構造

まず、ページを初期化する必要があります。初期化レイアウトはHTMLタグに直接記述されるのではなく、ゲームノードツリーを通じて初期化されます。

行を表すために this.row を使用し、列を表すために this.col を使用して、20 行 20 列のテーブルを設定します。

Games.prototype.init = 関数(){
    this.dom = document.createElement('table');
    var tr、td;
    //行と列のツリーをトラバースする for (var i = 0; i < this.row; i++) {
        // 行を走査してノード上にツリーを作成します tr = document.createElement('tr');
 
        (var j = 0; j < this.col; j++) の場合 {
            // 列をトラバースしてノード上にツリーを作成します td = document.createElement('td');
            // ツリーにノードを追加します tr.appendChild(td);
 
 
            // ツリーにノードを追加します this.dom.appendChild(tr);
 
        }
    }
    // テーブル上のツリー document.getElementById('app').appendChild(this.dom);
}

結果:

2. 蛇の色のレンダリング

スネークをレンダリングするためのロジック: スネーク クラスは、Game クラスの setColor メソッドを呼び出します。これは、本質的にはテーブルの色をレンダリングするためです。テーブルは Game クラスが初期化されるときに作成されるため、Game に色をレンダリングするためのメソッドを設定させるのは合理的です。

// 色を設定するメソッド Games.prototype.setColor = function (row, col, color) {
    // テーブルの行と列の色を設定します。this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].style.backgroundColor = color;
}

この時点で、SnakeクラスはgameのsetColorメソッドを呼び出すようになります。

Snake.prototype.render = 関数 () {
    // ヘビのレンダリング game.setColor(this.body[0].row, this.body[0].col, 'pink');
    // スネークボディ for (var i = 1; i < this.body.length; i++) {
        game.setColor(this.body[i].row, this.body[i].col, 'skyblue');
    }
}

この時点で、誰が Snake のレンダリングを呼び出すのかという疑問が生じます。 Snakeのコンストラクタでゲームを呼び出すことはできません。Gameクラスの4つのステップがまだ実行されていないため、現在は未定義です。

解決策はタイマーを呼び出すことです。タイマーは非同期なので、Game クラスの 4 つのステップの実行を妨げることはありません。

    this.timer = setInterval(関数() {
        // タイマーの核はゲーム レンダリングの本質、つまり画面のクリア - 更新 - レンダリングです // スネークをレンダリングします game.snake.render();
    }, 20);

結果:

3. ヘビの動き

ヘビの動きは、実際にはボディ配列の更新です。本質は、ボディ配列の尾を削除し、頭を追加して、ヘビが新しい状態をレンダリングすることです。

Snake.prototype.update = 関数(){
 
    // 現在の方向はwilldirectionを受け取ります
    this.direction = this.willDirection;
    スイッチ(this.direction) {
        ケース 'R':
            this.body.unshift({ '行': this.body[0].row, '列': this.body[0].col + 1 });
            壊す;
        ケース 'D':
            this.body.unshift({ '行': this.body[0].row + 1, '列': this.body[0].col });
            壊す;
        ケース 'L':
            this.body.unshift({ '行': this.body[0].row, '列': this.body[0].col - 1 });
            壊す;
        ケース 'T':
            this.body.unshift({ '行': this.body[0].row - 1, '列': this.body[0].col });
            壊す;
    }

この時点で、蛇はどんどん長くなっていることがわかります

スネークに色のレンダリング方法を伝えたので、以前のレンダリングを消去する必要があります。

ゲームの画面を消去する方法を設定しました

// 画面をクリアする Games.prototype.clear = function () {
    (var i = 0; i < this.row; i++) の場合 {
        (var j = 0; j < this.col; j++) の場合 {
            this.dom.getElementsByTagName('tr')[i].getElementsByTagName('td')[j].style.backgroundColor = '#fff';
            this.dom.getElementsByTagName('tr')[i].getElementsByTagName('td')[j].innerHTML = '';
        }
    }
}

次に、タイマーでゲームの3つのステップを実行します。画面のクリア、更新、レンダリングです。

 // 画面をクリアします game.clear();
        // スネークの動き/更新 // スネークの更新速度 スネーク側が長いほど速度が上がります var during = game.snake.body.length < 30 ? 30 - game.snake.body.length : 1;
        // Snake 更新 game.f % during == 0 && game.snake.update();
        // ヘビをレンダリングします game.snake.render();

ヘビはさまざまな方向に移動します。Game の bindEvent イベントを設定すると、キーボード イベントを監視し、さまざまな方向を変更し、ヘビの頭が下に移動したときに上キーが押せないことを判断できます。

Games.prototype.bindEvent = 関数(){
    var self = this;
    //キーボードイベント document.onkeydown = function (even) {
        スイッチ (even.keyCode) {
            ケース37:
                // まず、現在の方向が右に移動している場合、この時点で左ボタンを押すことはできません。 if (self.snake.direction == 'R') return;
                方向をLに変更します。
                壊す;
            ケース38:
                // まず、現在の方向が下向きであるかどうかを判断し、この時点で上キーを押すことはできません。 if (self.snake.direction == 'D') return;
                方向を変更します。
                壊す;
            ケース39:
                // まず、現在の方向が左に移動している場合、この時点では右ボタンを押すことはできません。 if (self.snake.direction == 'L') return;
                方向を変更します。
                壊す;
            ケース40:
                // まず、現在の方向が上向きの場合、この時点ではキーを押すことができません。 if (self.snake.direction == 'T') return;
                方向変更('D')
                壊す;
        }
    }
}

このとき、Snake クラスにも対応する方向の一致が必要です。Snake を初期化するときに this.direction='R' を設定します。

Snake.prototype.update = 関数(){
 
    // 現在の方向はwilldirectionを受け取ります
    this.direction = this.willDirection;
    スイッチ(this.direction) {
        ケース 'R':
            this.body.unshift({ '行': this.body[0].row, '列': this.body[0].col + 1 });
            壊す;
        ケース 'D':
            this.body.unshift({ '行': this.body[0].row + 1, '列': this.body[0].col });
            壊す;
        ケース 'L':
            this.body.unshift({ '行': this.body[0].row, '列': this.body[0].col - 1 });
            壊す;
        ケース 'T':
            this.body.unshift({ '行': this.body[0].row - 1, '列': this.body[0].col });
            壊す;
    }

4. ヘビの死を判定する方法 ヘビの死を判定する方法は2つあります

1つ目は、蛇自体がテーブル部分を超えていることです

 // テーブルの端を超える部分 if (this.body[0].col > game.col - 1 || this.body[0].row > game.row - 1 || this.body[0].col < 0 || this.body[0].row < 0) {
        alert('ゲームオーバー、現在のスコアは ' + game.score です);
        ゲームのタイマーをクリアします。
        this.body.shift();
        ゲームのタイマーをクリアします。
    }

2つ目は、蛇自体が体の一部と重なっていることです。

  // 自身をヒット for (var i = 1; i < this.body.length; i++) {
        this.body[0].col == this.body[i].col && this.body[0].row == this.body[i].row)の場合{
            alert('ゲームオーバー、現在のスコアは ' + game.score です);
            this.body.shift();
            ゲームのタイマーをクリアします。
        }
    }

5. 食品の創造

この時点で、食べ物を生産するためのFoodクラスを作成し、Gameでインスタンス化し、タイマーでレンダリングします。

食べ物の列と行をランダムに生成するときは、まずそれがヘビの上にあるかどうかを確認します。

関数 Food(gameSnake) {
    var self = this;
    // 食べ物の場所 // do-while ループ ステートメントは、最初に行と列を作成し、次に行と列がヘビの上にあるかどうかを判断します。do {
        this.row = parseInt(Math.random() * gameSnake.row);
        this.col = parseInt(Math.random() * gameSnake.col);
    } while ((関数 () {
        // ヘビの行と列を走査し、それらを新しくランダムに生成された食品の行と列と比較して、それらが重複しているかどうかを確認します for (var i = 0; i < gameSnake.snake.body.length; i++) {
            gameSnake.snake.body[i].row == self.row && gameSnake.snake.body[i].col == self.col) の場合 {
                true を返します。
            }
 
        }
        false を返します。
    })())
 
    コンソールにログ出力します。
}
 
Food.prototype.render = 関数(){
    game.setHTML(this.row, this.col, '♥');
}

6. ヘビが食べる餌の長さ

ヘビが移動すると、配列本体の先頭に要素が追加され、尾の要素が削除されます。したがって、ヘビの頭が餌に触れた後は、尾をそのままにしておけばよいだけです。

   this.body[0].row == game.food.row && this.body[0].col == game.food.col) の場合 {
        // 新しい食べ物を作成します。game.food = new Food(game);
        // フレーム番号を0に戻す
        // スコアを追加 game.score++;
        ゲーム.f = 0;
    } それ以外 {
        this.body.pop();
    }

ヘビは餌を早く食べる

餌に当たるまで増加するフレーム番号を設定し、ヘビの長さが長くなるにつれてヘビの更新速度を速めます。

         0 を返します。
        ゲーム.f++;
       // ヘビの速度を更新します。ヘビの側面が長くなると、速度が上がります。var during = game.snake.body.length < 30 ? 30 - game.snake.body.length : 1;
        // Snake 更新 game.f % during == 0 && game.snake.update();
        // ヘビをレンダリングする

7. ゲーム開始機能

HTML でボタンを記述し、位置決めによって適切な場所に配置し、クリック イベントを与えるだけで、開始ボタンをクリックした後にのみ Game 内のコードが実行されます。

 <div id="アプリ"></div>
    <div class="startgame"><img src="images/btn1.gif" alt=""></div>
    <div class="stopgame"><img src="images/btn4.png" alt=""></div>
    <スクリプト>
        var ゲーム = null;
        var btnstart = document.querySelector('.startgame');
        var btnstop = document.querySelector('.stopgame')
        btnstart.addEventListener('click', 関数() {
            btnstart.style.display = 'なし';
            ゲーム = 新しいゲーム();
            // コンソールログ(テーブル);
            var テーブル = document.querySelector('テーブル');
            table.addEventListener('click', 関数() {
                ゲームのタイマーをクリアします。
                btnstop.style.display = 'ブロック';
            })

8. ゲームの一時停止/再開機能

一時停止ボタンとテーブルの両方にクリック イベントを設定します。テーブルをクリックすると、停止ボタンが表示され、ゲーム内のタイマーが停止します。一時停止ボタンをクリックすると、タイマーが開始して非表示になります。

     btnstop.addEventListener('click', 関数() {
                btnstop.style.display = 'なし';
                game.timer = setInterval(関数() {
                    // タイマーの核はゲーム レンダリングの本質です。画面をクリア - 更新 - レンダリング game.f++;
                    // document.getElementById('f').innerHTML = 'フレーム番号:' + game.f;
                    // // スコアをレンダリングします // document.getElementById('score').innerHTML = 'Score:' + game.score;
                    // 画面をクリアします game.clear();
                    // スネークの動き/更新 // スネークの更新速度 スネーク側が長いほど速度が上がります var during = game.snake.body.length < 30 ? 30 - game.snake.body.length : 1;
                    // Snake 更新 game.f % during == 0 && game.snake.update();
                    // ヘビをレンダリングします game.snake.render();
                    // 食べ物をレンダリングする game.food.render();
                }, 10);
            })

これで、JS で Snake ゲームを実装する方法に関するこの記事は終了です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援して頂ければ幸いです。

以下もご興味があるかもしれません:
  • JavaScript の絶妙なスネーク実装プロセス
  • スネークゲームのアイデアを実現するためのJavaScript
  • 古典的なスネークゲームの JavaScript 実装
  • JS 実用的なオブジェクト指向スネークゲームの例

<<:  LeetCode の SQL 実装 (178. スコアランキング)

>>:  Docker に ElasticSearch をインストールする方法を 1 つの記事で解説

推薦する

React のクラスからフックへの移行

目次リアクトフック序文なぜフックなのか?クラス関数クラスとフックの比較フックはコンポーネントの状態を...

VMware Workstation と vSphere 間で仮想マシンを移行する (画像とテキスト)

1. Workstationで仮想マシンのハードウェアバージョンを変更するWorkstation ...

MySQLクエリステートメントの簡単な操作例

この記事では、例を使用して、MySQL クエリ ステートメントの簡単な操作を説明します。ご参考までに...

Web アプリ開発時間を短縮する 10 の時間を節約するヒント (グラフィカル チュートリアル)

今日の開発環境では、速いほど良いです。 「迅速なアプリケーション開発」、「アジャイル ソフトウェア開...

HTML 内の CSS および JS リンクのバージョン番号 (キャッシュを更新)

背景検索エンジンで「.htaccess キャッシュ」というキーワードを検索すると、ウェブサイトのファ...

一般的な JavaScript 文字列メソッド 28 個と使用方法のヒントのまとめ

目次序文1. 文字列の長さを取得する2. 文字列の指定された位置の値を取得する(1) charAt(...

JS に依存せずにレスポンシブ レイアウトを実現する CSS3 モバイル vw+rem メソッド

1. はじめに(1)vw/vhの紹介使用する前に、vw と rem とは何か、その機能について簡単に...

Mysql論理アーキテクチャの詳細な説明

1. 全体的なアーキテクチャ図他のデータベースと比較すると、MySQL は、そのアーキテクチャがさま...

DockerでEurekaを設定する方法

ユーレカ: 1. JDKイメージを構築するEurekaコンテナを起動するjdkフォルダと必要なファイ...

Linux RabbitMQ クラスタ構築プロセス図

1. 全体的な手順冒頭で、RabbitMQ サービスをインストールして実行する方法を紹介しましたが、...

プロジェクトにおける CSS グリッドシステムの柔軟な使用方法の詳細な説明

序文CSS グリッドは通常、さまざまなフレームワークにバンドルされていますが、実際のビジネス ニーズ...

マークアップ言語 - CSS レイアウト

123WORDPRESS.COM HTML チュートリアル セクションに戻るには、ここをクリックして...

MySQL データベースのインデックスとトランザクション

目次1. 索引1.1 コンセプト1.2 機能1.3 索引作成の原則1.3.1 ディスクアクセス回数を...

Vue3 の SetUp 関数のプロパティとコンテキスト パラメータの詳細な説明

1. setUp関数の最初のパラメータpropsセットアップ(プロパティ、コンテキスト){}最初のパ...

HTML で特定のテキストを非表示にするにはどうすればよいでしょうか?

テキスト非表示コード、HTML 内の特定のテキストを非表示にするコードをコピーコードは次のとおりです...