html代码:
1 <div class="content">
2 <div class="btn startBtn"> <!-- 开始按钮 -->
3 <button type="button"></button>
4 </div>
5 <div class="btn stopBtn"> <!-- 暂停按钮 -->
6 <button type="button"></button>
7 </div>
8 <div id="snakeWrap"></div> <!-- 主题内容 -->
9 </div>
css代码:
1 * {
2 margin: 0;
3 padding: 0;
4 }
5 body {
6 background-color: #565F65;
7 width: 100%;
8 height: 10vh;
9 overflow: hidden;
10 }
11
12 .content {
13 width: 500px;
14 height: 500px;
15 position: absolute;
16 top: 50%;
17 left: 50%;
18 margin-top: -250px;
19 margin-left: -250px;
20 background-color: #565F65;
21 border: 10px solid #E7E7E7;
22 box-shadow: inset 0px 0px 5px 2px #000;
23 }
24 .btn {
25 width: 100%;
26 height: 100%;
27 position: absolute;
28 top: 0;
29 left: 0;
30 background-color: rgba(0, 0, 0, .3); /*游戏未开始时和暂停时的遮罩*/
31 z-index: 2;
32 }
33 .btn button {
34 background: none;
35 border: none;
36 background-size: 100% 100%;
37 cursor: pointer;
38 outline: none;
39 position: absolute;
40 left: 50%;
41 top: 50%;
42 }
43 .startBtn button{
44 width: 170px;
45 height: 80px;
46 background-image: url(img/startbtn.png);
47 margin-top: -40px;
48 margin-left: -85px;
49 }
50 .stopBtn {
51 display: none;
52 }
53 .stopBtn button{
54 width: 70px;
55 height: 70px;
56 background-image: url(img/stopbtn.png);
57 margin-top: -35px;
58 margin-left: -35px;
59 }
60
61 #snakeWrap {
62 width: 500px;
63 height: 500px;
64 position: relative;
65 }
66 .snakeHead { /*蛇头样式*/
67 background-color: aqua;
68 border-radius: 50%;
69 }
70 .snakeBody { /*蛇身样式*/
71 background-color: navajowhite;
72 border-radius: 50%;
73 }
74 .food { /*食物样式*/
75 background-image: url(img/food.png);
76 background-size: cover;
77 }
javascript 代码:
1 var sw = 20, //一个方块的宽
2 sh = 20, //一个方块的高
3 tr = 25, //行数
4 td = 25; //列数
5 var snake = null, //蛇的实例
6 food = null, //食物的实例
7 game = null; //游戏的实例
8 function Square(x, y, classname) {
9 this.x = x * sw; //方块实际的位置
10 this.y = y * sh; //方块实际的位置
11 this.class = classname;
12
13 this.viewContent = document.createElement('div'); //方块对应的DOM元素
14 this.viewContent.className = this.class;
15 this.parent = document.getElementById('snakeWrap'); //方块的父级
16 }
17
18 Square.prototype.create = function() { //创建方块 DOM,并添加到页面里
19 this.viewContent.style.position = 'absolute';
20 this.viewContent.style.width = sw + 'px';
21 this.viewContent.style.height = sh + 'px';
22 this.viewContent.style.left = this.x + 'px';
23 this.viewContent.style.top = this.y + 'px';
24
25 this.parent.appendChild(this.viewContent);
26 };
27
28 Square.prototype.remove = function() {
29 this.parent.removeChild(this.viewContent);
30 }
31
32 //蛇
33 function Snake() {
34 this.head = null; //存一下蛇头的信息
35 this.tail = null; //存一下蛇尾的信息
36 this.pos = []; //存储蛇身上的每一个方块的位置,二维数组
37
38 this.directionNum = { //存储蛇走的方向,用一个对象来表示
39 left : {
40 x : -1,
41 y : 0,
42 rotate : 180
43 },
44 right : {
45 x : 1,
46 y : 0,
47 rotate : 0
48 },
49 up : {
50 x : 0,
51 y : -1,
52 rotate : -90
53 },
54 down : {
55 x : 0,
56 y : 1,
57 rotate : 90
58 }
59 }
60 }
61
62 Snake.prototype.init = function() {
63 //创建蛇头
64 var snakeHead = new Square(2, 0, 'snakeHead');
65 snakeHead.create();
66 this.head = snakeHead; // 存储蛇头信息
67 this.pos.push([2, 0]); //把蛇头的位置存起来
68
69 //创建蛇身体
70 var snakeBody1 = new Square(1, 0, 'snakeBody');
71 snakeBody1.create();
72 this.pos.push([1, 0]); //把蛇身1的位置存起来
73
74 var snakeBody2 = new Square(0, 0, 'snakeBody');
75 snakeBody2.create();
76 this.tail = snakeBody2; //把蛇尾的信息存起来
77 this.pos.push([0, 0]); //把蛇身1的位置存起来
78
79 //让蛇头蛇身形成链表关系
80 snakeHead.last = null;
81 snakeHead.next = snakeBody1;
82
83 snakeBody1.last = snakeHead;
84 snakeBody1.next = snakeBody2;
85
86 snakeBody2.last = snakeBody1;
87 snakeBody2.next = null;
88
89 //给蛇添加一条属性,用来表示蛇走的方向
90 this.direction = this.directionNum.right; //默认让蛇往右走
91
92 }
93
94 //这个方法用来获取蛇头的下一个位置对应的元素, 要根据元素做不同的事情
95 Snake.prototype.getNextPos = function() {
96 var nextPos = [ //蛇头要走的下一个点的坐标
97 this.head.x/sw + this.direction.x,
98 this.head.y/sh + this.direction.y
99 ];
100
101 //下一个点是自己,代表撞到了自己,游戏结束
102 var selfCollind = false; //是否撞到自己
103 this.pos.forEach(function(value) {
104 if(value[0] == nextPos[0] && value[1] == nextPos[1]) {
105 //如果数组中的两个数据都相等,就说明下一个点在蛇身上里面能找到,代表撞到自己了
106 selfCollind = true;
107 }
108 });
109 if(selfCollind) {
110 console.log('撞到自己了!');
111
112 this.strategies.die.call(this);
113
114 return;
115 }
116
117 //下一个点是墙,游戏结束
118 if(nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] > td - 1 || nextPos[1] > tr - 1) {
119 console.log('撞墙了!');
120
121 this.strategies.die.call(this);
122
123 return;
124 }
125 //下一个点是食物,吃
126 if(food && food.pos[0] == nextPos[0] && food.pos[1] == nextPos[1]) {
127 //如果这个条件成立说明现在蛇头要走的下一个点是食物的那个点
128 console.log('撞到食物了了!');
129 this.strategies.eat.call(this);
130 return;
131 }
132 //下一个点什么都不是,走
133 this.strategies.move.call(this);
134 };
135
136 //处理碰撞后要做的事
137 Snake.prototype.strategies = {
138 move : function(format) { //这个参数用于决定要不要删除最后一个方块(蛇尾), 当传了这个参数后就表示要做的事情是吃
139 //创建新身体(在蛇头位置)
140 var newBody = new Square(this.head.x/sw, this.head.y/sh, 'snakeBody');
141 //更新链表关系
142 newBody.next = this.head.next;
143 newBody.next.last = newBody;
144 newBody.last = null;
145
146
147 this.head.remove(); //旧舌头从原来的位置删除
148 newBody.create();
149
150 //创建一个新蛇头(蛇头下一个要走到的点)
151 var newHead = new Square(this.head.x/sw + this.direction.x, this.head.y/sh + this.direction.y, 'snakeHead')
152 //更新链表关系
153 newHead.next = newBody;
154 newHead.last = null;
155 newBody.last = newHead;
156 newHead.viewContent.style.transform = 'rotate('+this.direction.rotate+'deg)';
157 newHead.create();
158
159
160 //蛇身上每一个方块的坐标也要更新
161 this.pos.splice(0,0, [this.head.x/sw + this.direction.x, this.head.y/sh + this.direction.y]);
162 this.head = newHead; //还要把this.head的信息更新一下
163
164 if(!format) { //如何format 的值为 false, 表示需要删除(除了吃之外的操作)
165 this.tail.remove();
166 this.tail = this.tail.last;
167
168 this.pos.pop();
169 }
170
171 },
172 eat : function() {
173 this.strategies.move.call(this, true);
174 createFood();
175 game.score ++;
176 },
177 die : function() {
178 game.over();
179 }
180 }
181
182 snake = new Snake();
183
184 //创建食物
185 function createFood() {
186 //食物小方块的随机坐标
187 var x = null;
188 var y = null;
189
190 var include = true; //循环跳出的条件, true表示食物的坐标在蛇身上(需要继续循环),false表示食物坐标不在蛇身上(不循环了)
191 while(include) {
192 x = Math.round(Math.random() * (td - 1)); //0-29
193 y = Math.round(Math.random() * (tr - 1));
194
195 snake.pos.forEach(function(value) {
196 if(x != value[0] && y != value[1]) {
197 //这个条件成立说明现在随机出来的这个坐标,在蛇身上并没有找到
198 include = false;
199 }
200 });
201
202 }
203 //生成食物
204 food = new Square(x, y, 'food');
205 food.pos = [x,y]; //存储一下生成食物的坐标,用于跟蛇头要走的下一个点作对比
206 var foodDom = document.querySelector('.food');
207 if(foodDom) {
208 foodDom.style.left = x*sw + 'px';
209 foodDom.style.top = y*sh + 'px';
210 }else {
211 food.create();
212 }
213 }
214
215
216
217 //创建游戏逻辑
218 function Game() {
219 this.timer = null;
220 this.score = 0;
221 this.speed = 200;
222 }
223 Game.prototype.init = function() {
224 snake.init();
225 snake.getNextPos();
226 createFood();
227
228 document.onkeydown = function(ev) { //用户按下方向键触发事件
229 if(ev.which == 37 && snake.direction != snake.directionNum.right) {
230 //用户按下左键是,蛇不能是往右走
231 snake.direction = snake.directionNum.left;
232 }else if(ev.which == 38 && snake.direction != snake.directionNum.dowm) {
233 snake.direction = snake.directionNum.up;
234 }else if(ev.which == 39 && snake.direction != snake.directionNum.left) {
235 snake.direction = snake.directionNum.right;
236 }else if(ev.which == 40 && snake.direction != snake.directionNum.up) {
237 snake.direction = snake.directionNum.down;
238 }
239 }
240
241 this.start();
242 }
243
244 Game.prototype.start = function() { //开始游戏
245 this.timer = setInterval(function() {
246 snake.getNextPos();
247
248 }, this.speed);
249 }
250 Game.prototype.pause = function() {
251 clearInterval(this.timer);
252 }
253 Game.prototype.over = function() { //开始游戏
254 clearInterval(this.timer);
255 alert('你的得分为' + this.score);
256
257 //游戏回到最初的状态
258 var snakeWrap = document.getElementById('snakeWrap');
259 snakeWrap.innerHTML = '';
260 snake = new Snake();
261 game = new Game();
262 var startBtnWrap = document.querySelector('.startBtn');
263 startBtnWrap.style.display = 'block';
264 }
265 //开启游戏
266 game = new Game();
267 var startBtn = document.querySelector('.startBtn button');
268 startBtn.onclick = function() {
269 startBtn.parentNode.style.display = 'none';
270 game.init();
271 };
272
273
274 //暂停
275 var snakeWrap = document.getElementById('snakeWrap');
276 var puseBtn = document.querySelector('.stopBtn button')
277 snakeWrap.onclick = function() {
278 game.pause();
279 puseBtn.parentNode.style.display = 'block';
280 }
281
282 puseBtn.onclick =function() {
283 game.start();
284 puseBtn.parentNode.style.display = 'none';
285 }