一、首先 创建地图
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>