创建一个盒子box作为蛇的身体,当前盒子中只有一个子元素,代表此时蛇的长度为1.
在创建一个盒子food作为贪吃蛇的食物。
<div> <div></div> </div> <div></div>
2.CSS
设置蛇和食物的样式,这里注意蛇和食物都是绝对定位。
<style> *{ padding: 0px; margin: 0px; } #box div{ width: 30px; height: 30px; box-sizing: border-box; background: green; border: 1px solid black; position: absolute; } #food{ width: 30px; height: 30px; background: brown; position: absolute; } </style>
3.脚本
获取蛇的身体和每一个子元素
var box = document.getElementById("box"); var boxs = document.getElementById("box").children;
定义蛇头的位置
var snackX = 0; var snackY = 0;
获取屏幕宽度和高度,以此来设定墙的边界,以限制蛇的移动范围。
var cw = document.documentElement.clientWidth; var ch = document.documentElement.clientHeight; var minsnackX = 0; var maxsnackX = Math.floor(cw / boxs[0].offsetWidth)*boxs[0].offsetWidth; var minsnackY = 0; var maxsnackY = Math.floor(ch / boxs[0].offsetHeight)*boxs[0].offsetHeight;
定义初始的移动方向。
var turn = "right";
获取食物元素,并设置食物的位置坐标。
var foodele = document.getElementById("food"); var foodX,foodY;
蛇的初始化
for(var i = 0; i <6 ; i++){ box.appendChild(boxs[0].cloneNode(true)); }
刷新食物
function food(){ //此处的坐标要先获取页面最大支持的蛇身体的块数,然后在块数中随机,然后乘以块数的大小, //因为蛇的移动每一步都是固定的,想要判定食物和蛇头重合就必须坐标是整块的倍数。 foodX = parseInt( Math.random()*Math.floor(cw / boxs[0].offsetWidth))*boxs[0].offsetWidth; foodY = parseInt( Math.random()*Math.floor(ch / boxs[0].offsetHeight))*boxs[0].offsetHeight; //判定当食物的产生位置和蛇的任何一个位置重合时就重新生成食物。 for(var i = 0;i<boxs.length;i++){ if(foodX + "px" === boxs[i].style.left && foodY + "px" === boxs[i].style.top){ food(); } } foodele.style.left = foodX + "px"; foodele.style.top = foodY + "px"; }
调用food()方法 生成第一个食物
food();
设置定时器 每次执行一次蛇的运行方法
var timer = setInterval(function(){ snackMOve(); },150)
封装一个蛇的运动方法
//移动和判定边界 function snackMOve(){ //此处为判定方向 根据判定的方向,向改方向前进一个方块 switch(turn){ case "right":snackX +=30;break; case "left":snackX -=30;break; case "bottom":snackY +=30;break; case "top":snackY -=30;break; } //如果蛇越过了墙就从另一端出现 if(snackX > maxsnackX){ snackX = 0; } if(snackX < minsnackX){ snackX = maxsnackX; } if(snackY > maxsnackY){ snackY = 0; } if(snackY < minsnackY){ snackY = maxsnackY; } //从最后一个开始,每个元素跟随上一个元素的位置 for(var i = boxs.length-1; i >0 ; i--){ boxs[i].style.left = boxs[i-1].style.left; boxs[i].style.top = boxs[i-1].style.top ; } //第一个也就是蛇头的位置,永远是根据方向获取的位置 boxs[0].style.left = snackX + "px"; boxs[0].style.top = snackY + "px" ; //判定吃到食物 就长大和刷新 //当蛇头位置移动之后与食物重合 那么刷新食物,并且在蛇的身体中插入一个克隆的元素,相当于长度+1 if(snackX === foodX && snackY === foodY){ food(); box.appendChild(boxs[0].cloneNode(true)); }else{ //判定撞死 //当蛇头与身体中的任何一个元素重合,那么判定结束游戏,停止定时器 for(var i = 1;i<boxs.length;i++){ if(snackX + "px" === boxs[i].style.left && snackY + "px" === boxs[i].style.top){ clearInterval(timer); alert("失败"); } } } }
蛇的运动方向
document.onkeydown = function(eve){ var e = eve||event; var keyCode = e.keyCode||e.which; switch(keyCode){ case 37:if(turn === "right"){break;}turn = "left";break; case 38:if(turn === "bottom"){break;}turn = "top";break; case 39:if(turn === "left"){break;}turn = "right";break; case 40:if(turn === "top"){break;}turn = "bottom";break; } }
全部代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ padding: 0px; margin: 0px; } #box div{ width: 30px; height: 30px; box-sizing: border-box; background: green; border: 1px solid black; position: absolute; } #food{ width: 30px; height: 30px; background: brown; position: absolute; } </style> </head> <body> <div> <div></div> </div> <div></div> <script> var box = document.getElementById("box"); var boxs = document.getElementById("box").children; var snackX = 0; var snackY = 0; var cw = document.documentElement.clientWidth; var ch = document.documentElement.clientHeight; var minsnackX = 0; var maxsnackX = Math.floor(cw / boxs[0].offsetWidth)*boxs[0].offsetWidth; var minsnackY = 0; var maxsnackY = Math.floor(ch / boxs[0].offsetHeight)*boxs[0].offsetHeight; var turn = "right"; var foodele = document.getElementById("food"); var foodX,foodY; for(var i = 0; i <6 ; i++){ box.appendChild(boxs[0].cloneNode(true)); } //随机食物 function food(){ foodX = parseInt( Math.random()*Math.floor(cw / boxs[0].offsetWidth))*boxs[0].offsetWidth; foodY = parseInt( Math.random()*Math.floor(ch / boxs[0].offsetHeight))*boxs[0].offsetHeight; for(var i = 0;i<boxs.length;i++){ if(foodX + "px" === boxs[i].style.left && foodY + "px" === boxs[i].style.top){ food(); } } foodele.style.left = foodX + "px"; foodele.style.top = foodY + "px"; } food(); //设置定时器 移动 var timer = setInterval(function(){ snackMOve(); },150) //移动和判定边界 function snackMOve(){ switch(turn){ case "right":snackX +=30;break; case "left":snackX -=30;break; case "bottom":snackY +=30;break; case "top":snackY -=30;break; } //根据边界归零 if(snackX > maxsnackX){ snackX = 0; } if(snackX < minsnackX){ snackX = maxsnackX; } if(snackY > maxsnackY){ snackY = 0; } if(snackY < minsnackY){ snackY = maxsnackY; } for(var i = boxs.length-1; i >0 ; i--){ boxs[i].style.left = boxs[i-1].style.left; boxs[i].style.top = boxs[i-1].style.top ; } boxs[0].style.left = snackX + "px"; boxs[0].style.top = snackY + "px" ; //判定吃到食物 就长大和刷新 if(snackX === foodX && snackY === foodY){ food(); box.appendChild(boxs[0].cloneNode(true)); }else{ //判定撞死 暂停计时器 刷新 for(var i = 1;i<boxs.length;i++){ // console.log(boxs[i].style.left); if(snackX + "px" === boxs[i].style.left && snackY + "px" === boxs[i].style.top){ clearInterval(timer); alert("失败"); // console.log(1) } } } } //方向 document.onkeydown = function(eve){ var e = eve||event; var keyCode = e.keyCode||e.which; switch(keyCode){ case 37:if(turn === "right"){break;}turn = "left";break; case 38:if(turn === "bottom"){break;}turn = "top";break; case 39:if(turn === "left"){break;}turn = "right";break; case 40:if(turn === "top"){break;}turn = "bottom";break; } } </script> </body> </html>
总结
贪吃蛇的思路主要是有以下几个部分