一个原生JS实现的不太成熟的贪吃蛇游戏

一个初初初初级前端民工

主要是记录一下写过的东西,复习用

大佬们如果看到代码哪里不符合规范,或者有更好写法的,欢迎各位批评指正

十分感谢

 

 

实现一个贪吃蛇游戏需要几步?

1.有地图

2.有蛇

3.有食物

4.有游戏规则

----->面向对象的思想:

完整代码:

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="utf-8">
  5         <title></title>
  6         <style>
  7             #map{
  8                 width: 800px;
  9                 height: 600px;
 10                 background-color: #e6e6e6;
 11                 position: relative;
 12             }
 13             #talk{
 14                 color: red;
 15                 position: absolute;
 16                 right: -20px;
 17                 top: 20px;
 18             }
 19             #scoreList{
 20                 border: 1px solid cadetblue;
 21                 border-left: none;
 22                 box-shadow: 1px 1px 1px #A9A9A9;
 23                 width: 200px;
 24                 height: 400px;
 25                 overflow-y: auto;
 26                 position: absolute;
 27                 right: -200px;
 28             }
 29             #scoreList h3{
 30                 text-align: center;
 31             }
 32             .name,.score{
 33                 display: inline-block;
 34                 width: 45%;
 35                 text-align: center;
 36             }
 37             #start{
 38                 position: absolute;
 39                 right: -200px;
 40                 bottom: 20px;
 41                 background-color: cornflowerblue;
 42                 color: white;
 43                 box-shadow: 2px 2px 3px #d6d6d6;
 44                 padding: 5px;
 45                 cursor: pointer;
 46             }
 47         </style>
 48     </head>
 49     <body>
 50         <div id="map">
 51             <div id="scoreList">
 52                 <h3>排行榜</h3>
 53                 <hr />
 54                 <div id="container"></div>
 55             </div>
 56             <div id="start" onclick="start()">开始游戏</div>
 57         </div>
 58         <script>
 59             var name = '';
 60             var scoreList = [];
 61             var result = {};
 62             function my$(id){
 63                 return document.getElementById(id);
 64             }
 65             if(document.cookie){
 66                 // listShow();
 67             }
 68             function listShow(){
 69                 var scoreStr='';
 70                 console.log(document.cookie);
 71                 var cookies = document.cookie.split(',');
 72                 for(var i = 0;i<cookies.length;i++){
 73                     var item = JSON.parse(cookies[i]);
 74                     scoreStr += '<span class="name">'+item.userName+'</span><span class="score">'+item.userScore+'</span>';
 75                 }                    
 76                     my$('container').innerHTML = scoreStr;
 77             }
 78             //食物
 79             (function(){
 80                 var elements = [];
 81                 //用来存储食物【实例对象】的数组,在被蛇'吃掉'之后,可以通过数组来找到这个对象,进而实现在html中删除相应结点。
 82                 
 83                 //食物的构造函数 
 84                 function Food(x,y,width,height,color){
 85                     this.x = x||0; //没有传入值时横坐标默认为0
 86                     this.y = y||0;
 87                     this.width = width||20;
 88                     this.height = height||20;
 89                     this.color = color||'#a0c9fb';
 90                 }
 91                 //初始化,将设置好的属性值转化为样式
 92                 Food.prototype.init = function(map){
 93                     remove(); //将之前的所有食物删除
 94                     var div = document.createElement('div');  //创建一个div元素
 95                     div.style.position = 'absolute';
 96                     div.style.width = this.width + 'px';
 97                     div.style.height = this.height + 'px';
 98                     div.style.backgroundColor = this.color;
 99                     this.x = parseInt(Math.random()*(map.offsetWidth/this.width))*this.width;
100                     this.y = parseInt(Math.random()*(map.offsetHeight/this.height))*this.height;
101                     div.style.left = this.x + 'px';
102                     div.style.top = this.y + 'px';
103                     map.appendChild(div); //将div添加到地图中
104                     elements.push(div); //将div对象追加到数组当中
105                 }
106                 //删除食物
107                 function remove(){
108                     for(var i=0;i<elements.length;i++){
109                         var ele = elements[i]; 
110                         ele.parentNode.removeChild(ele);
111                         elements.splice(i,1);
112                     }
113                 }
114                 window.Food = Food; //Food构造函数是在自调用函数中写的(目的是避免变量重名的问题),这里用Food构造函数来创建window对象的Food方法,使其可以在自调用函数之外被调用
115             }());
116             //
117             (function(){
118                 var elements = [];
119                 function Snake(width,height,direction){
120                     this.width = width||20;
121                     this.height = height||20;
122                     this.direction = direction||'right';
123                     this.currentDir = this.direction;
124                     this.score = 0;
125                     this.body = [
126                         {x:3,y:2,color:'red'},
127                         {x:2,y:2,color:'orange'},
128                         {x:1,y:2,color:'orange'}
129                     ]    //蛇的每一块身体是一个div,通过它们坐标的改变来实现蛇的移动.
130                 }
131                 //初始化,
132                 Snake.prototype.init = function(map){
133                     remove();
134                     for(var i=0;i<this.body.length;i++){  //body的每一块都有相应的坐标,颜色,宽高等,要通过循坏为每一块进行初始化
135                         var obj = this.body[i];
136                         var div = document.createElement('div');
137                         map.appendChild(div);
138                         div.style.position = 'absolute';
139                         div.style.width = this.width + 'px';
140                         div.style.height = this.height + 'px';
141                         div.style.backgroundColor = obj.color;
142                         div.style.left = obj.x*this.width + 'px';
143                         div.style.top = obj.y*this.height + 'px';
144                         elements.push(div);
145                     }
146                 }
147                 //让蛇动起来(改变body每一块的坐标 每次调用整体动一下)
148                 Snake.prototype.move = function(food,map){ //food参数在用来判断蛇是否吃掉食物时使用,map参数在对food进行初始化时使用
149                     var i = this.body.length-1;  //判断蛇的body中 最后一块的下标
150                     for(;i>0;i--){  //Step1: 从最后一块开始到第二块的坐标值改变
151                         this.body[i].x = this.body[i-1].x;
152                         this.body[i].y = this.body[i-1].y;
153                     }
154                     switch(this.direction){ //Step2: 根据之前设定的方向来判断蛇头(第一块)的坐标变化
155                         case 'right':this.body[0].x+=1;break;
156                         case 'left':this.body[0].x-=1;break;
157                         case 'top':this.body[0].y-=1;break;
158                         case 'bottom':this.body[0].y+=1;break;
159                     }
160                     
161                     //判断是否吃到  蛇头的坐标 == 食物的坐标 即为吃到
162                     var headX = this.body[0].x*this.width;
163                     var headY = this.body[0].y*this.height;
164                     if(headX == food.x && headY == food.y){
165                         var last = this.body[this.body.length-1]; 
166                         this.body.push({
167                             x:last.x,
168                             y:last.y,
169                             color:last.color
170                         }); //在body最后增加一个对象,坐标等于最后一块的坐标即可
171                         this.score = this.score+1; 
172                         food.init(map); //重新初始化一个食物出来
173                     }
174                 }
175                 function remove(){
176                     var i = elements.length-1;
177                     for(;i>=0;i--){
178                         elements[i].parentNode.removeChild(elements[i]);
179                         elements.splice(i,1);
180                     }
181                 }
182                 window.Snake = Snake;
183             }());
184             //游戏
185             (function(){
186                 var that; //setInterval中的this是window,所以先定义一个that,将我们要使用的this对象存在that中,这样就可以在setInterval中使用了
187                 function Game(map){
188                     that = this; //this是新的实例对象 
189                     this.food = new Food(); //创建food实例对象
190                     this.snake = new Snake(); //创建snake实例对象
191                     this.map = map; //将这些都作为game实例对象的属性
192                 }
193                 Game.prototype.init = function(){
194                     this.food.init(this.map);
195                     this.snake.init(this.map);
196                     this.run();
197                     this.bindKey();
198                 }
199                 
200                 // 之前的snake.move是让蛇动一下,在这里放在setInterval中让它一直移动.
201                 Game.prototype.run = function(){
202                     var timeId = setInterval(function(){  //timeId用于clearInterval
203                         this.snake.move(this.food,this.map); //1.蛇的坐标改变
204                         this.snake.init(this.map);  //2.画出蛇
205                         var xMax = this.map.offsetWidth/this.snake.width;  //横坐标最大值
206                         var yMax = this.map.offsetHeight/this.snake.height;//纵坐标最大值
207                         var headX = this.snake.body[0].x;  
208                         var headY = this.snake.body[0].y;
209                         if(headX>=xMax||headX<0||headY>=yMax||headY<0){ //判断是否撞墙
210                             this.scoreFunction(timeId);
211                             //尝试变色
212                             // var i=0;
213                             // setInterval(function(){
214                             //     this.snake.body[i].color = 'red';
215                             //     this.snake.init();
216                             //     i++;
217                             // }.bind(that),500) 
218                             //本来想写一个 蛇撞墙之后身体都变成红色的效果 emmm失败了  
219                         }
220                         for(var i=1;i<this.snake.body.length;i++){  //判断是否撞自己
221                             if(headX==this.snake.body[i].x&&headY==this.snake.body[i].y){
222                                 this.scoreFunction(timeId);
223                             }
224                         }
225                     }.bind(that),150); //bind的作用是将bind后面括号中的值作为函数中this的值
226                 }
227                 //分数结算函数 
228                 Game.prototype.scoreFunction = function(timeId){
229                     alert('啊啊啊wsl!!!!');
230                     name = prompt('请问高手尊姓大名?');
231                     result.userName = name;
232                     result.userScore = this.snake.score;
233                     scoreList.push(JSON.stringify(result));
234                     scoreList.sort(function(a,b){
235                         var a = JSON.parse(a);
236                         var b = JSON.parse(b);
237                         return b.userScore - a.userScore;
238                     }) //排行榜排序功能
239                     var cookieStr = JSON.stringify(scoreList);
240                     cookieStr = cookieStr.replace(',',';');
241                     document.cookie = 'list = '+cookieStr; //尝试写在cookie中并没有成功 嘤
242                     //将分数写入scoreList盒子
243                     var scoreStr='';
244                     for(var i in scoreList){
245                         var item = JSON.parse(scoreList[i]);
246                         scoreStr += '<span class="name">'+item.userName+'</span><span class="score">'+item.userScore+'</span>';
247                 }
248                     my$('container').innerHTML = scoreStr;
249                     clearInterval(timeId);  //清除定时器  蛇停止移动
250                 }
251                 
252                 //按下键盘相应键,给蛇的direction赋值,需要注意的是蛇不可以掉头
253                 Game.prototype.bindKey = function(){
254                     document.addEventListener('keydown',function(e){
255                         switch(e.keyCode){
256                             case 37:
257                                 if(this.snake.currentDir!='right'){
258                                     this.snake.direction='left';
259                                     this.snake.currentDir='left';
260                                 }
261                                 break;
262                             case 38:
263                                 if(this.snake.currentDir!='bottom'){
264                                     this.snake.direction='top';
265                                     this.snake.currentDir='top';
266                                 }
267                                 break;
268                             case 39:
269                                 if(this.snake.currentDir!='left'){
270                                     this.snake.direction='right';
271                                     this.snake.currentDir='right';
272                                 }
273                                 break;
274                             case 40:
275                                 if(this.snake.currentDir!='top'){
276                                     this.snake.direction='bottom';
277                                     this.snake.currentDir='bottom';
278                                 }
279                                 break;
280                         }
281                     }.bind(that),false)
282                 }
283                 //把Game暴露给window
284                 window.Game = Game;
285             }())
286             //创建游戏对象并初始化
287             function start(){
288                 var game = new Game(my$('map'));
289                 game.init(my$('map'));
290             }
291             
292         </script>
293     </body>
294 </html>

 

 

1.自调用函数除了避免变量重名外还有其他的作用吗?

2.原型的作用是共享数据,节约内存空间。 

3.setInterval 中的this是window。

4.bind的作用是将bind后面括号中的值作为函数中this的值。

posted @ 2019-08-15 15:27  兔咂  阅读(214)  评论(0编辑  收藏  举报