screenshots
The target
The purpose of the game is to experience the use of JavaScript advanced syntax, not the ability to abstract objects. Using object-oriented approach to analyze problems requires a long process of accumulation.
The development tools
VS Code
Project file setup
Now we officially start the snake game production.
Set up the project file directory
Build the page
Put a container for the game scene div#map and style it. The code in index. HTML is as follows:
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div class="map" id="map"></div>
</body>
</html>
Copy the code
Create a new index. CSS file in the CSS folder and edit it with the following code:
* {
margin: 0;
padding: 0;
}
.map {
position: relative;
width: 800px;
height: 600px;
background-color: lightgray;
}
Copy the code
Use Alt + B shortcut keys in index. HTML to open it in the browser and generate the game background as follows:
Analyze the objects the game needs to create
Objects to see:
- Food
- Serpent (snake)
Invisible objects:
- Game logic, etc
Creating a food object
Add tool method objects. Add tools.js to the js folder and write the following code:
(function () {
// Create a tool object with multiple tool methods added inside
var Tools = {
// Get a random integer inside a range
getRandom: function (min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; // Contain maximum value, contain minimum value
},
// Get the random color method
getColor: function () {
// RGB (r,g,b) three color values can be randomly selected between 0 and 255 numbers
// Get three color values
var r = this.getRandom(0.255);
var g = this.getRandom(0.255);
var b = this.getRandom(0.255);
// Return a color value
return "rgb(" + r + "," + g + "," + b + ")"; }};window.Tools = Tools; }) ();Copy the code
Add the foods.js file to the js folder and open the edit and write the following code: Create a food object
function Food(option) {
// Avoid passing parameters of the wrong data type or without passing parameters
option = option instanceof Object ? option : {};
// The data passed in May be objects like arrays, so you need to make a further judgment
this.width = option.width || 20;
this.height = option.height || 20;
this.x = option.x || 0;
this.y = option.y || 0;
this.color = option.color || "green";
// Add an attribute to store all future div elements rendered from this object
this.elements = [];
}
Copy the code
Render on the page
// Render an element onto the page that needs to be added to the method of the prototype object
Food.prototype.render = function (map) {
Create a new div element
var ele = document.createElement("div");
// Add the corresponding style
ele.style.width = this.width + "px";
ele.style.height = this.height + "px";
ele.style.left = this.x + "px";
ele.style.top = this.y + "px";
ele.style.backgroundColor = this.color;
// Add the new element to the specified parent
map.appendChild(ele);
// Add the new element to the array to facilitate the later call to delete
this.elements.push(ele);
};
Copy the code
To test, again write the following code in foods.js.
// Get the map element
var map = document.getElementById("map");
/ / test
var food = new Food();
food.render(map);
Copy the code
Then import all the js files in index.html as follows:
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, </title> <link rel="stylesheet" href=" CSS /index.css"> </head> <body> <div class="map" id="map"></div> <script src="js/tools.js"></script> <script src="js/foods.js"></script> </body> </html>Copy the code
The Alt+B shortcut opens with the default browser and a food object is rendered.
Implement random change of food object position
Now the food is fixed in position. If you want it to move randomly, you define the element as absolute position. Var ps = “absolute”; . Horizontal random analysis of food object position: Use a random function whose left value is at (0,n-1) * w, where n is the number of food items that can fit in a row and w is the width of the food object. Similarly, the relevant codes are as follows:
this.x = Tools.getRandom(0, map.clientWidth / this.width - 1) * this.width;
this.y = Tools.getRandom(0, map.clientHeight / this.height - 1) * this.height;
Copy the code
Thus, the contents of foods.js are modified as follows:
Var ps = "absolute"; Function Food(option) {function Food(option) {// Do not pass the parameter data type, or do not pass the parameter option = option instanceof Object? option : {}; / / the incoming data is likely to be similar to an array object, so need to be further determine this. Width = option. The width | | 20; this.height = option.height || 20; this.x = option.x || 0; this.y = option.y || 0; this.color = option.color || "green"; This.elements = []; // Add an attribute to store all future div elements rendered by this object. } // Render an element onto the page, Food.prototype.render = function (map) {var ele = document.createElement("div"); This. x = tools. getRandom(0, map.clientWidth/this.width - 1) * this.width; this.y = Tools.getRandom(0, map.clientHeight / this.height - 1) * this.height; Width = this.width + "px"; // Add the corresponding style ele.style.width = this.width + "px"; ele.style.height = this.height + "px"; ele.style.left = this.x + "px"; ele.style.top = this.y + "px"; ele.style.backgroundColor = this.color; ele.style.position = ps; Map. appendChild(ele); // add the new element to the specified parent. // Add the new element to the array for later calls to delete this.elements. Push (ele); }; Var map = document.getelementById ("map"); Var food = new food (); food.render(map);Copy the code
In this way, the function of random location of food is realized.
Food Deletion Method
When eaten by a snake, food disappears and is regenerated in another place. Add the following code to foods.js:
// Remove a food div element
Food.prototype.remove = function (map, i) {
// There are several ways to get the subscript of the food to be deleted
// Remove the element from the HTML structure
map.removeChild(this.elements[i]);
// Remove the element from the array
this.elements.splice(i, 1);
};
// Test, delete food after 2 seconds
setTimeout(function () {
food.remove(map, 0)},2000)
Copy the code
Regenerating food is just another callfood.render(map);
Can.
Self – calling functions close scope
Now the Food object and tools object have been basically created, but they and their methods are all global variables, which is easy to cause variable pollution and difficult to manage. So we need to wrap them again with self-calling function methods, that is (function (){Food})(); And (the function () {view}) (); Change their scope from global to local. Both global variables are set to point to the encapsulated Food object and tools object. So the contents of foods.js are as follows:
// We need to narrow down the role of the definition constructor
// Anonymous function, self-calling function, IIFE, closed scope
(function () {
// Global variables
var ps = "absolute";
// Create the food constructor
function Food(option) {
// Avoid passing parameters of the wrong data type or without passing parameters
option = option instanceof Object ? option : {};
// The data passed in May be objects like arrays, so you need to make a further judgment
this.width = option.width || 20;
this.height = option.height || 20;
this.x = option.x || 0;
this.y = option.y || 0;
this.color = option.color || "green";
// Add an attribute to store all future div elements rendered from this object
this.elements = [];
}
// Render an element onto the page that needs to be added to the method of the prototype object
Food.prototype.render = function (map) {
Create a new div element
var ele = document.createElement("div");
// Get a random x and y value each time before setting the style
this.x = Tools.getRandom(0, map.clientWidth / this.width - 1) * this.width;
this.y = Tools.getRandom(0, map.clientHeight / this.height - 1) * this.height;
// Add the corresponding style
ele.style.width = this.width + "px";
ele.style.height = this.height + "px";
ele.style.left = this.x + "px";
ele.style.top = this.y + "px";
ele.style.backgroundColor = this.color;
ele.style.position = ps;
// Add the new element to the specified parent
map.appendChild(ele);
// Add the new element to the array to facilitate the later call to delete
this.elements.push(ele);
};
// Remove a food div element
Food.prototype.remove = function (map, i) {
// There are several ways to get the subscript of the food to be deleted
// Remove the element from the HTML structure
map.removeChild(this.elements[i]);
// Remove the element from the array
this.elements.splice(i, 1);
};
// Expose the Food function with the window object for external use
window.Food = Food; }) ();// We need to find a way to call the Food function outside
Copy the code
Tools.js contains the following contents:
(function () {
// Create a tool object with multiple tool methods added inside
var Tools = {
// Get a random integer inside a range
getRandom: function (min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; // Contain maximum value, contain minimum value
},
// Get the random color method
getColor: function () {
// RGB (r,g,b) three color values can be randomly selected between 0 and 255 numbers
// Get three color values
var r = this.getRandom(0.255);
var g = this.getRandom(0.255);
var b = this.getRandom(0.255);
// Return a color value
return "rgb(" + r + "," + g + "," + b + ")"; }};window.Tools = Tools; }) ();Copy the code
Creating a snake object
Analysis needs: A snake is born with three segments, two bodies and one head, fixed at birth (upper left corner of map). Has the movement direction, the timing movement step length and other attributes. Rendering methods, movement methods, food eating methods, etc. After eating food, the snake grows in length.
Start creating:
Create Snake’s constructor and set the properties
Width The default width of the snake node is 20
Height The default height of the snake festival is 20
The body array, the head and body of the snake, starts with the head
Direction Direction of the snake by default, right can be left, top, or bottom
Through the prototype setup method
Render Creates a random snake object and prints it to the map
Encapsulation is done by self-calling the function: Expose the Snake object through the window
Create a new snake. Js file in the js folder with the following contents.
// Use self-calling functions to close scopes
(function () {
// Global variables
var ps = "absolute";
// Create the snake constructor
function Snake(option) {
// Avoid passing parameters of the wrong data type or without passing parameters
option = option instanceof Object ? option : {};
// Add attributes to the object
// Set the width and height properties of the snakestick
this.width = option.width || 20;
this.height = option.height || 20;
// Set the snake data
this.body = [
{x: 3.y: 2.color: "red"},
{x: 2.y: 2.color: "blue"},
{x: 1.y: 2.color: "blue"}];// Set the direction of the snake. You can also set it to left, top, or bottom
this.direction = "right";
// Add an array of elements to store all rendered divs
this.elements = [];
}
// Add a method to render elements to the page
Snake.prototype.render = function (map) {
// Generate the corresponding number of div elements
// go through the number group
for (var i = 0,len = this.body.length ; i < len ; i++) {
// Generate a new div element based on the data of each item in the array
var piece = this.body[i];
// Create a new element
var ele = document.createElement("div");
// Add styles
ele.style.width = this.width + "px";
ele.style.height = this.height + "px";
ele.style.left = piece.x * this.width + "px";
ele.style.top = piece.y * this.height + "px";
ele.style.position = ps;
ele.style.backgroundColor = piece.color;
// Render inside the specified parent
map.appendChild(ele);
// The new element to be added is stored in the array
this.elements.push(ele); }};// Expose the constructor through window
window.Snake = Snake; }) ();/ / test
var map = document.getElementById("map");
var snake = new Snake();
snake.render(map);
Copy the code
Then add a reference to index.html:<script src="js/snake.js"></script>
Run to get the rendered snake object.
Creating a Game object
Start the Game (draw all Game objects, render food objects and snake objects) by calling the function itself, encapsulate the Game, Comment out the original test code. Game.js is as follows:
// The self-calling function closes the scope
(function () {
// Define a global variable that stores this
var that;
// Create a game constructor
function Game(map) {
// Set three properties, store food, snake, map
this.food = new Food();
this.snake = new Snake();
this.map = map;
that = this;
}
// Add a method to start the game that initializes the snake and food
Game.prototype.start = function () {
// 1. Add snakes and food to the map
this.food.render(this.map);
this.food.render(this.map);
this.food.render(this.map);
this.snake.render(this.map);
}
// Expose the constructor through window
window.Game = Game; }) ();/ / test
var map = document.getElementById("map");
game = new Game();
game.start();
Copy the code
Alt+B shortcut in index.html using the default browser.
Add movement to the snake
Analysis: When the snake moves one square, each segment of the snake moves to the position of the previous one. So we can deal with the movements of the snake from back to front, and then we can deal with the movements of the snake’s head. Add the following movement method to the self-calling function of snake. Js:
// Add the snake movement method
Snake.prototype.move = function () {
// Each segment of the snake becomes the same as the previous one
// The loop needs to start with the last item in order to avoid premature changes to the previous data
for (var i = this.body.length - 1 ; i > 0 ; i--) {
this.body[i].x = this.body[i-1].x;
this.body[i].y = this.body[i-1].y;
}
// Store the snakehead data
var head = this.body[0];
// The head of the snake changes position according to the direction
switch (this.direction) {
case "right":
head.x += 1;
break;
case "left":
head.x -= 1;
break;
case "top":
head.y -= 1;
break;
case "bottom":
head.y += 1;
}
Copy the code
When used, call snake. Move () and render snake. Render () to achieve the movement. However, we rendered the snake object twice, which is equivalent to a second snake covering the top of the first snake. The last render didn’t disappear, the snake looked like it had an extra knot of tail, so we had to delete the last render. Add the following deletion method to snake. Js:
// Remove all div elements from the snake that was last rendered
Snake.prototype.remove = function (map) {
// Iterate over the number group and delete all elements
// Delete the element from the HTML structure
for (var i = this.elements.length - 1 ; i >= 0 ; i--) {
map.removeChild(this.elements[i]);
}
// The array also needs to be emptied
this.elements = [];
}
Copy the code
Override the start method in game.js:
// Add a method to start the game that initializes the snake and food
Game.prototype.start = function () {
// 1. Add snakes and food to the map
this.food.render(this.map);
this.food.render(this.map);
this.food.render(this.map);
this.snake.render(this.map);
this.snake.move();
this.snake.remove(this.map);
this.snake.render(this.map);
}
Copy the code
Save and run Alt+B in index.html to see that the snake has moved one space to the right.It is equivalent to snake calling the move(), remove(), and render() methods once to make the snake object move one space.
Game logic writing
Analysis: After rendering the snake and food to the map, need: 1. Make the snake move automatically runSnake(); In addition, during exercise, eating food will increase the snake body, hitting the wall will end the game. 2. Control the movement direction of the snake through the up, down, and left arrow bindKey(); Game.js is modified as follows:
// The self-calling function closes the scope
(function () {
// Define a global variable that stores this
var that;
// Create a game constructor
function Game(map) {
// Set three properties, store food, snake, map
this.food = new Food();
this.snake = new Snake();
this.map = map;
that = this;
}
// Add a method to start the game that initializes the snake and food
Game.prototype.start = function () {
// 1. Add snakes and food to the map
this.food.render(this.map);
this.food.render(this.map);
this.food.render(this.map);
this.snake.render(this.map);
// 2. Let the game logic begin
// 2.1 Make the snake move automatically
runSnake();
// 2.2 Control the movement direction of the snake through the up, down and left arrows
bindKey();
}
// Encapsulates a private function that controls the direction in which the up, down, left, and right keys change
function bindKey() {
// Bind keyboard press events to the document
document.onkeydown = function (e) {
// console.log(e.keyCode);
// Keyboard encoding
// 37 -- left
// 38 -- top
// 39 -- right
// 40 -- bottom
switch (e.keyCode) {
case 37:
that.snake.direction = "left";
break;
case 38:
that.snake.direction = "top";
break;
case 39:
that.snake.direction = "right";
break;
case 40:
that.snake.direction = "bottom";
break; }}; }// Encapsulates a private function that can only be called inside the module
function runSnake() {
// Start a timer to make the snake move continuously
var timer = setInterval(function () {
// This inside the timer function refers to window
// Make the snake move
that.snake.move();
// Delete the previous snake
that.snake.remove(that.map);
// Render snake in new position
that.snake.render(that.map);
// Record the largest position
var maxX = that.map.offsetWidth / that.snake.width;
var maxY = that.map.offsetHeight / that.snake.height;
// Find the current snakehead location
var headX = that.snake.body[0].x;
var headY = that.snake.body[0].y;
// Every time the snake moves to a new location, it decides whether it has eaten
// 2.3 Judge whether the snake head colliders with the food, eat the food, and add a section to it
// Record the coordinates of the food
// var foodX = that.food.x;
// var foodY = that.food.y;
// Get the coordinate position of the snake head, px value
var hX = headX * that.snake.width;
var hY = headY * that.snake.height;
/ / determine
// Compare each element in the array of foods, who was eaten, remove themselves, render a new element
for (var i = 0 ; i < that.food.elements.length ; i++) {
if (that.food.elements[i].offsetLeft === hX && that.food.elements[i].offsetTop === hY) {
// Eat the food
// Let the food be deleted, then render a new food
that.food.remove(that.map,i);
that.food.render(that.map);
// Add a new snake festival
var last = that.snake.body[that.snake.body.length - 1];
that.snake.body.push({
x: last.x,
y: last.y,
color: last.color }); }}// Every time you move, check if you are out of the map and the game is over
// 2.4 Determine if it is out of the map and end the game
// Make a judgment
if (headX < 0 || headX >= maxX || headY < 0 || headY >= maxY) {
// Stop the timer
clearInterval(timer);
// Pop up a reminder
alert("Game over"); }},150);
}
// Expose the constructor through window
window.Game = Game; }) ();/ / test
var map = document.getElementById("map");
game = new Game(map);
game.start();
Copy the code
At this point, the game function is basically completed. Here are some optimizations for non-functional implementations.
Code optimization
All use self-calling functions
We need to wrap the test part of game.js into a separate JS file and use it as a self-calling function. So we create a new main.js file in the js folder with the following contents:
// Use self-calling functions to close scopes
(function () {
var map = document.getElementById("map");
var game = newGame(map); game.start(); }) ();Copy the code
Add a reference to index.html: Thus, each JS file is a self-calling function, each with its own function and scope.
Arguments to a self-calling function
In the self-calling function, we use the window variable to expose the constructor through the window. When parsing, the interpreter will jump out of scope every time to look for the global variable Window, which is inefficient and cannot be compressed like other variables when compressing the code, so we need to pass the window parameter to the self-calling function. Since undefined can be overridden to give a new value in IE8, we also pass undefined, in the scope of the self-calling anonymous function, to make sure undefined is really undefined. Thus, all self-calling functions are of the following form:
(function (window.undefined) ({})window.undefined);
Copy the code
Js code compression
Create a new index.js folder in the js folder, which contains the contents of tools.js, foods.js, snake. Js, game.js, and main.js in order:
// All module code should be introduced in a certain order
// ======================Tools============================; (function (window.undefined) {
// Create a tool object with multiple tool methods added inside
var Tools = {
// Get a random integer inside a range
getRandom: function (min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; // Contain maximum value, contain minimum value
},
// Get the random color method
getColor: function () {
// RGB (r,g,b) three color values can be randomly selected between 0 and 255 numbers
// Get three color values
var r = this.getRandom(0.255);
var g = this.getRandom(0.255);
var b = this.getRandom(0.255);
// Return a color value
return "rgb(" + r + "," + g + "," + b + ")"; }};window.Tools = Tools; }) (window.undefined)
// ==================Food===========================; (function (window.undefined) {
// Global variables
var ps = "absolute";
// Create the food constructor
function Food(option) {
// Avoid passing parameters of the wrong data type or without passing parameters
option = option instanceof Object ? option : {};
// The data passed in May be objects like arrays, so you need to make a further judgment
this.width = option.width || 20;
this.height = option.height || 20;
this.x = option.x || 0;
this.y = option.y || 0;
this.color = option.color || "green";
// Add an attribute to store all future div elements rendered from this object
this.elements = [];
}
// Render an element onto the page that needs to be added to the method of the prototype object
Food.prototype.render = function (map) {
Create a new div element
var ele = document.createElement("div");
// Get a random x and y value each time before setting the style
this.x = Tools.getRandom(0, map.clientWidth / this.width - 1) * this.width;
this.y = Tools.getRandom(0, map.clientHeight / this.height - 1) * this.height;
// Add the corresponding style
ele.style.width = this.width + "px";
ele.style.height = this.height + "px";
ele.style.left = this.x + "px";
ele.style.top = this.y + "px";
ele.style.backgroundColor = this.color;
ele.style.position = ps;
// Add the new element to the specified parent
map.appendChild(ele);
// Add the new element to the array to facilitate the later call to delete
this.elements.push(ele);
};
// Remove a food div element
Food.prototype.remove = function (map, i) {
// There are several ways to get the subscript of the food to be deleted
// Remove the element from the HTML structure
map.removeChild(this.elements[i]);
// Remove the element from the array
this.elements.splice(i, 1);
};
// Expose the Food function with the window object for external use
window.Food = Food; }) (window.undefined)
// ===================Snake=============================; (function (window.undefined) {
// Global variables
var ps = "absolute";
// Create the snake constructor
function Snake(option) {
// Avoid passing parameters of the wrong data type or without passing parameters
option = option instanceof Object ? option : {};
// Add attributes to the object
// Set the width and height properties of the snakestick
this.width = option.width || 20;
this.height = option.height || 20;
// Set the snake data
this.body = [
{x: 3.y: 2.color: "red"},
{x: 2.y: 2.color: "blue"},
{x: 1.y: 2.color: "blue"}];// Set the direction of the snake. You can also set it to left, top, or bottom
this.direction = "right";
// Add an array of elements to store all rendered divs
this.elements = [];
}
// Add a method to render elements to the page
Snake.prototype.render = function (map) {
// Generate the corresponding number of div elements
// go through the number group
for (var i = 0,len = this.body.length ; i < len ; i++) {
// Generate a new div element based on the data of each item in the array
var piece = this.body[i];
// Create a new element
var ele = document.createElement("div");
// Add styles
ele.style.width = this.width + "px";
ele.style.height = this.height + "px";
ele.style.left = piece.x * this.width + "px";
ele.style.top = piece.y * this.height + "px";
ele.style.position = ps;
ele.style.backgroundColor = piece.color;
// Render inside the specified parent
map.appendChild(ele);
// The new element to be added is stored in the array
this.elements.push(ele); }};// Add the snake movement method
Snake.prototype.move = function () {
// Each segment of the snake becomes the same as the previous one
// The loop needs to start with the last item in order to avoid premature changes to the previous data
for (var i = this.body.length - 1 ; i > 0 ; i--) {
this.body[i].x = this.body[i-1].x;
this.body[i].y = this.body[i-1].y;
}
// Store the snakehead data
var head = this.body[0];
// The head of the snake changes position according to the direction
switch (this.direction) {
case "right":
head.x += 1;
break;
case "left":
head.x -= 1;
break;
case "top":
head.y -= 1;
break;
case "bottom":
head.y += 1; }};// Remove all div elements from the snake that was last rendered
Snake.prototype.remove = function (map) {
// Iterate over the number group and delete all elements
// Delete the element from the HTML structure
for (var i = this.elements.length - 1 ; i >= 0 ; i--) {
map.removeChild(this.elements[i]);
}
// The array also needs to be emptied
this.elements = [];
}
// Expose the constructor through window
window.Snake = Snake; }) (window.undefined)
// ========================Game===================; (function (window.undefined) {
// Define a global variable that stores this
var that;
// Create a game constructor
function Game(map) {
// Set three properties, store food, snake, map
this.food = new Food();
this.snake = new Snake();
this.map = map;
that = this;
}
// Add a method to start the game that initializes the snake and food
Game.prototype.start = function () {
// 1. Add snakes and food to the map
this.food.render(this.map);
this.food.render(this.map);
this.food.render(this.map);
this.snake.render(this.map);
// 2. Let the game logic begin
// 2.1 Make the snake move automatically
runSnake();
// 2.2 Control the movement direction of the snake through the up, down and left arrows
bindKey();
}
// Encapsulates a private function that controls the direction in which the up, down, left, and right keys change
function bindKey() {
// Bind keyboard press events to the document
document.onkeydown = function (e) {
// console.log(e.keyCode);
// Keyboard encoding
// 37 -- left
// 38 -- top
// 39 -- right
// 40 -- bottom
switch (e.keyCode) {
case 37:
that.snake.direction = "left";
break;
case 38:
that.snake.direction = "top";
break;
case 39:
that.snake.direction = "right";
break;
case 40:
that.snake.direction = "bottom";
break; }}; }// Encapsulates a private function that can only be called inside the module
function runSnake() {
// Start a timer to make the snake move continuously
var timer = setInterval(function () {
// This inside the timer function refers to window
// Make the snake move
that.snake.move();
// Delete the previous snake
that.snake.remove(that.map);
// Render snake in new position
that.snake.render(that.map);
// Record the largest position
var maxX = that.map.offsetWidth / that.snake.width;
var maxY = that.map.offsetHeight / that.snake.height;
// Find the current snakehead location
var headX = that.snake.body[0].x;
var headY = that.snake.body[0].y;
// Every time the snake moves to a new location, it decides whether it has eaten
// 2.3 Judge whether the snake head colliders with the food, eat the food, and add a section to it
// Record the coordinates of the food
// var foodX = that.food.x;
// var foodY = that.food.y;
// Get the coordinate position of the snake head, px value
var hX = headX * that.snake.width;
var hY = headY * that.snake.height;
/ / determine
// Compare each element in the array of foods, who was eaten, remove themselves, render a new element
for (var i = 0 ; i < that.food.elements.length ; i++) {
if (that.food.elements[i].offsetLeft === hX && that.food.elements[i].offsetTop === hY) {
// Eat the food
// Let the food be deleted, then render a new food
that.food.remove(that.map,i);
that.food.render(that.map);
// Add a new snake festival
var last = that.snake.body[that.snake.body.length - 1];
that.snake.body.push({
x: last.x,
y: last.y,
color: last.color }); }}// Every time you move, check if you are out of the map and the game is over
// 2.4 Determine if it is out of the map and end the game
// Make a judgment
if (headX < 0 || headX >= maxX || headY < 0 || headY >= maxY) {
// Stop the timer
clearInterval(timer);
// Pop up a reminder
alert("Game over"); }},150);
}
// Expose the constructor through window
window.Game = Game; }) (window.undefined)
// ========================== Main =========================; (function (window.undefined) {
var map = document.getElementById("map");
var game = newGame(map); game.start(); }) (window.undefined)
Copy the code
Search for “code compression” in a search engine, and you’ll find an online compression tool that removes comments, whitespace, and identifier obfuscation. The transmission speed will be improved after compression. We compress the contents of index.js. Create a new index.min.js file in the js folder, and the content is the compressed code:
(function(){var a={getRandom:function(c,b){c=Math.ceil(c); b=Math.floor(b); Return Math. Floor (Math. The random () * (b - c + 1)) + c}, getColor: function () {var e = this. GetRandom (0255); Var d = this. GetRandom (0255); Var c = this. GetRandom (0255); return"rgb("+e+","+d+","+c+")"}}; window.Tools=a})(); (function(){var b="absolute"; function a(c){c=c instanceof Object? c:{}; this.width=c.width||20; this.height=c.height||20; this.x=c.x||0; this.y=c.y||0; this.color=c.color||"green"; this.elements=[]}a.prototype.render=function(d){var c=document.createElement("div"); this.x=Tools.getRandom(0,d.clientWidth/this.width-1)*this.width; this.y=Tools.getRandom(0,d.clientHeight/this.height-1)*this.height; c.style.width=this.width+"px"; c.style.height=this.height+"px"; c.style.left=this.x+"px"; c.style.top=this.y+"px"; c.style.backgroundColor=this.color; c.style.position=b; d.appendChild(c); this.elements.push(c)}; a.prototype.remove=function(d,c){d.removeChild(this.elements[c]); this.elements.splice(c,1)}; window.Food=a})(); (function(){var b="absolute"; function a(c){c=c instanceof Object? c:{}; this.width=c.width||20; this.height=c.height||20; this.body=[{x:3,y:2,color:"red"},{x:2,y:2,color:"blue"},{x:1,y:2,color:"blue"}]; this.direction="right"; this.elements=[]}a.prototype.render=function(g){for(var d=0,c=this.body.length; d<c; d++){var e=this.body[d]; var f=document.createElement("div"); f.style.width=this.width+"px"; f.style.height=this.height+"px"; f.style.left=e.x*this.width+"px"; f.style.top=e.y*this.height+"px"; f.style.position=b; f.style.backgroundColor=e.color; g.appendChild(f); this.elements.push(f)}}; a.prototype.move=function(){for(var d=this.body.length-1; d>0; d--){this.body[d].x=this.body[d-1].x; this.body[d].y=this.body[d-1].y}var c=this.body[0]; switch(this.direction){case"right":c.x+=1; break; case"left":c.x-=1; break; case"top":c.y-=1; break; case"bottom":c.y+=1}}; a.prototype.remove=function(d){for(var c=this.elements.length-1; c>=0; c--){d.removeChild(this.elements[c])}this.elements=[]}; window.Snake=a})(); (function(){var c; function d(e){this.food=new Food(); this.snake=new Snake(); this.map=e; c=this}d.prototype.start=function(){this.food.render(this.map); this.food.render(this.map); this.food.render(this.map); this.snake.render(this.map); b(); a()}; function a(){document.onkeydown=function(f){switch(f.keyCode){case 37:c.snake.direction="left"; break; case 38:c.snake.direction="top"; break; case 39:c.snake.direction="right"; break; case 40:c.snake.direction="bottom"; break}}}function b(){var e=setInterval(function(){c.snake.move(); c.snake.remove(c.map); c.snake.render(c.map); var l=c.map.offsetWidth/c.snake.width; var j=c.map.offsetHeight/c.snake.height; var f=c.snake.body[0].x; var n=c.snake.body[0].y; var m=f*c.snake.width; var k=n*c.snake.height; for(var g=0; g<c.food.elements.length; g++){if(c.food.elements[g].offsetLeft===m&&c.food.elements[g].offsetTop===k){c.food.remove(c.map,g); c.food.render(c.map); var h=c.snake.body[c.snake.body.length-1]; c.snake.body.push({x:h.x,y:h.y,color:h.color})}}if(f<0||f>=l||n<0||n>=j){clearInterval(e); alert("Game over")}},150)}window.Game=d})(); (function(){var b=document.getElementById("map"); var a=new Game(b); a.start()})();Copy the code
Later, there will be a package tool compression, instead of manual compression. We are now in order to understand this compression process, to develop this awareness. Index.html simply introduces a js file named index.min.js, which contains the following contents:
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div class="map" id="map"></div>
<! -- Import multiple js files -->
<! -- <script src="js/tools.js"></script> <script src="js/food.js"></script> <script src="js/snake.js"></script> <script src="js/game.js"></script> <script src="js/main.js"></script> -->
<! To optimize performance, you need to reduce the number of HTTP requests the browser sends.
<! -- <script src="js/index.js"></script> -->
<script src="js/index.min.js"></script>
</body>
</html>
Copy the code
Run Alt+B to get the same gameplay effect.
Ahh, I am good at cooking!!