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 つの記事で解説

推薦する

CSS で水平方向と垂直方向に中央揃えする 10 の方法を教えます (要約)

面接には必需品、仕事でも必ず使います。うーん、誰でも分かるでしょう。これ以上何も言わずに、要約とレン...

Mysql でよく使用される時間、日付、変換関数の概要

この記事では、主に実際のアプリケーションでよく使用されるMySQLの時刻と日付、および変換関数につい...

MySQL テーブルを削除するときに外部キー制約を無視するシンプルな実装

テーブルを削除することはあまり一般的ではありませんが、特に外部キーの関連付けがあるテーブルの場合は、...

Prometheus を使用して、MySQL の自動増分主キーの残りの使用可能パーセンテージをカウントします。

最近、本番環境のデータベースがログデータを狂ったように書き込み、主キー値のオーバーフローを引き起こし...

Dockerコンテナのデータボリュームの詳細な説明

何ですかまず、Docker の概念を見てみましょう。アプリケーションと実行環境をコンテナにパッケージ...

Vue-router は現在の場所 (/path) へのナビゲーションを許可しません。エラーの原因と修正

目次エラーメッセージ原因エラーのデモンストレーション回避策方法1方法2方法3エラーメッセージ現在の場...

角度に基づくツリー型セカンダリテーブルを実現する

まず効果を見てみましょう: コード: 1.html <div class="user...

Mysql general_log をクリーンアップする方法の概要

方法1: グローバル general_log を 'OFF' に設定します。 テーブ...

Vueはキャンバスの手書き入力を使用して中国語を認識します

効果画像: 序文:最近、屋外の大画面プロジェクトに取り組んでいました。システムの入力方法は使いにくか...

CSS3のtext-fill-colorプロパティの詳細な説明

text-fill-color とは何を意味しますか?文字通りの意味から言えば、「テキストの塗りつぶ...

Vueはタブ切り替えを実装します

この記事では、タブ切り替えを実装するためのVueの具体的なコードを例として紹介します。具体的な内容は...

JavaScript WebAPI、DOM、イベント、操作要素例の詳しい説明

目次ウェブAPI DOM DOMツリーDOM要素取得方法ドキュメントオブジェクトのプロパティイベント...

Docker ベースの Jenkins のデプロイに関する詳細なチュートリアル

このドキュメントを作成した当時は2019年12月頃で、er2.200が最新バージョンでした。 1.画...

理論の普及——ユーザーエクスペリエンス

1. 概念分析 1: UE ユーザー エクスペリエンス <br />英語ではユーザー エ...

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

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