属性:方向、一组蛇节(div,div,div)、地图、食物
方法:生成蛇,增加蛇头,计算新蛇头的位置,蛇移动
属性:横向位置、纵向位置、div元素、地图
方法:随机位置
属性:蛇,食物
方法:开始
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>贪吃蛇title>
<link rel="stylesheet" href="css/index.css">
head>
<body>
<div id="map">
div>
<script src="js/all.js" >script>
<script>
// 获取页面上的地图元素
var map = document.querySelector('#map');
// 创建了一个食物对象
// var food1 = new Food(map);
// // 食物随机一下
// food1.randomLoaction();
var game = new Game(map);
game.start();
script>
body>
html>
/* 地图 */
#map {
position: relative;
margin: 0 auto;
width: 900px;
height: 600px;
background-color: #1f575c;
box-shadow: 0px 0px 50px 20px green;
}
/* 蛇头、蛇身体、食物基本样式 */
.snake-head,
.snake-body,
.food {
position: absolute;
width: 18px;
height: 18px;
border: dotted 1px black;
/* border-radius: 17px; */
}
/* 蛇的身体 */
.snake-body {
background: pink;
}
/* 蛇头样式 */
.snake-head {
background-color: red;
}
/* 食物 */
.food {
background-color: #00ff00;
}
all.js
function Food(m) {
this.x = 0;
this.y = 0;
this.div = document.createElement("div");
this.div.className = "food";
this.map = m;
this.map.appendChild(this.div)
}
Food.prototype.randomLoaction = function () {
var maxX = 900 / 20 - 1;
var maxY = 600 / 20 - 1;
var indexX = getIntNum(0, maxX);
var indexY = getIntNum(0, maxY);
this.x = indexX * 20;
this.y = indexY * 20;
this.div.style.left = this.x + "px";
this.div.style.top = this.y + "px"
};
function getIntNum(min, max) {
var num = parseInt(Math.random() * (max - min + 1) + min);
return num
};
function Snake(m, f) {
this.direction = "right";
this.bodys = [];
this.map = m;
this.food = f;
this.createBodys()
}
Snake.prototype.createBodys = function () {
for (var i = 0; i < 3; i++) {
this.insertNewHead()
}
};
Snake.prototype.insertNewHead = function () {
var newHead = document.createElement("div");
newHead.className = "snake-head";
var location = this.getNewHeadLoaction();
newHead.style.left = location.left + "px";
newHead.style.top = location.top + "px";
this.map.appendChild(newHead);
var oldHead = this.bodys[0];
if (oldHead != undefined) {
oldHead.className = "snake-body"
}
this.bodys.unshift(newHead)
};
Snake.prototype.getNewHeadLoaction = function () {
var x = 0;
y = 0;
var oldHead = this.bodys[0];
if (oldHead == undefined) {
return {left: x, top: y}
}
x = oldHead.offsetLeft;
y = oldHead.offsetTop;
switch (this.direction) {
case"left":
x = x - 20;
break;
case"right":
x = x + 20;
break;
case"bottom":
y = y + 20;
break;
case"top":
y = y - 20;
break
}
return {left: x, top: y}
};
Snake.prototype.move = function () {
var obj = this.getNewHeadLoaction();
if (obj.left < 0 || obj.left == 900 || obj.top < 0 || obj.top == 600) {
alert("想不开死了");
return true
}
var last = this.bodys.pop();
last.className = "snake-head";
var oldHead = this.bodys[0];
oldHead.className = "snake-body";
this.bodys.unshift(last);
last.style.left = obj.left + "px";
last.style.top = obj.top + "px";
if (obj.left == this.food.x && obj.top == this.food.y) {
this.insertNewHead();
this.food.randomLoaction()
}
return false
};
function Game(m) {
this.food = new Food(m);
this.snake = new Snake(m, this.food)
}
Game.prototype.start = function () {
this.food.randomLoaction();
var snake = this.snake;
var flag = window.setInterval(function () {
var isDead = snake.move();
console.log(isDead);
if (isDead) {
clearInterval(flag)
}
}, 100);
document.onkeydown = function (e) {
var code = e.keyCode;
switch (code) {
case 37:
if (snake.direction != "right") {
snake.direction = "left"
}
break;
case 38:
snake.direction = "top";
break;
case 39:
snake.direction = "right";
break;
case 40:
snake.direction = "bottom";
break
}
}
};
food.js
(function (w) {
// 形参w用来接收window对象,目的是为了缩短访问window的时间,提高程度性能。
// 1. 定义一个食物的构造函数
function Food(m) {
// 食物的横向位置
this.x = 0;
// 食物的纵向位置
this.y = 0;
// 创建一个div元素
this.div = document.createElement('div');
// 设置div的类名
this.div.className = 'food';
// 地图属性
this.map = m;
// 把div放进地图中
this.map.appendChild(this.div);
}
// 2. 定义一个随机食物的方法放入原型中
Food.prototype.randomLoaction = function () {
// this代表谁?看将来的调用者。 this→调用者。
// 将来横向的最大索引
var maxX = 900 / 20 - 1;
// 将来纵向的最大索引
var maxY = 600 / 20 - 1;
// 随机出横向和纵向的位置索引
//[0,maxX]
var indexX = getIntNum(0, maxX);
//[0,maxY]
var indexY = getIntNum(0, maxY);
// 计算位置,这里的x和y并不会直接影响div,而是保留下来为了将来和蛇头的位置对比。
this.x = indexX * 20;
this.y = indexY * 20;
// 设置div的left和top值
this.div.style.left = this.x + 'px';
this.div.style.top = this.y + 'px';
};
// 获取n-m之间的随机数 [n,m]
function getIntNum(min, max) {
// (max-min + 1) + min
var num = parseInt(Math.random() * (max - min + 1) + min);
return num;
}
// 把Food放到window中,就可以暴露出去
// window是对象
w.Food = Food;
}(window));
game.js
(function (w) {
// 游戏构造函数
function Game(m) {
// 游戏中的食物
this.food = new Food(m);
// 游戏中的蛇
this.snake = new Snake(m, this.food);
}
// 开始方法
Game.prototype.start = function () {
//0. 随机一下食物
this.food.randomLoaction();
// this → game
var snake = this.snake;
// 1. 开启定时器,让蛇不断的移动
var flag = window.setInterval(function () {
// this代表window
// 2. 调用蛇的move方法
var isDead = snake.move();
console.log(isDead);
// 判断是否死了
if (isDead) {
clearInterval(flag);
}
}, 100);
//2. 给文档注册键盘按下事件
document.onkeydown = function (e) {
// 获取键码值
var code = e.keyCode;
// 判断四种情况,更改蛇的方向,先判断蛇的移动方向
switch (code) {
case 37: // 左侧
if (snake.direction != 'right') {
snake.direction = 'left';
}
break;
case 38: // 上侧
snake.direction = 'top';
break;
case 39: // 右侧
snake.direction = 'right';
break;
case 40: // 下侧
snake.direction = 'bottom';
break;
}
};
};
//通过window将Game暴露出去
w.Game = Game;
}(window));
snake.js
(function (w) {
// 构造函数
function Snake(m, f) {
// 蛇移动的方向 left top right bottom
this.direction = 'right';
// 蛇的节数 蛇节中的第0个div是蛇头 后面其他的都是蛇身
this.bodys = [];
// 蛇的要追加的地图
this.map = m;
// 蛇要吃的食物
this.food = f;
// 生成蛇
this.createBodys();
}
// 生成蛇
Snake.prototype.createBodys = function () {
// 增加三个新蛇头,初始化为3节
for (var i = 0; i < 3; i++) {
this.insertNewHead();
}
};
// 增加蛇头
Snake.prototype.insertNewHead = function () {
// 创建一个div,表示新的蛇头
var newHead = document.createElement('div');
// 设置类名
newHead.className = 'snake-head';
// 计算新蛇头的位置
var location = this.getNewHeadLoaction();
// 把计算好的位置设置给新蛇头元素
newHead.style.left = location.left + 'px';
newHead.style.top = location.top + 'px';
// 把新蛇头放入地图中
this.map.appendChild(newHead);
// 获取旧的蛇头,看是否存在,若存在,把旧的蛇头改为身体
var oldHead = this.bodys[0];
if (oldHead != undefined) {
oldHead.className = 'snake-body';
}
// 把新蛇节放到蛇的bodys中
this.bodys.unshift(newHead);
};
// 计算新蛇头的位置,返回两个数据
Snake.prototype.getNewHeadLoaction = function () {
// 定义两个变量,分别表示计算后新蛇头的位置
var x = 0; y = 0;
// 判断是否有蛇头
var oldHead = this.bodys[0];
// 若没有蛇头,将来返回 {left:0,top:0}
if (oldHead == undefined) {
return { left: x, top: y };
}
// 有蛇头,则计算。 获取原有蛇头的位置
x = oldHead.offsetLeft;
y = oldHead.offsetTop;
// 根据蛇移动的方向计算
switch (this.direction) {
case 'left':
x = x - 20;
break;
case 'right':
x = x + 20;
break;
case 'bottom':
y = y + 20;
break;
case 'top':
y = y - 20;
break;
}
return { left: x, top: y };
};
// 蛇移动方法
Snake.prototype.move = function () {
// 1. 计算并获取新蛇头的位置
var obj = this.getNewHeadLoaction();
// 1.1 判断蛇头的位置是否已经越过边界
if (obj.left < 0 || obj.left == 900 || obj.top < 0 || obj.top == 600) {
alert('想不开死了');
return true; // 这里的返回值,主要高速定时器,蛇是否死了
}
// 2. 从蛇的bodys中取出最后节 pop()
var last = this.bodys.pop();
// 3. 设置最后一节的类名为蛇头 snake-head
last.className = 'snake-head';
// 4. 获取旧的蛇头
var oldHead = this.bodys[0];
// 5. 把旧的蛇头改为身体 snake-body
oldHead.className = 'snake-body';
// 6. 把最后一节追加到数组的最前面
this.bodys.unshift(last);
// 7. 把新蛇头的位置赋值给最后一节的left和top样式
last.style.left = obj.left + 'px';
last.style.top = obj.top + 'px';
// 8 判断蛇有没有吃到食物
if (obj.left == this.food.x && obj.top == this.food.y) {
// console.log('吃了')
// 8.1 蛇要增加一节
this.insertNewHead();
// 8.2 食物要随机一下位置
this.food.randomLoaction();
}
return false;
}
w.Snake = Snake;
}(window));