贪吃蛇案例

案例分析重点

模拟贪吃蛇游戏,做的项目
地图: 宽,高,背景颜色,因为小蛇和食物都是相对于地图显示的,这里小蛇和食物都是地图的子元素,随机位置显示,脱离文档流的,地图也需要脱离文档流–css需要设置:宽,高,背景颜色,脱标

食物—div元素
elements—>存储div的数组(将来删除的食物div时候,先从map中删除div,再从数组中移除div)
食物:宽,高,背景颜色,横坐标,纵坐标
一个食物就是一个对象,这个对象有相应的属性,这个对象需要在地图上显示
最终要创建食物的对象,先 有构造函数,并且把相应的值作为参数传入到构造函数中
食物要想显示在地图上,食物的初始化就是一个行为
1.食物的构造函数—>创建食物对象
2.食物的显示的方法–>通过对象调用方法,显示食物,设置相应的样式
2.1.1 因为食物要被小蛇吃掉,吃掉后应该再次出现食物,原来的食物就删除了
2.1.2 每一次初始化食物的时候先删除原来的食物,然后重新的初始化食物
2.1.3 通过一个私有的函数(外面不能调用的函数)删除地图上的食物,同时最开始的时候食物也相应的保存到一个数组中,再从这个数组中把食物删除
最后的时候,把食物的构造函数给window下的属性,这样做,外部就可以直接使用这个食物的构造函数了

小蛇
小蛇就是一个对象
属性: 每个身体都有宽,高,方向
属性:身体分三个部分,每个部分都是一个对象,每个部分都有横纵坐标,背景颜色
小蛇要想显示在地图上,先删除之前的小蛇,然后再初始化小蛇(小蛇要移动)–方法

小蛇要移动—方法
思路:把小蛇的头的坐标给小蛇第一部分的身体,第一部分的身体的坐标给下一个部分身体
小蛇的头,需要单独的设置:方向

案例效果



案例代码

Css

1
2
3
4
5
6
7
8
9
10
11
12
13
* {
padding: 0;
margin: 0;
}

.wrap {
width: 800px;
height: 600px;
background-color: #ccc;
position: relative;
top: 20px;
left: 20px;
}

Html

1
2
3
4
<!-- 贪吃蛇地图 -->
<div class="wrap">

</div>

Js (Js代码均为外部引入代码)

引入代码一 food.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
* @Author: yhf
* @Date: 2018-09-10 00:04:58
* @Last Modified by: yhf
* @Last Modified time: 2018-09-10 10:23:05
*/
// 食物就是一个对象,有宽高颜色,横纵坐标
// 食物自调用
(function () {
var elements = [];
// 先有食物的对象
function Food(x, y, width, height, color) {
this.x = x;
this.y = y;
this.width = width || 20;
this.height = height || 20;
this.color = color || "green";
};

// 私有函数--删除食物
function remove() {
for (let i = 0; i < elements.length; i++) {
const ele = elements[i];
// 找到这个子元素的父级元素,删除
ele.parentNode.removeChild(ele);
// 再次吧elements中的元素也要删除
elements.splice(i, 1);
}
}

// 在原始添加初始化方法(作用:再页面上显示)
// 因为食物要在地图上显示,所以需要在地图的这个参数(wrap--就是页面上的.class = wrap 的这个div)
Food.prototype.init = function (wrap) {
// 先删除这个食物
// 外部无法访问
remove();

// 创建div
var div = document.createElement("div");
// 把div添加到wrap上
wrap.appendChild(div);
// 设置div的样式
div.style.width = this.width + "px";
div.style.height = this.height + "px";
div.style.backgroundColor = this.color;
// 脱离文档流
div.style.position = "absolute";
// 随机横纵坐标
this.x = parseInt(Math.random() * (wrap.offsetWidth / this.width)) * this.width;
this.y = parseInt(Math.random() * (wrap.offsetHeight / this.height)) * this.height;
div.style.left = this.x + "px";
div.style.top = this.y + "px";
// 把div加入到数组中
elements.push(div);
};
// Food暴露给力windwo,外部可以使用
window.Food = Food;
}());

引入代码二 Snake.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* @Author: yhf
* @Date: 2018-09-10 00:08:15
* @Last Modified by: yhf
* @Last Modified time: 2018-09-10 00:11:02
*/
// 小蛇的自调函数
(function () {
// 存放蛇
var elements = [];
// 小蛇的构造函数
function Snake(width, height, direction) {
// 蛇的每个部分的宽
this.width = width || 20;
this.height = height || 20;

// 蛇的身体
this.body = [{
x: 3,
y: 2,
color: "red"
}, // 头
{
x: 2,
y: 2,
color: "orange"
}, // 身体
{
x: 1,
y: 2,
color: "orange"
} // 身体
];
// 方向
this.direction = direction || "right";
};
// 添加小蛇初始化方法
Snake.prototype.init = function (wrap) {
// 清理蛇
remove();
// 创建div
for (let i = 0; i < this.body.length; i++) {
const obj = this.body[i]
// 创建div
var div = document.createElement("div");
// 吧div加入到wrap
wrap.appendChild(div);
// 设置div样式
div.style.position = "absolute";
div.style.width = this.width + "px";
div.style.height = this.height + "px";
// 横纵坐标
div.style.left = obj.x * this.width + "px";
div.style.top = obj.y * this.height + "px";
// 背景颜色
div.style.backgroundColor = obj.color;
// 把div加入到数组
elements.push(div);
}
};

// 小蛇动方法
Snake.prototype.move = function (food, wrap) {
// 改变小蛇身体坐标位置
var i = this.body.length - 1;
for (; i > 0; i--) {
this.body[i].x = this.body[i - 1].x;
this.body[i].y = this.body[i - 1].y;
}
// 判断方向--改变小蛇头位置
switch (this.direction) {
case "right":
this.body[0].x += 1;
break;
case "left":
this.body[0].x -= 1;
break;
case "top":
this.body[0].y -= 1;
break;
case "bottom":
this.body[0].y += 1;
break;
}
// 判断有没有吃到食物
// 蛇和食物的坐标一致
var headX = this.body[0].x * this.width;
var headY = this.body[0].y * this.height;

// 判断蛇的头的坐标和食物的坐标是否相同
if (headX == food.x && headY == food.y) {
// 获取蛇的尾巴
var last = this.body[this.body.length - 1];
// 复制多一个
this.body.push({
x: last.x,
y: last.y,
color: last.color
});
// 把食物删除
food.init(wrap);
}
};

// 删除小蛇都函数
function remove() {
// 获取数组
var i = elements.length - 1;
for (; i >= 0; i--) {
// 从当前元素找到父级元素删除
const ele = elements[i];
// 从wrap删除
ele.parentNode.removeChild(ele);
elements.splice(i, 1);
}
}

// 把Snake暴露给window
window.Snake = Snake;
}());

引入代码三 Game.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
* @Author: yhf
* @Date: 2018-09-10 00:08:23
* @Last Modified by: yhf
* @Last Modified time: 2018-09-10 00:08:23
*/
// 自调用封装游戏对象
(function () {
var that = null;
// 游戏构造函数
function Game() {
this.food = new Food(); // 食物对象
this.snake = new Snake(); // 蛇对象
this.wrap = wrap; // 地图
that = this;
};
Game.prototype.init = function () {
// 初始化游戏
// 食物初始化
this.food.init(this.wrap);
// 小蛇初始化
this.snake.init(this.wrap);
// 调用自动移动蛇方法
this.runSnake(this.food, this.wrap);
// 调用按键方法
this.bindKey();
};
// 添加原型,设小蛇跑起来
Game.prototype.runSnake = function (food, wrap) {
// 自动移动
var time = setInterval(function () {
// 此时this是window
// 移动蛇
this.snake.move(food, wrap);
// 初始化蛇
this.snake.init(wrap);
// 横坐标的最大值
var maxX = wrap.offsetWidth / this.snake.width;
var maxY = wrap.offsetHeight / this.snake.height;
// 小蛇头坐标
var headX = this.snake.body[0].x;
var headY = this.snake.body[0].y;
// 横坐标
if (headX < 0 || headX >= maxX) {
// 撞墙,停止定时器
clearInterval(time);
alert("游戏结束");
}
// 纵坐标
if (headY < 0 || headY >= maxY) {
// 撞墙,停止定时器
clearInterval(time);
alert("游戏结束");
}
}.bind(that), 150)
};

// 添加原型方法--设置用户按键
Game.prototype.bindKey = function () {
// 获取用户按键
document.addEventListener("keydown", function (e) {
// 此时this应该是keydown的事件对象
// 所以this就是document
// 获取按键值
switch (e.keyCode) {
case 37:
this.snake.direction = "left";
break;
case 38:
this.snake.direction = "top";
break;
case 39:
this.snake.direction = "right";
break;
case 40:
this.snake.direction = "bottom";
break;
}
}.bind(that), false);
};

window.Game = Game;
}());

内部调用代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 方法一
// 获取地图
const wrap = document.querySelector(".wrap");
// 初始化游戏对象
var gm = new Game(wrap);
// 开始游戏
gm.init();


// 方法二
// 初始化游戏对象
var gm = new Game(document.querySelector(".wrap"));
// 开始游戏
gm.init();
-------------本文结束感谢您的阅读-------------
0%