JavaScript 实现简易版贪吃蛇(Day_13)
时光永远在变迁,你始终要丢下过去。
使用语言
JavaScript
概述
Html 页面
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>贪吃蛇</title>
6 <link rel="stylesheet" href="css/style.css">
7 </head>
8 <body>
9 <div id="map"></div>
10 <h2>使用WSAD 或者 上下左右键 控制方向 </h2>
11 <script src="js/index.js"></script>
12 </body>
13 </html>
CSS 页面
1 #map {
2 width: 800px;
3 height: 600px;
4 background-color: lightgray;
5 position: relative;
6 }
JavaScript 部分
1 // ---------------------Tools--------------------------
2
3
4 ;(function (window, undefined) {
5 var Tools = {
6 getRandom: function (min, max) {
7 return Math.floor(Math.random() * (max - min + 1)) + min;
8 }
9 }
10 // 暴露Tools给window
11 window.Tools = Tools;
12 })(window, undefined)
13
14 // -----------------------Food---------------------------
15 ;(function (window, undefined) {
16 // 局部作用域
17 var position = 'absolute';
18 // 记录上一次创建的食物,为删除做准备
19 var elements = [];
20 function Food(options) {
21 options = options || {};
22 this.x = options.x || 0;
23 this.y = options.y || 0;
24
25 this.width = options.width || 20;
26 this.height = options.height || 20;
27
28 this.color = options.color || 'green';
29 }
30
31 // 渲染
32 Food.prototype.render = function (map) {
33 // 删除之前创建的食物
34 remove();
35
36 // 随机设置x和y的值
37 this.x = Tools.getRandom(0, map.offsetWidth/this.width - 1) * this.width;
38 this.y = Tools.getRandom(0, map.offsetHeight/this.height - 1) * this.height;
39
40 // 动态创建div 页面上显示的食物
41 var div = document.createElement('div');
42 map.appendChild(div);
43
44 elements.push(div);
45
46 // 设置div的样式
47 div.style.position = position;
48 div.style.left = this.x + 'px';
49 div.style.top = this.y + 'px';
50 div.style.width = this.width + 'px';
51 div.style.height = this.height + 'px';
52 div.style.backgroundColor = this.color;
53 }
54
55 function remove() {
56 for (var i = elements.length - 1; i >= 0; i--) {
57 // 删除div
58 elements[i].parentNode.removeChild(elements[i]);
59 // 删除数组中的元素
60 // 删除数组元素
61 // 第一个参数,从哪个元素开始删除
62 // 第二个参数,删除几个元素
63 elements.splice(i, 1);
64 }
65 }
66
67 // 把Food构造函数 让外部可以访问
68 window.Food = Food;
69 })(window, undefined)
70
71 // ---------------------------Snake----------------------
72 ;(function (window, undefined) {
73 var position = 'absolute';
74 // 记录之前创建的蛇
75 var elements = [];
76 function Snake(options) {
77 options = options || {};
78 // 蛇节 的大小
79 this.width = options.width || 20;
80 this.height = options.height || 20;
81 // 蛇移动的方向
82 this.direction = options.direction || 'right';
83 // 蛇的身体(蛇节) 第一个元素是蛇头
84 this.body = [
85 {x: 3, y: 2, color: 'red'},
86 {x: 2, y: 2, color: 'blue'},
87 {x: 1, y: 2, color: 'blue'}
88 ];
89 }
90
91 Snake.prototype.render = function (map) {
92 // 删除之前创建的蛇
93 remove();
94 // 把每一个蛇节渲染到地图上
95 for (var i = 0, len = this.body.length; i < len; i++) {
96 // 蛇节
97 var object = this.body[i];
98 //
99 var div = document.createElement('div');
100 map.appendChild(div);
101
102 // 记录当前蛇
103 elements.push(div);
104
105 // 设置样式
106 div.style.position = position;
107 div.style.width = this.width + 'px';
108 div.style.height = this.height + 'px';
109 div.style.left = object.x * this.width + 'px';
110 div.style.top = object.y * this.height + 'px';
111 div.style.backgroundColor = object.color;
112 }
113 }
114 // 私有的成员
115 function remove() {
116 for (var i = elements.length - 1; i >= 0; i--) {
117 // 删除div
118 elements[i].parentNode.removeChild(elements[i]);
119 // 删除数组中的元素
120 elements.splice(i, 1);
121 }
122 }
123
124 // 控制蛇移动的方法
125 Snake.prototype.move = function (food, map) {
126 // 控制蛇的身体移动(当前蛇节 到 上一个蛇节的位置)
127 for (var i = this.body.length - 1; i > 0; i--) {
128 this.body[i].x = this.body[i - 1].x;
129 this.body[i].y = this.body[i - 1].y;
130 }
131 // 控制蛇头的移动
132 // 判断蛇移动的方向
133 var head = this.body[0];
134 switch(this.direction) {
135 case 'right':
136 head.x += 1;
137 break;
138 case 'left':
139 head.x -= 1;
140 break;
141 case 'top':
142 head.y -= 1;
143 break;
144 case 'bottom':
145 head.y += 1;
146 break;
147 }
148
149 // 2.4 判断蛇头是否和食物的坐标重合
150 var headX = head.x * this.width;
151 var headY = head.y * this.height;
152 if (headX === food.x && headY === food.y) {
153 // 让蛇增加一节
154 // 获取蛇的最后一节
155 var last = this.body[this.body.length - 1];
156 this.body.push({
157 x: last.x,
158 y: last.y,
159 color: last.color
160 })
161
162 // 随机在地图上重新生成食物
163 food.render(map);
164 }
165
166 }
167
168 // 暴露构造函数给外部
169 window.Snake = Snake;
170 })(window, undefined)
171
172 //----------------------Game---------------------------
173 ;(function (window, undefined) {
174 var that; // 记录游戏对象
175 function Game(map) {
176 this.food = new Food();
177 this.snake = new Snake();
178 this.map = map;
179 that = this;
180 }
181
182 Game.prototype.start = function () {
183 // 1 把蛇和食物对象,渲染到地图上
184 this.food.render(this.map);
185 this.snake.render(this.map);
186 // 2 开始游戏的逻辑
187 // 2.1 让蛇移动起来
188 // 2.2 当蛇遇到边界游戏结束
189 runSnake();
190 // 2.3 通过键盘控制蛇移动的方向
191 bindKey();
192 // 2.4 当蛇遇到食物 --- 在snake的move方法中处理
193 }
194
195 // 通过键盘控制蛇移动的方向
196 function bindKey() {
197 // document.onkeydown = function () {};
198 document.addEventListener('keydown', function (e) {
199 // console.log(e.keyCode);
200 // 37 - left
201 // 38 - top
202 // 39 - right
203 // 40 - bottom
204 switch (e.keyCode) {
205 case 37:
206 this.snake.direction = 'left';
207 break;
208 case 38:
209 this.snake.direction = 'top';
210 break;
211 case 39:
212 this.snake.direction = 'right';
213 break;
214 case 40:
215 this.snake.direction = 'bottom';
216 break;
217
218 // 65 - left
219 // 87 - top
220 // 68 - right
221 // 83 - bottom
222
223 case 65:
224 this.snake.direction = 'left';
225 break;
226 case 87:
227 this.snake.direction = 'top';
228 break;
229 case 68:
230 this.snake.direction = 'right';
231 break;
232 case 83:
233 this.snake.direction = 'bottom';
234 break;
235 }
236 }.bind(that), false);
237 }
238
239 // 私有的函数 让蛇移动
240 function runSnake() {
241 var timerId = setInterval(function () {
242 // 让蛇走一格
243 // 在定时器的function中this是指向window对象的
244 // this.snake
245 // 要获取游戏对象中的蛇属性
246 this.snake.move(this.food, this.map);
247 this.snake.render(this.map);
248
249 // 2.2 当蛇遇到边界游戏结束
250 // 获取蛇头的坐标
251 var maxX = this.map.offsetWidth / this.snake.width;
252 var maxY = this.map.offsetHeight / this.snake.height;
253 var headX = this.snake.body[0].x;
254 var headY = this.snake.body[0].y;
255 if (headX < 0 || headX >= maxX) {
256 alert('Game Over');
257 clearInterval(timerId);
258 }
259
260 if (headY < 0 || headY >= maxY) {
261 alert('Game Over');
262 clearInterval(timerId);
263 }
264 }.bind(that), 150);
265 }
266
267 // 暴露构造函数给外部
268 window.Game = Game;
269 })(window, undefined)
270
271 // -------------------调用------------------
272 ;(function (window, undefined) {
273 var map = document.getElementById('map');
274 var game = new Game(map);
275 game.start();
276 })(window, undefined)
运行效果截图
其他补充
这是一个简单的贪吃蛇,很多功能没有实现,喜欢的小伙伴可以继续往下做。
任何时候不要吝啬您的赞美,喜欢就点赞拉~,
PS:
如果,您希望更容易地发现我的新博客,不妨点击一下关注。
如果你觉得本篇文章对你有所帮助,请给予我更多的鼓励,
因为,我的写作热情也离不开您的肯定支持,感谢您的阅读,我是【肥肥也】!
JavaScript 实现简易版贪吃蛇(Day_13)的更多相关文章
- Javascript基础示例:用JS写简易版贪吃蛇(面向对象)
废话不多说,代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...
- OC版贪吃蛇
昨天写了一个js版贪吃蛇,今天突然想写一个OC版的,来对比一下两种语言的区别 oc版功能,适配所有尺寸iphone,可暂停,可设置地图和蛇的比例,可加速 对比一下会发现js版的相对OC版的会简单一些, ...
- TOJ 3973 Maze Again && TOJ 3128 简单版贪吃蛇
TOJ3973传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=3973 时间限制(普通 ...
- JavaScript原生实现《贪吃蛇》
概述 JavaScript原生实现<贪吃蛇>,每吃掉一个食物,蛇的身体会变长,食物会重新换位置. 详细 代码下载:http://www.demodashi.com/demo/10728.h ...
- 如何用python制作贪吃蛇以及AI版贪吃蛇
用python制作普通贪吃蛇 哈喽,大家不知道是上午好还是中午好还是下午好还是晚上好! 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...
- JavaScript版—贪吃蛇小组件
最近在学习JavaScript,利用2周的时间看完了<JavaScript高级编程>,了解了Js是一门面向原型编程的语言,没有像C#语言中的class,也没有私有.公有.保护等访问限制的级 ...
- js版贪吃蛇
之前没有写博客的习惯,这是我的第一个博客,有些的不好的地方,希望大家多多提意见 js版的贪吃蛇相对比较简单,废话不多说直接上代码,有需要注意的地方我会标红,github源码地址https://gith ...
- JavaScript实践-简单的贪吃蛇小游戏
实现逻辑: //获取Html中的格子(行,列) //建立数组存储所有格子(x,y) //建立数组用于存储蛇身(x,y) //生成随机坐标(x,y)的函数 //随机创建蛇身并存储到蛇身数组 //创建食物 ...
- Winfrom 极简版贪吃蛇源码
该源码是我在百度知识库借助前辈的的经验,加上自己的一点小改动写的一个非常简陋的贪吃蛇小程序.如果你们有更好的改动方案,欢迎评论. 进入主题吧! 1.创建一个桌面应运程序,拖一个定时器控件.这样,程序界 ...
随机推荐
- Spring Boot demo系列(五):Docker部署
2021.2.24 更新 1 概述 本文讲述了如何使用Docker部署Spring Boot应用,首先介绍了Docker的安装过程,接着介绍了Docker的一些基础知识,最后讲述了Dockerfile ...
- JMeter循环读取CSV文件实现接口批量测试
首先要理解为什么要进行批量测试,当我们在工作中进行接口测试时,项目的接口肯定不止一个,而是很多很多,而且每个接口都需要进行正确参数,错误参数,参数为空,特殊字符等方式来测试接口是否能够正确返回所需的响 ...
- 1067 Sort with Swap(0, i)
Given any permutation of the numbers {0, 1, 2,..., N−1}, it is easy to sort them in increasing order ...
- 官宣 MAUI 在.NET Preview 3的最新进展
我们在.NET 6 Preview 3中交付了.NET多平台应用UI的移动和桌面开发的最新进展.此版本添加了Windows平台和WinUI 3,改进了基本应用程序和启动构建器,添加了原生生命周期事件, ...
- html书签展示(带搜索)
源代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title ...
- pycharm2019
812LFWMRSH-eyJsaWNlbnNlSWQiOiI4MTJMRldNUlNIIiwibGljZW5zZWVOYW1lIjoi5q2j54mIIOaOiOadgyIsImFzc2lnbmVlT ...
- Mybatis-Plus01 快速开始
Mybatis-Plus虽然官网上有一个快速开始,但是实际操作有点问题,所以,自己写了一个. 版本说明 如果用其他软件版本可能会有部分差异 mybatis-plus:3.4.0 之前我是使用的是3.0 ...
- Asp.NetCore Web开发之路由
接着讲asp.net core web开发,这节讲路由系统(Route). 在asp.net core中通过路由来将请求映射到对应的action,主要用到两个中间件,UseRouting()和UseE ...
- QFNU 10-30 training
7-9 特立独行的幸福 题意:见PTA 思路:其实就是遍历进行查找,利用递归函数,为了解决是特立独行,还要用一个全局数组进行存储所有满足条件的数进行去重标记,最后在输出的时候进行判断是否是只读取过一次 ...
- matlab添加当前路径下的所有子目录
% 添加当前路径下的所有子目录addpath(genpath(pwd));