JavaScript exquisite snake implementation process

JavaScript exquisite snake implementation process

This article is not simple! !

Today, the blogger worked hard to write a small snake game. The whole process from scratch was simply thrilling.

Next, this blogger will talk about this process in detail! !

Without further ado, let's take a look at the final presentation.

Only after watching it did I understand what operation is, it's simply legendary! !

Next, let’s talk about the actual operation without bragging!

First of all, we need to know that the so-called snake is nothing more than the colors walking on the table! The initial effect is as shown below

Of course, arrays are used for operations here, and constructors are used for encapsulation.

Three js files are encapsulated here, which are used to write food, snakes, and our mediator Game.js file!

As I just said, writing a snake is a process from scratch, so at the beginning there was nothing in our index.html, just a div box, and the other tables, snakes, and food were all created later using functions.

1. Create HTML structure

The following is the initial code in our body:

<body>
    <div id="app">
    </div>
    <script src="js/Snake.js"></script>
    <script src="js/Food.js"></script>
    <script src="js/Game.js"></script>
    <script>
        var game = new Game();
    </script>
</body>

2. Create a table

The first step from scratch is, of course, to add our table to the page first, so we need a general framework! ! In this way, you can see the table shown in the picture above. Seeing this, it seems that every next step is worth it!

function Game() {
    this.row = 25; //Number of rows this.col = 25; //Number of columns this.init(); //Initialize the node }
Game.prototype.init = function () {
    this.dom = document.createElement('table'); // Create a table var tr, td;
    // Traverse rows and columns for (var i = 0; i < this.row; i++) {
        tr = document.createElement('tr'); // Create a row for (var j = 0; j < this.col; j++) {
            td = document.createElement('td'); // Create a column tr.appendChild(td); // Append the column to the row }
        this.dom.appendChild(tr); // Append the row to the table}
    document.querySelector('#app').appendChild(this.dom); //Append the table to the div}

3. Create the snake head and body

The second step from nothing to something, snake head snake head snake head, snake body snake body snake body! Seeing this, I realized how important it is to learn and know.

function Snake() {
    // Initialization body of the snake this.body = [
        { 'row': 3, 'col': 5 },
        { 'row': 3, 'col': 4 },
        { 'row': 3, 'col': 3 },
        { 'row': 3, 'col': 2 }
    ];
}
Snake.prototype.render = function () {
    // Rendering of snake head game.setColorHead(this.body[0].row, this.body[0].col);
    // Rendering of the snake body for (var i = 1; i < this.body.length; i++) {
        game.setColor(this.body[i].row, this.body[i].col, '#649c49')
    }
}

Snake calls the properties of the mediator Game prototype object!

Game.prototype.setColor = function (row, col, color) {
    this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].style.background = color;
}

4. Create Food

The third step from nothing to something is food, food, food! Seeing this, we have all the basic forms!

function Food(gameSnake) {
    var self = this;
    // The following do-while loop statement is used to create a row and col first and then determine whether the row and col are on the snake. do {
        // Food location this.row = parseInt(Math.random() * gameSnake.row)
        this.col = parseInt(Math.random() * gameSnake.col)
    } while ((function () {
        // Traverse the row and col of the snake and then check whether it overlaps with the newly randomly generated row and col of food for (var i = 0; i < gameSnake.snake.body.length; i++) {
            if (self.row == gameSnake.snake.body[i].row && self.col == gameSnake.snake.body[i].col) {
                return true;
            }
        }
        return false;
    })());
}
Food.prototype.render = function () {
    game.setHTML(this.row, this.col);
}

5. Make the snake move

The fourth step from nothing to something: get moving, move, move! Using the head, tail, and deletion of an array here is a perfect match!

//Snake movementSnake.prototype.update = function () {
    this.direction = this.willDirection;
    switch (this.direction) {
        case 'R': //right this.body.unshift({ 'row': this.body[0].row, 'col': this.body[0].col + 1 });
            break;
        case 'D': //Next this.body.unshift({ 'row': this.body[0].row + 1, 'col': this.body[0].col });
            break;
        case 'L': //left this.body.unshift({ 'row': this.body[0].row, 'col': this.body[0].col - 1 });
            break;
        case 'U': //up this.body.unshift({ 'row': this.body[0].row - 1, 'col': this.body[0].col });
            break;
    }
    // Judgment of death, the part beyond the edge of the table if (this.body[0].col > game.col - 1 || this.body[0].col < 0 || this.body[0].row > game.row - 1 || this.body[0].row < 0) {
        alert('I hit the wall, I ate a total of ' + game.score + 'strawberries');
        this.body.shift();
        clearInterval(game.timer);
        location.reload();
    }
    // When you hit yourself, you will be judged dead for (var i = 1; i < this.body.length; i++) {
        // If the row and col of the current snake's head and a certain part of the body completely overlap if (this.body[0].row == this.body[i].row && this.body[0].col == this.body[i].col) {
            alert('Bumped into myself and ate it' + game.score + 'strawberry');
            this.body.shift();
            clearInterval(game.timer);
            location.reload();
        }
    }
    // Snake eating food // If the current snake's head does not overlap with the food, it means that it has not eaten the food at this time. At this time, the tail is deleted. If it overlaps, it means that it is late. At this time, we do not delete the tail if (this.body[0].row == game.food.row && this.body[0].col == game.food.col) {
        // At this time, only the head is added, and the tail is not deleted game.food = new Food(game); //Create a new food game.score++;
        game.f = 0;
    } else {
        this.body.pop(); //Delete the last element of the array}
}

6. Control the direction of the snake

The fifth step from nothing to something is the direction of the snake! When you get here, looking back at every step in the past, they are all just floating clouds! !

// Change the direction of the snake to prevent it from turning around before rendering once Snake.prototype.changeDirection = function (d) {
    this.willDirection = d;
}
// Set up keyboard event monitoring Game.prototype.bindEvent = function () {
    var self = this;
    document.addEventListener('keydown', function (e) {
        // Use ASCII code value to determine the keyboard direction switch (e.keyCode) {
            case 37: //leftif (self.snake.direction == 'R') return; // First judge, if the current direction is moving to the right, we cannot press the left button at this time self.snake.changeDirection('L');
                self.d = 'L';
                break;
            case 38: //up if (self.snake.direction == 'D') return; // First make a judgment, if the current direction is moving downward, we cannot press the up key at this time self.snake.changeDirection('U');
                self.d = 'U';
                break;
            case 39: //rightif (self.snake.direction == 'L') return; // First make a judgment, if the current direction is moving left, we cannot press the right button at this time self.snake.changeDirection('R');
                self.d = 'R';
                break;
            case 40: //Nextif (self.snake.direction == 'U') return; // First judge, if the current direction is moving upward, we cannot press the key at this time self.snake.changeDirection('D');
                self.d = 'D';
                break;
        }
    })
}

Finally, just set the style as we like. Here I set the corresponding color according to my favorite pink and insert the food I like! !

7. Complete code

index.html

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Snake</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #app {
            position: relative;
            border: 20px solid #f8bbd0;
            background-color: #fce4ec;
            width: 500px;
            height: 500px;
            margin: 15px auto;
        }
 
        table {
            border-collapse: collapse;
            background-color: #fce4ec;
        }
 
        td {
            position: relative;
            background-size: 100% 100%;
            border-radius: 50%;
            width: 20px;
            height: 20px;
            text-align: center;
            /* background-color: #fce4ec; */
            /* border: 1px solid #aaa; */
        }
 
        td .snake {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
 
        .start,
        .suspend {
            cursor: pointer;
            position: absolute;
            width: 150px;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
 
        .suspend {
            display: none;
            z-index: 2;
        }
    </style>
</head>
 
<body>
    <!-- <h3 id="f">Frame number: 0</h3>
    <h3 id="score">Score: 0</h3> -->
    <div id="app">
        <img src="images/start.gif" alt="" class="start">
        <img src="images/suspended.png" alt="" class="suspend">
    </div>
    <!-- <script src="js/last.js"></script> -->
    <script src="js/Snake.js"></script>
    <script src="js/Food.js"></script>
    <script src="js/Game.js"></script>
    <script>
        var game = null;
        var flag = true;
        var suspend = document.querySelector('.suspend');
        document.querySelector('.start').addEventListener('click', function () {
            // document.querySelector('#app').style.backgroundColor='white';
            this.style.display = 'none';
            game = new Game();
            document.querySelector('table').addEventListener('click', function () {
                clearInterval(game.timer);
                suspend.style.display = 'block';
 
            })
            suspend.addEventListener('click', function () {
                suspend.style.display = 'none';
                game.timer = setInterval(function () {
                    game.f++;
                    // document.getElementById('f').innerHTML = 'Frame number:' + game.f;
                    // document.getElementById('score').innerHTML = 'Score:' + game.score;
                    // Clear the screen game.clear();
                    // Snake movement (update)
                    // Update speed of the snake. When the snake becomes longer, the speed should be increased var during = game.snake.body.length < 30 ? 30 - game.snake.body.length : 1;
                    game.f % during == 0 && game.snake.update();
 
                    // game.snake.update();
                    // Render the snake game.snake.render();
                    // Render food game.food.render();
                }, 10)
            })
        })
    </script>
</body>
 
</html>

Game.js

function Game() {
    this.row = 25; //Number of rowsthis.col = 25; //Number of columnsthis.score = 0; //Scorethis.init(); //Initialize nodethis.snake = new Snake(); //Instantiate snake classthis.food = new Food(this); //Initialize food// this.last = new Last();
    this.start(); //Execute timer task this.bindEvent(); //Keyboard event monitoring this.d = 'R';
}
Game.prototype.init = function () {
    this.dom = document.createElement('table'); // Create a table var tr, td;
    // Traverse rows and columns for (var i = 0; i < this.row; i++) {
        tr = document.createElement('tr'); // Create a row for (var j = 0; j < this.col; j++) {
            td = document.createElement('td'); // Create a column tr.appendChild(td); // Append the column to the row }
        this.dom.appendChild(tr); // Append the row to the table}
    document.querySelector('#app').appendChild(this.dom); //Append the table to the div}
// Traverse the table and clear the colors on the table Game.prototype.clear = function () {
    for (var i = 0; i < this.row; i++) {
        for (var j = 0; j < this.col; j++) {
            this.dom.getElementsByTagName('tr')[i].getElementsByTagName('td')[j].style.background = '';
            this.dom.getElementsByTagName('tr')[i].getElementsByTagName('td')[j].innerHTML = '';
        }
    }
}
// How to set the color of the table's row and column Game.prototype.setColor = function (row, col, color) {
    this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].style.background = color;
}
// Set the snake head Game.prototype.setColorHead = function (row, col) {
    var img = document.createElement('img');
    img.src = 'images/snake.png';
    img.className = 'snake';
    this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].appendChild(img);
    // this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].style.backgroundColor='transparent'
    switch (this.d) {
        case 'R': //right break;
        case 'D': //Next img.style.transform = 'rotate(90deg)';
                break;
        case 'L': //left img.style.transform = 'rotate(180deg)';
                break;
        case 'U': //upper img.style.transform = 'rotate(-90deg)';
                break;
    }
}
// Rendering food Game.prototype.setHTML = function (row, col) {
    this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].style.backgroundImage = 'url(./images/food.png)';
}
// Set up keyboard event monitoring Game.prototype.bindEvent = function () {
    var self = this;
    document.addEventListener('keydown', function (e) {
        // Use ASCII code value to determine the keyboard direction switch (e.keyCode) {
            case 37: //leftif (self.snake.direction == 'R') return; // First judge, if the current direction is moving to the right, we cannot press the left button at this time self.snake.changeDirection('L');
                self.d = 'L';
                break;
            case 38: //up if (self.snake.direction == 'D') return; // First make a judgment, if the current direction is moving downward, we cannot press the up key at this time self.snake.changeDirection('U');
                self.d = 'U';
                break;
            case 39: //rightif (self.snake.direction == 'L') return; // First make a judgment, if the current direction is moving left, we cannot press the right button at this time self.snake.changeDirection('R');
                self.d = 'R';
                break;
            case 40: //Nextif (self.snake.direction == 'U') return; // First judge, if the current direction is moving upward, we cannot press the key at this time self.snake.changeDirection('D');
                self.d = 'D';
                break;
        }
    })
}
Game.prototype.start = function () {
    // Frame number this.f = 0;
    // The core of the timer is the essence of game rendering: clear screen - update - render this.timer = setInterval(function () {
        game.f++;
        // document.getElementById('f').innerHTML = 'Frame number:' + game.f;
        // document.getElementById('score').innerHTML = 'Score:' + game.score;
        // Clear the screen game.clear();
        // Snake movement (update)
        // Update speed of the snake. When the snake becomes longer, the speed should be increased var during = game.snake.body.length < 30 ? 30 - game.snake.body.length : 1;
        game.f % during == 0 && game.snake.update();
        // game.snake.update();
        // Render the snake game.snake.render();
        // Render food game.food.render();
    }, 10)
}

Snake.js

function Snake() {
    // Initialization body of the snake this.body = [
        { 'row': 3, 'col': 5 },
        { 'row': 3, 'col': 4 },
        { 'row': 3, 'col': 3 },
        { 'row': 3, 'col': 2 }
    ];
    this.direction = 'R'; //Semaphore, set the direction of movement this.willDirection = 'R'; //The direction to be changed is to make a U-turn on the spot}
Snake.prototype.render = function () {
    // Rendering of snake head game.setColorHead(this.body[0].row, this.body[0].col);
    // Rendering of the snake body for (var i = 1; i < this.body.length; i++) {
        game.setColor(this.body[i].row, this.body[i].col, '#649c49')
    }
}
//Snake movementSnake.prototype.update = function () {
    this.direction = this.willDirection;
    switch (this.direction) {
        case 'R': //right this.body.unshift({ 'row': this.body[0].row, 'col': this.body[0].col + 1 });
            break;
        case 'D': //Next this.body.unshift({ 'row': this.body[0].row + 1, 'col': this.body[0].col });
            break;
        case 'L': //left this.body.unshift({ 'row': this.body[0].row, 'col': this.body[0].col - 1 });
            break;
        case 'U': //up this.body.unshift({ 'row': this.body[0].row - 1, 'col': this.body[0].col });
            break;
    }
    // Judgment of death, the part beyond the edge of the table if (this.body[0].col > game.col - 1 || this.body[0].col < 0 || this.body[0].row > game.row - 1 || this.body[0].row < 0) {
        alert('I hit the wall, I ate a total of ' + game.score + 'strawberries');
        this.body.shift();
        clearInterval(game.timer);
        location.reload();
    }
    // When you hit yourself, you will be judged dead for (var i = 1; i < this.body.length; i++) {
        // If the row and col of the current snake's head and a certain part of the body completely overlap if (this.body[0].row == this.body[i].row && this.body[0].col == this.body[i].col) {
            alert('Bumped into myself and ate it' + game.score + 'strawberry');
            this.body.shift();
            clearInterval(game.timer);
            location.reload();
        }
    }
    // Snake eating food // If the current snake's head does not overlap with the food, it means that it has not eaten the food at this time. At this time, the tail is deleted. If it overlaps, it means that it is late. At this time, we do not delete the tail if (this.body[0].row == game.food.row && this.body[0].col == game.food.col) {
        // At this time, only the head is added, and the tail is not deleted game.food = new Food(game); //Create a new food game.score++;
        game.f = 0;
    } else {
        this.body.pop(); //Delete the last element of the array}
}
// Change the direction of the snake to prevent it from turning around before rendering once Snake.prototype.changeDirection = function (d) {
    this.willDirection = d;
}

Food.js

function Food(gameSnake) {
    var self = this;
    // The following do-while loop statement is used to create a row and col first and then determine whether the row and col are on the snake. do {
        // Food location this.row = parseInt(Math.random() * gameSnake.row)
        this.col = parseInt(Math.random() * gameSnake.col)
    } while ((function () {
        // Traverse the row and col of the snake and then check whether it overlaps with the newly randomly generated row and col of food for (var i = 0; i < gameSnake.snake.body.length; i++) {
            if (self.row == gameSnake.snake.body[i].row && self.col == gameSnake.snake.body[i].col) {
                return true;
            }
        }
        return false;
    })());
}
Food.prototype.render = function () {
    game.setHTML(this.row, this.col);
}

8. Pictures

Next, I will put the pictures I used here, and those who like them can use them directly!

IX. Conclusion

Friends who have read to the end, do you think it is actually very simple? If you’re interested, go try it now! !

This is the end of this article about the implementation process of JavaScript exquisite snake. For more relevant JavaScript snake content, please search 123WORDPRESS.COM’s previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • JS implements the snake game
  • JavaScript to achieve the idea of ​​​​snake game
  • JavaScript implementation of classic snake game
  • JS practical object-oriented snake game example

<<:  How to solve the phantom read problem in MySQL

>>:  Detailed process of installing Presto and connecting Hive in Docker

Recommend

Solution to the blank page after vue.js packaged project

I believe that many partners who have just come i...

MySQL 5.7.19 installation and configuration method graphic tutorial (win10)

Detailed tutorial on downloading and installing M...

MySQL 8.0.24 version installation and configuration method graphic tutorial

This article records the installation and configu...

IIS7 IIS8 reverse proxy rule writing, installation and configuration method

Purpose: Treat Station A as the secondary directo...

How to build Jenkins+Maven+Git continuous integration environment on CentOS7

This article takes the deployment of Spring boot ...

jQuery plugin to implement floating menu

Learn a jQuery plugin every day - floating menu, ...

Analysis of GTK treeview principle and usage

The GtkTreeView component is an advanced componen...

Mini Program to Implement Paging Effect

This article example shares the specific code for...

JavaScript to display hidden form text

This article shares the specific code of JavaScri...

Basic operations on invisible columns in MySQL 8.0

Table of contents 01 Create invisible columns 02 ...

Some tips on deep optimization to improve website access speed

<br />The website access speed can directly ...

Install mysql5.7.13 using RPM in CentOS 7

0. Environment Operating system for this article:...