简介
一个基于原生js可由键盘上下左右控制的贪吃蛇游戏,主要开发思路分为以下几个部分:
- 基本的html页面(地图区域,开始按钮,计分板)
- 地图网格的创建(这里为方便修改,用js创建可控大小的网格)
- 蛇头的创建
- 蛇的移动
- 食物的创建,随机刷位置(排除刷在蛇身上的情况)
- 蛇头和食物碰撞可增加长度
- 蛇头碰边界或自身则游戏结束
具体模块
基本的html页面
这部分很简单,主要包含1个列表(用来创建网格)、一个开始按钮、一个计分板的div、一个蛇头的div,如果需要更华丽的效果,可再添加css样式
<div id="container">
<ul id="uls"></ul>
<button id="btn">start</button>
<div id="score">score:0</div>
<div id="snake"></div>
</div>
地图的创建
首先声明一个对象,定义网格的长宽及每一个格子的尺寸
data = {
size:30, //尺寸(注意加1px边框)
x:20, //横向数量
y:20 //纵向数量
},
给定 ul 的宽度,在预留的 ul 中添加 li ,给li一个浮动,根据溢出会换行则可以创建出x列y行的网格,li 数量和大小由data确定
function creatMap(){
container.style.width = (data.size + 1)*data.x + "px";
for(var i = 0 ; i < data.x*data.y ; i++){
var oLi = document.createElement("li");
oLi.style.width = oLi.style.height = data.size + "px";
oLi.index = i;
uls.appendChild(oLi);
}
start();
}
这里需要注意,给列表加边框时,会出现 li 边框重叠以及和 ul 边框重叠的情况,可以给 ul 只加左边框和上边框,li 只加下边框和右边框来解决,下面为图示
创建完毕为这样的效果
蛇头的创建
跟上方类似,不过只有一个格子的大小
蛇的移动
这里使用定时器自动移动,当按下对应的按键时改变方向
蛇头的移动
以右键举例:一个简单的按键函数,当按下右键时,蛇头离地图左侧的左边距变为原来左边距+一个格子的宽度,即向右移动一格,其他方向同理。
switch(en.keyCode){
case 37: //左
oDiv[0].style.left = oDiv[0].offsetLeft - width + "px";
break;
case 38: //上
oDiv[0].style.top = oDiv[0].offsetTop - width + "px";
break;
case 39: //右
oDiv[0].style.left = oDiv[0].offsetLeft + width + "px";
break;
case 40: //下
oDiv[0].style.top = oDiv[0].offsetTop + width + "px";
break;
}
蛇身的移动
因为蛇身为一个数组,移动即为这一个方块的左边距和上边距变为上一个方块的左边距和上边距
for(var i = oDiv.length-1 ; i >0 ; i--){
oDiv[i].style.left = oDiv[i-1].offsetLeft + "px";
oDiv[i].style.top = oDiv[i-1].offsetTop + "px";
}
食物的创建
建一个可能出现位置的数组
首先给蛇身和列表给一个格子一个索引值,当索引值不相等时,则可把这个格子加入数组中
/*排除豆豆刷新在蛇身体上的情况*/
var hrr = [];
for(var i = 0 ; i < lis.length ; i++){
if(isFilter(lis[i])){
hrr.push(lis[i]);
}
}
function isFilter(li){
for(var i = 0 ; i < oDiv.length ; i++){
if(li.index == oDiv[i].index){ //索引值相等,则排除
return false;
}
}
return true;
}
数组中随机值显示
在排除重叠可能后,则创建数组中一个随机索引值的方块,效果如下,绿色为蛇头黄色为食物
蛇头吃食物
碰撞函数
碰撞的临界值有四种情况,即物体1的右边距=物体2的左边距,物体1的左边距=物体2的右边距,上下同理(边距为物体边框和ul边框之间的距离)
function eat(el1,el2){
var r1 = el1.offsetLeft + el1.offsetWidth,
r2 = el2.offsetLeft + el2.offsetWidth,
l1 = el1.offsetLeft,
l2 = el2.offsetLeft,
t1 = el1.offsetTop,
t2 = el2.offsetTop,
b1 = el1.offsetTop + el1.offsetHeight,
b2 = el2.offsetTop + el2.offsetHeight;
if(r1 <= l2 || l1 >= r2 || b1 <= t2 || t1 >= b2){
return false; //没碰返回false
}
else{
return true;
}
}
蛇加长度
利用appendChild()将食物剪切到蛇的数组里,并创建一个新的食物
/*吃豆豆加蛇身*/
if(eat(oDiv[0],food)){
food.className = "snakeBody";
snake.appendChild(food); //豆豆变成蛇身
creatFood(); //创建新豆豆
num();
}
游戏结束
当蛇头不与 li 相撞时则为出界,当蛇头与任何一截蛇身上下左右边距都相等时则为撞到自己,此时提示游戏结束
源码
源码可在以下链接下载网页链接