javascript贪吃蛇游戏

搭建页面

#map {
                 1350px;
                height: 640px;
                background-color: #ccc;
                position: relative;
            }

分析对象

游戏对象

蛇对象

食物对象

创建食物对象

创建Food的构造函数,并设置属性

var position='absolute';
    var elements=[];
    function Food(x,y,width,height,color){
        this.x=x || 0;
        this.y=y || 0;
        this.width=width || 20;
        this.height=height || 20;
        this.color=color || 'green';    
    }

通过原型设置render方法,实现随机产生食物对象,并渲染到map上

//通过原型设置render方法,实现随机产生食物对象,并渲染到map上
    Food.prototype.render=function (map){
        // 随机食物的位置,map.宽度/food.宽度,
        //总共有多少分food的宽度,随机一下。
        //然后再乘以food的宽度
    
        this.x=parseInt(Math.random()*map.offsetWidth/this.width)*this.width;
        this.y=parseInt(Math.random()*map.offsetHeight/this.height)*this.height;
    
        // 动态创建食物对应的div
        var div=document.createElement('div');
        map.appendChild(div);
        div.style.position=position;
        div.style.left=this.x+'px';
        div.style.top=this.y+'px';
        div.style.width=this.width+'px';
        div.style.height=this.height+'px';
        div.style.backgroundColor = this.color;
        elements.push(div);
    }

通过自调用函数,进行封装,通过window暴露Food对象

window.Food = Food;

创建蛇对象

属性

  • width 蛇节的宽度 默认20

  • height 蛇节的高度 默认20

  • body 数组,蛇的头部和身体,第一个位置是蛇头

  • direction 蛇运动的方向 默认right 可以是 left top bottom

(function(){
    var position='absolute';
    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:'blue'},
            {x:1,y:2,color:'blue'}
        ];
        this.direction=direction || 'right';
    }
    
    Snake.prototype.render=function(map){
        for(var i=0;i<this.body.length;i++){
            var obj=this.body[i];
            var div=document.createElement('div');
            map.appendChild(div);
            div.style.left=obj.x*this.width+'px';
            div.style.top=obj.y*this.height+'px';
            div.style.position=position;
            div.style.backgroundColor=obj.color;
            div.style.width=this.width+'px';
            div.style.height=this.height+'px';
        }
    }

在自调用函数中暴露Snake对象

window.Snake = Snake;

创建游戏对象

//构造函数
    (function(){
        var that=null;
    function Game(map){
        this.Food=new Food();
        this.Snake=new Snake();
        this.map=map;
        that=this;
    }
    
    //开始游戏,渲染食物对象和蛇对象
    Game.prototype.start=function(){
        this.Food.render(this.map);
        this.Snake.render(this.map);
        
        this.Snake.move(this.Food,this.map);
        this.Snake.render(this.map);
        
          runSnake(this.Snake, this.map);
          bindKey();
        
    }

游戏的逻辑

写蛇的move方法

/*- 在蛇对象(snake.js)中,在Snake的原型上新增move方法
1. 让蛇移动起来,把蛇身体的每一部分往前移动一下
2. 蛇头部分根据不同的方向决定 往哪里移动
*/
		Snake.prototype.move=function(Food,map){
			 // 让蛇身体的每一部分往前移动一下
			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 'left': 
        this.body[0].x -= 1;
        break;
      case 'right':
        this.body[0].x += 1;
        break;
      case 'top':
        this.body[0].y -= 1;
        break;
      case 'bottom':
        this.body[0].y += 1;
        break;
    }

  

让蛇自己动起来

//添加runSnake的私有方法,开启定时器调用蛇的move和render方法,让蛇动起来
    
    //判断蛇是否撞墙
    function runSnake(){
        var timerId=setInterval(function(){
        // 在渲染前,删除之前的蛇    
        this.Snake.render(this.map);
        // 判断蛇是否撞墙
        var maxX=this.map.offsetWidth/this.Snake.width;
        var maxY=this.map.offsetHeight/this.Snake.height;
        var headX=this.Snake.body[0].x;
        var headY=this.Snake.body[0].y;
        
        if(headX<0 || headX>=maxX){
            clearInterval(timerId);
            alert('Game Over');
        }
        if (headY < 0 || headY >= maxY) {
            clearInterval(timerId);
            alert('Game Over');
      }
        }.bind(that),150)
    }
    
    //通过键盘控制蛇的移动方向
    function bindKey(){
        document.addEventListener('keydown',function(e){
             switch (e.keyCode) {
        case 37:
          // left
          this.Snake.direction = 'left';
          break;
        case 38:
          // top
          this.Snake.direction = 'top';
          break;
        case 39:
          // right
          this.Snake.direction = 'right';
          break;
        case 40:
          // bottom
          this.Snake.direction = 'bottom';
          break;
      }
        }.bind(that),false);
    }
     window.Game = Game;
}())    

判断蛇是否吃到食物

// 在移动的过程中判断蛇是否吃到食物
    // 如果蛇头和食物的位置重合代表吃到食物
    // 食物的坐标是像素,蛇的坐标是几个宽度,进行转换 
        
        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.render(map);
        }
        }
        
        //添加删除蛇的私有方法,在render中调用
        function remove(){
            // 删除渲染的蛇
            var i=elements.length-1;
            for(;i>=0;i--){
                 // 删除页面上渲染的蛇
                elements[i].parentNode.removeChild(elements[i]);
                // 删除elements数组中的元素
                elements.splice(i,1);
            }
        }
        

把html中的js代码放到index.js中

避免html中出现js代码

自调用函数的参数


(function (window, undefined) {
 var document = window.document;

}(window, undefined))
  • 传入window对象

将来代码压缩的时候,可以吧 function (window) 压缩成 function (w)

  • 传入undefined

在将来会看到别人写的代码中会把undefined作为函数的参数(当前案例没有使用)因为在有的老版本的浏览器中 undefined可以被重新赋值,防止undefined 被重新赋值

心得:

虽然这是第一个模仿的小游戏,相信以后会有更多属于自己的小程序
原文地址:https://www.cnblogs.com/www-tty-com/p/13817337.html