二十七、JS经典贪吃蛇demo

一、首先 创建地图

1.封装一个地图的类;

function Map(){
    //设置地图的相关属性
    this.width=1200;
    this.height=600;
    this.position="relative";
    this.backgroundColor="black";
    this.margin="0 auto";
    //封装接受地图对象的属性
    this.Mapr=null;
    //构造创建地图方法
    this.CreateMap=function(){
        if(this.Mapr==null){
            //创建dom元素
            this.Mapr=document.createElement("div");
            this.Mapr.style.width=this.width+"px";
            this.Mapr.style.height=this.height+"px";
            this.Mapr.style.position=this.position;
            this.Mapr.style.backgroundColor=this.backgroundColor;
            this.Mapr.style.margin=this.margin;
            //将创建到的dom元素添加到body
            document.body.appendChild(this.Mapr);
        }
    }
}

2.通过实例化调用类的属性和方法创建地图;

//实例化地图 调用创建方法
 map=new Map();
 map.CreateMap();

 

二、创建蛇并构造相应的运动方法

1.创建蛇 封装一个蛇的类 及其创建方法

 分析:经典款贪吃蛇由若干个小方块组成身体,蛇头与蛇身的颜色不一致,但大小相同,即蛇是由很多属性一致的方块组成,要存储一系列类型一致的数据第一时间考虑数组,并且数组有push()追加方法,也解决了后面吃豆豆后身体增长的问题;默认蛇开始为3个小方块长度;(30x30的小方块)

注意:数组存储蛇的每一节,首个位置设置为蛇头;

  数组中存储null,left,top,颜色四个值;(left ,top值是小方块宽高x对应个数值)

var snack;
function Snack(){
    this.width=30;
    this.height=30;
    this.position="absolute";
    this.border="1px solid #ffffff";
    this.Snackbody=[[null,3,1,"red"],[null,2,1,"silver"],[null,1,1,"silver"]];
    //构造创建蛇方法
    this.CreatSnack=function(){
        for(var key in this.Snackbody){
            if(this.Snackbody[key][0]==null){
                this.Snackbody[key][0]=document.createElement("div");
                this.Snackbody[key][0].style.width=this.width+"px";
                this.Snackbody[key][0].style.height=this.height+"px";
                this.Snackbody[key][0].style.position=this.position;
                this.Snackbody[key][0].style.border=this.border;
                this.Snackbody[key][0].style.backgroundColor=this.Snackbody[key][3];
                map.Mapr.appendChild(this.Snackbody[key][0]);
            }
            this.Snackbody[key][0].style.left=this.Snackbody[key][1]*this.width+"px";
            this.Snackbody[key][0].style.top=this.Snackbody[key][2]*this.height+"px";
        }
    }
}

实例化蛇 调用创建方法

//实例化蛇 调用创建方法
snack=new Snack();
snack.CreatSnack();

 

2.封装蛇移动方法

 分析:

(1)贪吃蛇运动其实是属性(left,top)的传递,即蛇头移动后,其后那节身体移动到蛇头移动前的位置,再后面的身体依次移动到前一节移动前的位置;

注意:需增加一个蛇头默认方向属性

  控制蛇头在不同方向上的运动,带动蛇身体的移动;

  在改变每节属性改变之后需再次调用蛇的创建方法,相当于每次移动后在新的位置创建蛇;

//封装蛇移动的方法
this.SnackMove=function(){
    //通过传递蛇的left top值完成蛇的运动
    for(var i=this.Snackbody.length-1;i>0;i--){
        this.Snackbody[i][1]=this.Snackbody[i-1][1];
        this.Snackbody[i][2]=this.Snackbody[i-1][2];
    }
    //设置蛇头在不同方向的移动 带动蛇的移动 需增加一个默认方向属性
    switch(this.direct){
        case "right":this.Snackbody[0][1]+=1;break;
        case "left":this.Snackbody[0][1]-=1;break;
        case "up":this.Snackbody[0][2]-=1;break;
        case "down":this.Snackbody[0][2]+=1;break;
    }
    //调用蛇的创建方法
    this.CreatSnack();
}

 

(2)通过按键上下左右控制蛇的移动

e.keyCode 获取按键码的方法 利用获取到的按键码控制上下左右移动;

注意:当蛇朝着一个方向正在运动的时候,按相反键时不能使蛇反向移动,需要处理这个bug(在执行按键操作之前对现在的方向进行判断)

//通过按键事件控制蛇头改变方向
document.onkeydown=function(e){
   /* e.keyCode; 获取按键码的方法*/
   switch(e.keyCode){
       case 37:if(snack.direct!="right")snack.direct="left";break;
       case 38:if(snack.direct!="down")snack.direct="up";break;
       case 39:if(snack.direct!="left")snack.direct="right";break;
       case 40:if(snack.direct!="up")snack.direct="down";break;
    }
}

 

(3)封装蛇的穿墙方法 即当蛇运到到边界令其从相反方向的边间穿出;

 分析:利用蛇头的坐标值(left top)与边界做比较,相等时设置蛇头坐标为相反方向边界值;

 注意:

需要判断上下左右方向,只需改变这个方向上对应的坐标值;

需要蛇的运动方法内调用该方法,且放置在调用创建方法之前;

判断时使用方块个数值判断(地图宽=40个小方块 高=20个小方块)

从左()方向穿出去另一半出来时,需要对之进行-1处理,让其在地图内侧出现;

穿出去时left是以蛇头的右边线(下边线),所以判断条件是< >=;

 

Ps:也可以将这里写为撞墙后游戏结束,同理需要比较,在相同时停止计时器,弹出游戏停止的字幕;

//封装蛇的穿墙方法
this.Snackback=function(){
    if(this.Snackbody[0][1]>=40){
        this.Snackbody[0][1]=0;
    }
    if(this.Snackbody[0][1]<0){
        this.Snackbody[0][1]=39;
    }
    if(this.Snackbody[0][2]>=20){
        this.Snackbody[0][2]=0;
    }
    if(this.Snackbody[0][2]<0){
        this.Snackbody[0][2]=20;
    }
}

 

二、创建豆豆

1.封装豆豆的类 随机位置创建豆豆

 利用Math的随机数方法控制随机位置产生豆豆 注意 对生成的随机数要进行向下取整处理,保证每个豆豆都在 40x20的地图网格里;

/*第三步:封装一个豆豆类*/
 var food;
 function Food(){
     this.width=30;
     this.height=30;
     this.backgroundColor="yellow";
     this.position="absolute";
     this.foodr=null;
     this.x;//x轴 left
     this.y;//y轴 top
     //封装豆豆创建方法
     this.CreatFood=function(){
         this.x=Math.floor(Math.random()*40);
         this.y=Math.floor(Math.random()*20);
         if(this.foodr==null){
             this.foodr=document.createElement("div");
             this.foodr.style.width=this.width+"px";
             this.foodr.style.height=this.height+"px";
             this.foodr.style.backgroundColor=this.backgroundColor;
             this.foodr.style.position=this.position;
             map.Mapr.appendChild(this.foodr);
         }
         this.foodr.style.left=this.x*this.width+"px";
         this.foodr.style.top=this.y*this.height+"px";
     }
 }

实例化豆豆 调用创建方法

//实例化豆豆 调用创建方法
food=new Food();
food.CreatFood();

 

三、补充蛇运动方法代码

1.补充蛇吃豆豆  在蛇移动方法中补充

     分析:判断蛇的left top与豆豆的left top是否一致,一致时,重新创建随机豆豆,同时蛇身体数组追加一节;

 

//判断蛇是否吃到豆豆
if(this.Snackbody[0][1]==food.x&&this.Snackbody[0][2]==food.y){
    this.Snackbody.push([
        null,
        this.Snackbody[this.Snackbody.length-1][0],
        this.Snackbody[this.Snackbody.length-1][1],
        "silver"
    ])
    //食物换位置
    food.CreatFood();

}

 

 

2.补充蛇头撞到蛇身,弹出游戏结束,清除定时器;

  分析:循环判断蛇头是否和每节蛇身坐标一致,若出现一致,撞死。

 从第一节蛇身开始比较,

     注意:无论alert();在清除定时器之前或者之后,弹框之后还会执行一次运 动代码,因为alert()高于其他代码;

由于是在蛇运动过程中判断是否撞到,所以应该在蛇移动方法中调用该方法;

//封装蛇撞死方法
this.SnackDie=function(){
    for(var i=1;i<this.Snackbody.length;i++){
        if(this.Snackbody[0][1]==this.Snackbody[i][1]&&this.Snackbody[0][2]==this.Snackbody[i][2]){
            alert("撞死了");
            clearInterval(time);
        }
    }
}

 

四、完善整合代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>贪吃蛇</title>
    <style>
        body,html{
            width: 100%;
            height: 100%;
            overflow: hidden;/* 消除窗体抖动*/
        }
    </style>
</head>
<body>
<script>
   /* 第一步:封装一个地图类*/
   var map;
   function Map(){
       //设置地图的相关属性
       this.width=1200;
       this.height=600;
       this.position="relative";
       this.backgroundColor="black";
       this.margin="0 auto";
       //封装接受地图对象的属性
       this.Mapr=null;
       //构造创建地图方法
       this.CreateMap=function(){
           if(this.Mapr==null){
               //创建dom元素
               this.Mapr=document.createElement("div");
               this.Mapr.style.width=this.width+"px";
               this.Mapr.style.height=this.height+"px";
               this.Mapr.style.position=this.position;
               this.Mapr.style.backgroundColor=this.backgroundColor;
               this.Mapr.style.margin=this.margin;
               //将创建到的dom元素添加到body
               document.body.appendChild(this.Mapr);
           }
       }
   }
    /*第二步:封装一个蛇类*/
    var snack;
    function Snack(){
        this.width=30;
        this.height=30;
        this.position="absolute";
        this.border="1px solid #ffffff";
        this.Snackbody=[[null,3,1,"red"],[null,2,1,"silver"],[null,1,1,"silver"]];
        this.direct="right";//增加默认方向属性
        //构造创建蛇方法
        this.CreatSnack=function(){
            for(var key in this.Snackbody){
                if(this.Snackbody[key][0]==null){
                    this.Snackbody[key][0]=document.createElement("div");
                    this.Snackbody[key][0].style.width=this.width+"px";
                    this.Snackbody[key][0].style.height=this.height+"px";
                    this.Snackbody[key][0].style.position=this.position;
                    this.Snackbody[key][0].style.border=this.border;
                    this.Snackbody[key][0].style.backgroundColor=this.Snackbody[key][3];
                    map.Mapr.appendChild(this.Snackbody[key][0]);
                }
                this.Snackbody[key][0].style.left=this.Snackbody[key][1]*this.width+"px";
                this.Snackbody[key][0].style.top=this.Snackbody[key][2]*this.height+"px";
            }
        }
        //封装蛇移动的方法
        this.SnackMove=function(){
            //通过传递蛇的left top值完成蛇的运动
            for(var i=this.Snackbody.length-1;i>0;i--){
                this.Snackbody[i][1]=this.Snackbody[i-1][1];
                this.Snackbody[i][2]=this.Snackbody[i-1][2];
            }
            //设置蛇头在不同方向的移动 带动蛇的移动 需增加一个默认方向属性
            switch(this.direct){
                case "right":this.Snackbody[0][1]+=1;break;
                case "left":this.Snackbody[0][1]-=1;break;
                case "up":this.Snackbody[0][2]-=1;break;
                case "down":this.Snackbody[0][2]+=1;break;
            }
            //调用蛇的穿墙方法
            this.Snackback();
            //判断蛇是否吃到豆豆
            if(this.Snackbody[0][1]==food.x&&this.Snackbody[0][2]==food.y){
                this.Snackbody.push([
                    null,
                    this.Snackbody[this.Snackbody.length-1][0],
                    this.Snackbody[this.Snackbody.length-1][1],
                    "silver"
                ])
                //食物换位置
                food.CreatFood();
            }
            //调用蛇撞死方法
            this.SnackDie();
            //调用蛇的创建方法
            this.CreatSnack();
        };
        //封装蛇的穿墙方法
        this.Snackback=function(){
            if(this.Snackbody[0][1]>=40){
                this.Snackbody[0][1]=0;
            }
            if(this.Snackbody[0][1]<0){
                this.Snackbody[0][1]=39;
            }
            if(this.Snackbody[0][2]>=20){
                this.Snackbody[0][2]=0;
            }
            if(this.Snackbody[0][2]<0){
                this.Snackbody[0][2]=20;
            }
        }
        //封装蛇撞死方法
        this.SnackDie=function(){
            for(var i=1;i<this.Snackbody.length;i++){
                if(this.Snackbody[0][1]==this.Snackbody[i][1]&&this.Snackbody[0][2]==this.Snackbody[i][2]){
                    alert("撞死了");
                    clearInterval(time);
                }
            }
        }
    }
   /*第三步:封装一个豆豆类*/
    var food;
    function Food(){
        this.width=30;
        this.height=30;
        this.backgroundColor="yellow";
        this.position="absolute";
        this.foodr=null;
        this.x;//x轴 left
        this.y;//y轴 top
        //封装豆豆创建方法
        this.CreatFood=function(){
            this.x=Math.floor(Math.random()*40);
            this.y=Math.floor(Math.random()*20);
            if(this.foodr==null){
                this.foodr=document.createElement("div");
                this.foodr.style.width=this.width+"px";
                this.foodr.style.height=this.height+"px";
                this.foodr.style.backgroundColor=this.backgroundColor;
                this.foodr.style.position=this.position;
                map.Mapr.appendChild(this.foodr);
            }
            this.foodr.style.left=this.x*this.width+"px";
            this.foodr.style.top=this.y*this.height+"px";
        }
    }
    var time;
    window.οnlοad=function(){
       //实例化地图 调用创建方法
        map=new Map();
        map.CreateMap();
        //实例化蛇 调用创建方法
        snack=new Snack();
        snack.CreatSnack();
        time=setInterval(function(){
            snack.SnackMove();
        },200);

        //实例化豆豆 调用创建方法
        food=new Food();
        food.CreatFood();
        //通过按键事件控制蛇头改变方向
        document.οnkeydοwn=function(e){
           /* e.keyCode; 获取按键码的方法*/
           switch(e.keyCode){
               case 37:if(snack.direct!="right")snack.direct="left";break;
               case 38:if(snack.direct!="down")snack.direct="up";break;
               case 39:if(snack.direct!="left")snack.direct="right";break;
               case 40:if(snack.direct!="up")snack.direct="down";break;
            }
        }
    }
</script>
</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值