3

利用js制作简单的贪吃蛇游戏

Image text

首先,我们先来分析一下整个页面的构成。一看可知,游戏框内是一个盒子里面有许多的小方块,我们可以利用 ul和li标签来制作蛇和食物。右侧就是简单的 2个p标签·一个select标签· 2个input标签而已。代码如下

<div class="box" id="box">
    <ul class="oul" id="oul">

    </ul>
</div>
<div class="box1" id="box1">
    <p>最佳历史纪录:<span id="ls">0</span></p>
    <p >当前长度:<span id="dqcd">0</span></p>
    <select id="level">
        <option value="300">初级</option>
        <option value="200">中级</option>
        <option value="100">较难</option>
    </select>
    <input type="button" id="btn1" value="开始">
    <input type="button" id="btn2" value="暂停">
</div>
<audio src="mp3/bg.mp3" loop id="bgaudio"></audio>
        <audio src="mp3/go.wav" id="go"></audio>
        <audio src="mp3/chi.mp3" id="chi"></audio>
    <script type="text/javascript" src="zepto.min.js"></script>
    <script type="text/javascript" src="touch.js"></script>
    <script type="text/javascript" src="sss.js"></script>
    <!-- 引入支持库 -->

因为我们需要很多的小格子,所以 li标签 我们将用利用js里的for循环来创建,这样会使我们的代码量减少,减轻我们的工作量,我们在介绍js代码会详细介绍,现在先不多说。我们接下来要为html文档加上样式,因为代码比较简单,所以我们可以将样式随意写在什么地方。css代码如下:

*{
    margin: 0;
    padding: 0;
}
input{
    outline: none;
    margin: auto;
    
}       
.box{
    width: 3.2rem;
    margin: auto;
    float: left;
}
.oul{
    width: 3.14rem;
    height: 3.14rem;
    border:0.03rem solid peru;
}
.oul li{
    list-style: none;
    width: 5%;
    height: 5%;
    float: left;
}
.box1{
    width: 2rem;
    height: 1rem;
    padding-top: 0.3rem;
    font-size: 0.2rem;
    margin: auto;
    float: left;
}
#level{
    width: 100%;
    height: 0.4rem;
}
#ls{
    color:paleturquoise;
    margin-left: 0.1rem;
}
#dqcd{
    color:paleturquoise;
    margin-left: 0.01rem;
}
#btn1{
    width: 50%;
    height:0.3rem;
    margin-left: 0.4rem;
    margin-top: 0.2rem;
    background: palegreen;
    color: #fff;
    
}
#btn2{
    width: 50%;
    height: 0.3rem;
    margin-left: 0.4rem;
    margin-top: 0.2rem;
    background: palegreen;
    color: #fff;
}

因为我们需要兼容移动端设备和pc端设备,所以我们需要在css前加上媒体查询样式,并且在使用单位时,需要用到rem而不是px。
媒体查询代码如下:

@media screen and (min-width: 320px) {
    html {
      font-size: 100px; } }  
@media screen and (min-width: 360px) {
html {
    font-size: 113px; } }   
@media screen and (min-width: 375px) {
html {
    font-size: 117px; } }
@media screen and (min-width: 384px) {
html {
    font-size: 120px; } } 
@media screen and (min-width: 412px) {
html {
    font-size: 128px; } }
@media screen and (min-width: 414px) {
html {
    font-size: 129px; } }
@media screen and (min-width: 440px) {
html {
    font-size: 138px; } }
@media screen and (min-width: 480px) {
html {
    font-size: 150px; } }

上面我们已经将基本样式都写好,下面我们就要编辑js代码
因为我们需要兼容移动端设备,而现在的移动设备大多数没有键盘,所以我们需要引入一些库来支持手指划动,比如 bammer.js或者touch.js等等。我们这里使用的是touch.js。

在上面,我们并没有在html文档中建立 li标签,所以我们需要在js里建立,利用for循环:

var oul = document.getElementById("oul"); 
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var bgaudio = document.getElementById("bgaudio");
var si = document.getElementById("go");
var chi = document.getElementById("chi");
var dqcd = document.getElementById("dqcd");
var ls = document.getElementById("ls");
var level = document.getElementById("level");
// 首先我们先获取各个标签的id,在后面会用到 
var ox = document.createDocumentFragment();
function ab (){
    for(var i = 0 ; i<400 ; i++){
        var oli = document.createElement("li")
        ox.appendChild(oli)
    }
}
ab();
oul.appendChild(ox);

如果你建立后看的不直观,你可以给 li标签 一个边框,以便于观看,由于我们需要看到每一个小格子的索引,所以我们在循环内添加(oli.innerHTML = i),我们就可以清楚的看到每一个格子的索引值。

建立了游戏外边框后,我们开始建立蛇的身体和蛇的食物。在每一次的刷新后,我们会发现蛇身体和食物的颜色都会随机变化,所以我们需要建立一个随机颜色的函数,在每一次使用时直接调用就可以了。

function co (){
    return "rgb("+Math.floor(Math.random()*256)+","+Math.floor(Math.random()*256)+","+Math.floor(Math.random()*256)+")"
}

建立蛇身,蛇身长五,所以我们初始化一个变量,然后利用for循环建立

var snk = [];
snk = oul.children;
var snkbody = [];
var ox = document.createDocumentFragment();
for(var i=0;i<5;i++){
    snkbody.push({pos:i,color:co()})
}
// 创建蛇身
function cd (){
    for(var j=0,l=snkbody.length;j<l;j++){  
        snk[snkbody[j].pos].style.background=snkbody[j].color;   
    }      
}
cd(); 
// 为蛇添加随机颜色

然后我们为你为蛇建立食物,但是我们需要注意食物不能与蛇身在初始化到一起,所以我们需要如下代码:

var food = [{pos:0,color:"red"}];
function isin (index){
    for(var j=0,l=snkbody.length;j<l;j++){
        if(snkbody[j].pos==index){
                return true;
            break;
        }    
    }
    return false;    
};
function snkfood (){
    var index = Math.floor(Math.random()*400);
    while(isin(index)){
        index = Math.floor(Math.random()*400);
    }
    food = {pos:index,color:co()}
    snk[index].style.background=food.color;
}
// 如果食物被蛇身覆盖,随机再次产生产生一个食物
snkfood();

下面我们就需要让蛇动起来

var snkh = snkbody.slice(-1)[0].pos;
var snkw = snkbody.slice(0,1)[0].pos;
// 获取蛇头蛇尾位置
for(var k=0,l=snkbody.length;k<l-1;k++){
        snkbody[k].pos=snkbody[k+1].pos;
    }
snkh = snkbody[l-1].pos;
// 蛇向前一步走

然而我们像现在发现蛇虽然会走了,但是蛇尾的颜色并不会改变,所以我们还需要将蛇尾的颜色改变。

snk[snkw].style.background=0;

如果我们需要改变蛇的前进方向,我们需要清楚我们的设备,如果是移动设备,我们需要使用手指滑动方法,如果是pc设备,我们需要识别按键,所以我就使用了获取body.width的方法,如果大于1024,即识别为pc端,否则为移动端。

var bodywid = document.body.offsetWidth;
if(bodywid>1024){
    document.addEventListener("keydown",function(e){
        e=e||window.event;
        switch(e.keyCode){
            case 37:{
                //  left
                if(fxg==39)return false;
                fxg=e.keyCode;
                break;
            }
            case 38:{
                if(fxg==40)return false;
                fxg=e.keyCode;
                break;
                // up 
            }
            case 39:{
                if(fxg==37)return false;
                fxg=e.keyCode;
                break;
                // right   
            }
            case 40:{
                if(fxg==38)return false;
                fxg=e.keyCode;
                break;
                // down
            }
        }
    },false);
    // 识别按键
}else{
    oul.touch({
        swipeLeft:function(){
            kkk(37)
        },
        swipeRight:function(){
            kkk(39)
        },
        swipeUp:function(){
            kkk(38)
        },
        swipeDown:function(){
            kkk(40)
        },
    });
    // 划动改变函数kkk的值,使蛇改变方向
    function kkk (e){
          switch(e){
            case 37:{
                //  left
                if(fxg==39)return false;
                fxg=e;
                break;
            }
            case 38:{
                if(fxg==40)return false;
                fxg=e;
                break;
                // up 
            }
            case 39:{
                if(fxg==37)return false;
                fxg=e;
                break;
                // right   
            }
            case 40:{
                if(fxg==38)return false;
                fxg=e;
                break;
                // down
            }
        }
    }
    // 39:右  1:40  2:37  3:38
}
if(fxg==40){
        snkbody[l-1].pos=snkbody[l-1].pos+20;  
    }else if(fxg==37){
        snkbody[l-1].pos=snkbody[l-1].pos-1;
    }
    else if(fxg==38){
        snkbody[l-1].pos=snkbody[l-1].pos-20;
    }
    else if(fxg==39){
        snkbody[l-1].pos=snkbody[l-1].pos+1;
    }
// 根据我们的索引可以看出,向下就是依次+20,向上就是-20,向左就是-1,向右就是+1,所以我们在按键之后改变蛇头的方向即可

我们的蛇现在就可以走了,我们还想让他能够吃到食物

if(snkh==food.pos){
    snkbody.unshift({pos:snkw,color:food.color});
    // 将食物放到蛇尾
    snkfood();
    // 再次刷新食物
    chi.play();
    // 播放吃食物音效
    var snkbodycd = snkbody.length-5;
    // 获取分数
    dqcd.innerText=snkbodycd;   
    // 刷新当前分数
}

我们在平时玩贪吃蛇的时候,碰壁也会死亡,所以我们还需要做一下碰壁处理

// 我们的小格子边框是20个,所以我们要在全局建立个数变量
var geshu = 20;
// 之后根据索引找出各个边框处小格子的规律,并且识别蛇头方向,进行碰壁处理
var fxg = 39;
// 初始化方向为向右
if((snkh+1)%geshu==0&&fxg==39){    
    sile();  
}
else if(snkh>=400-geshu&&fxg==40){    
    sile();   
}
else if(snkh%geshu==0&&fxg==37){
    sile();  
}
else if(snkh<geshu&&fxg==38){  
    sile();  
}

我们在识别完墙壁后,我们还需要识别自己,让蛇撞上自己之后,也会死亡。

for(var i =0,l=snkbody.length;i<l-1;i++){
        if(snkbody[i].pos==snkh){
            sile(); 
        }
    }
    cd();

这样我们的贪吃蛇游戏已经完成了大半
下面就是我们将制作点击按钮和暂停按钮

btn1.onclick=function(){
    sudu = level.value
    // 设置速度
    clearInterval(ddd)
    // 首先清除定时器,防止多次点击定时器冲突
    ddd=setInterval(function(){
        fzhs ();
    },sudu) 
    // 将以上蛇开始运动的代码放入一个名为fzhs的代码中循环
    bgaudio.play();  
    // 播放背景音乐
}
// 点击开始
btn2.onclick=function(){
    clearInterval(ddd);
    // 清除定时器
    bgaudio.pause();
    // 声音暂停
}

在蛇死亡后,还需要死亡音效,弹出框,页面刷新

function sile(){
    var l = snkbody.length-5;
    // 计算蛇吃了几个食物
    var score = localStorage.getItem("score")
    if(l>score){
        localStorage.setItem("score",l)
    }
    // 如果当前分数大于历史最高分数,我们要将历史最高分数设置为当前分数
    si.play();
    // 播放死亡音乐
    alert("GameOver");
    // 弹出GameOver
    location.reload();
    页面刷新
    return false; 
}

我们还需要设置历史最高分数

var score = localStorage.getItem("score")||0;
ls.innerHTML = score;

这样一个贪吃蛇小游戏就做完了,你还可以对样式和js进行改进,并告诉我,让我们共同进步!!!

最后,我的github游戏奉上,希望你喜欢。
https://Smallmotor.github.io/...


Smallmotor
478 声望33 粉丝

心若向阳