【前端笔记】js简单代码实现贪吃蛇~~~

贪吃蛇是前端人入门且必须的技能。今天闲下来整理介绍一下~~~

首先,先要确定贪吃蛇小游戏的需求:

  • 背景墙   确定行列
  • 创建蛇头
  • 蛇头移动
  • 蛇头变相
  • 创建实物
  • 碰撞检测
  • 增加身体
  • 食物消失 随机创建新的
  • 身体蛇头一起移动

我们首先通过创建一些div元素来生成网格轨道背景:

然后创建蛇头(我们让蛇头位置是固定的,食物是随机产生的)

接下来是蛇头的自动移动(我们设置一个定时器来实现蛇头的自动移动):

蛇头的变向操作(使用到了键盘事件 我们使用上下左右键来移动 判断keycode值来改变蛇头位置)

接下来创建随机食物:

食物和蛇头的碰撞检测:

注意食物不能成成在身体上,所以我们需要添加条件判断:

吃掉食物后产生身体块

身体块随着头移动

把创建头 食物 身体 封装到一起(共有的地方)

让几个函数需要的参数是一致的,不一样的在内部实现

接下来还要优化以下~判断蛇头是否碰撞了边界和自己的身体,也要不让蛇可以回退移动;随机产生不同分值的食物,获得一定分值后的速度也要变快

以下是具体代码实现:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>贪吃蛇</title>
	<style>
		.out{
			width: 500px;
			height: 500px;
			background: #ccc;
			border: 1px solid blue;
			position: relative;
			overflow: hidden;
		}
		p{
			display: inline-block;
		}
		span{
			display: block;
		}
	</style>
</head>
<body>
<div class="out">
</div>
<button onclick="reset()">再玩一局</button>
&nbsp;&nbsp;&nbsp;&nbsp;得分:<p></p>
<span>得分大于等于5,改变速度。得分大于等于10,改变速度。</span>
<script src="./snake.js"></script>
<script>
var col=10;
var row=10;
var w=50;
var h=50;
var out=$('.out')[0];
var score=$('p')[0];
var bodys=[];
var num=0;


var time=1000;//速度
//背景
createBg(out,col,row)
// 蛇头
var head=createNode(1,out)
// 食物
var food=createNode(2,out)//createFood(out,w,h,col,row,1)
createKeyEvent(head);
//计时器
var timer=setInterval(play,time)
//
function play() {
	//身体移动
	moveBody(bodys,head)
	//头部移动
	moveHead(head);
	var checkstate=check(head,food);
	
	if(checkstate){
		//计算分数
		num+=Number(food.getAttribute('value'));
		score.innerHTML=num+"分"
		//判断分数 改变速度
		if (num>=5&&num<10) {
			time=600;
			clearInterval(timer);
			timer=setInterval(play,time);

		}
		else if(num>=10){
			time=300;
			clearInterval(timer);
			timer=setInterval(play,time);
		}


		//删除food
		out.removeChild(food);
		//创建food(food不能创建在身体上)
		food=createNode(2,out)
		//创建身体
		if (bodys.length>0) {
			// var body=createBody(out,w,h,bodys[bodys.length-1])
			var body=createNode(3,out,bodys[bodys.length-1])
			console.log(body)
		}else{
		   // var body=createBody(out,w,h,head)
		   var body=createNode(3,out,head)
		   console.log(body)
		}		
		bodys.push(body)
	}

    var bodycheckstate=checkbody(head,bodys);
	if (bodycheckstate==false) {
		clearInterval(timer);
		alert("咬到自己了!")
	}


	var borderstate=checkBorder(head,out);
	if (borderstate==false) {
		clearInterval(timer);
		 alert("game over!") 
	}
}

</script>
</body>
</html>
<!-- 
1.背景墙   确定行列
2.创建蛇头
3.蛇头移动
4.蛇头变相
5.创建实物
6.碰撞检测
7.增加身体
8.食物消失 随机创建新的
9身体蛇头一起移动

-------完成-------

 -->

 

 //获取元素方法
 function $(string){
   var tag=string.charAt(0);
   var ele=null;
   switch(tag){
       case ".":
        ele=document.getElementsByClassName(string.slice(1))
        break;
       case "#":
        ele=document.getElementById(string.slice(1))
        break;
       default:
        ele=document.getElementsByTagName(string);
        break;
   }
   return  ele;
}
//创建背景方法
function createBg(parent,col,row){
  //创建表格
  parent.style.width=row*50+"px";
  parent.style.height=col*50+"px";
  for (var i = 0; i < row; i++) {
    for (var j = 0; j < col; j++) {
      var  div =document.createElement('div')
      div.style.width="48px"
      div.style.height="48px"
      div.style.border="1px solid white"
      div.style.float='left'
      parent.appendChild(div);
    }
  }
}

//事件监听
function createKeyEvent(head){
  document.onkeyup=function(event){
   console.log(event)
   var event=event||window.event
   var key=event.keyCode;
      if (head.className=='top'&&key==40) {
         return;
       }
       else if (head.className=='right'&&key==37) {
        
          return;
       }
       else if (head.className=='down'&&key==38) {
          return;
       }
       else if (head.className=='left'&&key==39) {
           return;
       }
       switch(key){
          case 40: 
            head.className='down'
          break;
          case 37:
            head.className="left"
          break;
          case 38:
             head.className="top"
          break;
          case 39:
             head.className="right"
          break;
       }
}
}

//身体碰撞检测
function checkbody(obj1,arr) {
  for (var i = 1; i < arr.length; i++) {
      if (obj1.offsetTop==arr[i].offsetTop&&obj1.offsetLeft==arr[i].offsetLeft) {
          return false;
      }
  }
}




//碰撞检测
function check(obj1,obj2){
  if (obj1.offsetLeft==obj2.offsetLeft&&obj1.offsetTop==obj2.offsetTop) {
    return true;
  }
   return false;
}
//头部移动
function moveHead(head){
var left=0;
var top=0;
switch(head.className){
  case 'left':
  left=head.offsetLeft-50;
  top=head.offsetTop
  break;
  case 'right':
  left=head.offsetLeft+50;
  top=head.offsetTop
  break;
  case 'top':
  left=head.offsetLeft;
  top=head.offsetTop-50
  break;
  case 'down':
  left=head.offsetLeft;
  top=head.offsetTop+50
  break;
}
head.style.left=left+'px'
head.style.top=top+'px'
}
//移动body
function moveBody(array){
  if (array.length>0) {
     for (var i = array.length - 1; i >= 0; i--) {
          switch(array[i].className){
            case 'left':
              x=array[i].offsetLeft-50;
              y=array[i].offsetTop
              break;
              case 'right':
              x=array[i].offsetLeft+50;
              y=array[i].offsetTop
              break;
              case 'top':
              x=array[i].offsetLeft;
              y=array[i].offsetTop-50
              break;
              case 'down':
              x=array[i].offsetLeft;
              y=array[i].offsetTop+50
              break;
         }
          array[i].style.left=x+"px";
          array[i].style.top=y+'px'
          if (i==0) {
                   array[i].className=head.className
          }else{
            array[i].className=array[i-1].className
          }
    
     }
  }
}
/*
检测坐标是否重合
*/

function  checkfood(x,y,array){
  console.log(head)
  if (x==head.offsetLeft&&y==head.offsetTop) {
    return false
  }
  for (var i = 0; i < array.length; i++) {
    // 检测到重复
    if (array[i].offsetLeft==x&&array[i].offsetTop==y) {
      return false;
    }
    if (i==array.length-1) {
      return  true;
    }
  }
  return true;
}
/*
创建节点对象
 type 1  蛇头  2 food  3 身体
*/
function createNode(type,parent,preObj){
  var x=0;
  var y=0;
  var w=50;
  var h=50;
  var bgColor;
  var fen;
  var className="";
  var  preObj=preObj?preObj:null
  switch(type){
    case 1:
      bgColor="red"
      className="right"
      break;
    case 2:
       var foodtype=parseInt(Math.random()*10)%3
       var foods=[['yellow',1],['skyblue',2],['pink',3]]
        bgColor=foods[foodtype][0]
        fen=foods[foodtype][1]
          var array=bodys;
          // console.log(array)
        test();
        function test(){
            var a=parseInt(Math.random()*row)*50;
            var b=parseInt(Math.random()*col)*50;
            var state=checkfood(a,b,array)
            if (state) {
              x=a;
              y=b;
            }else{
              test();
            }
        }
        break;
    case 3:
       switch(preObj.className){
          case 'left':
            x=preObj.offsetLeft+50;
            y=preObj.offsetTop
            break;
            case 'right':
            x=preObj.offsetLeft-50;
            y=preObj.offsetTop
            break;
            case 'top':
            x=preObj.offsetLeft;
            y=preObj.offsetTop+50
            break;
            case 'down':
            x=preObj.offsetLeft;
            y=preObj.offsetTop-50
            break;
       }   
        className=preObj.className;
        bgColor='black'
       break ;
    default:
       break

  }
  var node=document.createElement('div');
  node.style.background=bgColor;
  node.style.position="absolute";
  node.style.left=x+"px";
  node.style.top=y+"px";
  node.style.width=w+"px";
  node.style.height=h+"px";
  node.style.zIndex=999;
  node.className=className;
  node.setAttribute("value",fen)
  parent.appendChild(node)
  return node;
}



function reset(){
  window.location.reload();
}
//检测碰撞到边界框
function checkBorder(obj1,obj2) {
  if (obj1.offsetLeft>obj2.offsetWidth||obj1.offsetLeft<0||obj1.offsetTop<0||obj1.offsetTop>obj2.offsetHeight) {
    return false;
  }
  return true;
}

  • 18
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值