其他分享
首页 > 其他分享> > JS推箱子项目总结——地图创建与铺设简述(二)

JS推箱子项目总结——地图创建与铺设简述(二)

作者:互联网

JS推箱子项目总结——地图创建与铺设简述(二)

前言

上一篇我们讲解了地图的简单创建,虽然最后我加上了二维数组的一个代码展示,但讲的还是不是很详细。所以就有写了一篇专门讲一下。
在上一篇我们其实对地图的原理有了一定的了解,就是使用循环,不断创建小方块,填充进大地图里。二维数组创建是对地图的进一步优化。
在这一篇了,我会讲解一下,使用二维数组创建箱子与终点
首先,我把上一篇的div使用函数创建模板的代码放在这。

 function createEle(oCss){
 //把形式参数定义为一个对象,然后对象名加.点就是对象的属性,可以随时调用。
         var oBox=document.createElement("div");
                oCss.parent.appendChild(oBox);
                oBox.id=oCss.id;
                oBox.style.width=oCss.w+"px";
                oBox.style.height=oCss.h+"px";
                oBox.style.position=oCss.p;
                oBox.style.margin=oCss.m;
                oBox.style.backgroundImage=oCss.bgi;
                oBox.style.backgroundSize=oCss.bgs;
        return oBox;
    }
    //"w"相当于oCss.w 以此类推。然后使用,(逗号)分割。
    //注意属性使用字符串,就跟:
    //box.style.margin="10px auto"一样,还是要用字符串形式。
    var oBox=createEle({"w":800,
                        "h":600,
    					"p":"relative",
    					"m":"10px auto",
    					"bgi":"url('tu.jpg')",
    					"bgs":"100% 100%",
    					"id":"",
    					"parent":document.body});

这里是上一篇,创建地图的代码。

.box{width: 500px;
     height:500px;
     background-color:#000;
     margin:50px auto; 
     position:relative;
     verflow: hidden;}
.son{width:48px;
     height:48px;
     border:1px solid #f0f;
     position:absolute;}
//createElement()创建元素与appendChild配套使用
//appendChild声明元素创建在哪里(哪个标签里面)
  var oMap=document.createElement("div");
    document.body.appendChild(oMap);
    oMap.className="box";
    for(var i=0;i<10;i++){
        for(var j=0;j<10;j++){
        var oSon=document.createElement("div");
        oSon.className="son";
        //定位位置
        oSon.style.left=j*50+"px";
        oSon.style.top=i*50+"px";
        oMap.appendChild(oSon);
        }
    }

二维数组使用

首先我们要把创建地图与二维数组对接,从二维数组中我们可以看出地图的行列数 以及一些具体要求。
首先我们写一个10 x 10的一个二维数组,以及创建地图的基本代码。

    //基础设施
function createEle(oCss){
         var oBox=document.createElement("div");
                oCss.parent.appendChild(oBox);
                oBox.style.width=oCss.w+"px";
                oBox.style.height=oCss.h+"px";
                oBox.style.position=oCss.p;
                oBox.style.left=oCss.l+"px";
                oBox.style.top=oCss.t+"px";
        return oBox;
    }
//注意在数组最后一位不需要加逗号,
//我们得确认二维数组是一个完整的。
arr=[
      [0,0,0,0,0,0,0,0,0,0],
      [0,1,1,1,1,1,1,1,1,0],
      [0,1,0,0,0,0,0,0,1,0],
      [0,1,0,0,0,0,0,0,1,0],
      [0,1,0,0,2,3,0,0,1,0],
      [0,1,0,0,0,0,0,0,1,0],
      [0,1,0,0,0,0,0,0,1,0],
      [0,1,0,0,0,0,0,10,1,0],
      [0,1,1,1,1,1,1,1,1,0],
      [0,0,0,0,0,0,0,0,0,0]
    ];
//创建外面的大box
    var oBox=createEle({"w":600,
                        "h":600,
                        "p":"relative",
                        "parent":document.body});
    oBox.style.margin="20px auto";
    oBox.style.backgroundColor="#000";
    //算出小box的长宽
    var w=oBox.clientWidth/arr.length;
    var h=oBox.clientHeight/arr[0].length;

    for(var row=0;row<arr.length;row++){
            for(var col=0;col<arr[0].length;col++){
                var oGrid=createEle({"w":w,
                                     "h":h,
                                     "p":"absolute",
                                     "parent":oBox,
                                     "l":col*w,
                                     "t":row*h
                                    });
            }
        }

在这里我们就跟二维数组对接了,使用arr.length与arr[0].length作为box的行列。现在只是行列有了对应,如果我们任意改变二维数组是没有任何变化的。
我们首先得改变二维数组,然后在循环创建的地方加上一个if条件,这样才会在地图上做出想要的创建。

    for(var row=0;row<arr.length;row++){
            for(var col=0;col<arr[0].length;col++){
                //我们把1当做障碍,2作为人物
                var oGrid=createEle({"w":w,
                                     "h":h,
                                     "p":"absolute",
                                     "parent":oBox,
                                     "l":col*w,
                                     "t":row*h
                                    });
            //我们在二维数组中搜索我们的数字,以此为基础创建
            //arr[row][col]
            if(arr[row][col]==1){
             oGrid.style.backgroundColor="#0ff";
                    }
            if(arr[row][col]==2){
                role=createEle({"w":w,
                                 "h":h,
                                 "p":"absolute",
                                 "parent":oBox,
                                 "l":col*w,
                                 "t":row*h
                                });
                role.style.backgroundColor="#fff";
                role.style.backgroundSize="100% 100%";
                //把人物作为一个对象,这样就可以在其中存储一些东西。
                role.row=row;
                role.col=col;
            }
            if(arr[row][col]==3){
                //原理与创建人物那段相同
           var oCase=createEle({"w":w,
                             "h":h,
                             "p":"absolute",
                             "parent":oBox,
                             "l":col*w,
                             "t":row*h
                            });
            oCase.style.backgroundColor="#ff0";
            oCase.style.backgroundSize="100% 100%";
            oCase.row=row;
            oCase.col=col;
                    }
            if(arr[row][col]==10){
                //原理与创建人物那段相同
                        var oWin=createEle({"w":w,
                                         "h":h,
                                         "p":"absolute",
                                         "parent":oBox,
                                         "l":col*w,
                                         "t":row*h
                                        });
                        oWin.style.backgroundColor="#0f0";
                        oWin.style.backgroundSize="100% 100%";
                        oWin.row=row;
                        oWin.col=col;
                    }
        }
    }

移动

现在我们创建了一个有主角有箱子的地图,虽然还不能动,而且箱子的行动实现在于人物的移动。

document.onkeydown=function move(e){
            var key=e.keyCode;//左:37  上:38  右:39  下:40
            if(key==37){
            //当人物左边是通路时,人物就可以行走
                if(arr[role.row][role.col-1]==0){//走之前要处理内存变化
                    arr[role.row][role.col]=0;
                    role.col=role.col-1;
                    role.style.left=role.col*h+"px";
                    arr[role.row][role.col]=2;
                    //当人物左边是箱子时,箱子随着人物的移动而移动
                }else if(arr[role.row][role.col-1]==3){
                    if(arr[role.row][role.col-2]==0||arr[role.row][role.col-2]==10){
                        //箱子左移了,人也左移
                        //箱子先移动
                        arr[oCase.row][oCase.col]=0;//箱子离开之前,还原0
                        oCase.col=oCase.col-1;
                        oCase.style.left=oCase.col*h+"px";
                        arr[oCase.row][oCase.col]=3;
                        //人跟着动
                        arr[role.row][role.col]=0;
                        role.col=role.col-1;
                        role.style.left=role.col*h+"px";
                        arr[role.row][role.col]=2;
                    }
                }
            }
                if(key==38){
                if(arr[role.row-1][role.col]==0){
                    arr[role.row][role.col]=0;
                    role.row=role.row-1;
                    role.style.top=role.row*w+"px";
                    arr[role.row][role.col]=2;
                }else if(arr[role.row-1][role.col]==3){
                    if(arr[role.row-2][role.col]==0||arr[role.row-2][role.col]==10){
                        arr[oCase.row][oCase.col]=0;//箱子离开之前,还原0
                        oCase.row=oCase.row-1;
                        oCase.style.top=oCase.row*w+"px";
                        arr[oCase.row][oCase.col]=3;
                        //人跟着动
                        arr[role.row][role.col]=0;
                        role.row=role.row-1;
                        role.style.top=role.row*w+"px";
                        arr[role.row][role.col]=2;
                    }
                }

            }
                if(key==39){
                if(arr[role.row][role.col+1]==0){
                    arr[role.row][role.col]=0;
                    role.col=role.col+1;
                    role.style.left=role.col*h+"px";
                    arr[role.row][role.col]=2;
                }else if(arr[role.row][role.col+1]==3){
                    if(arr[role.row][role.col+2]==0||arr[role.row][role.col+2]==10){
                        arr[oCase.row][oCase.col]=0;//箱子离开之前,还原0
                        oCase.col=oCase.col+1;
                        oCase.style.left=oCase.col*h+"px";
                        arr[oCase.row][oCase.col]=3;
                        //人跟着动
                        arr[role.row][role.col]=0;
                        role.col=role.col+1;
                        role.style.left=role.col*h+"px";
                        arr[role.row][role.col]=2;
                    }
                }
            }
            if(key==40){
                if(arr[role.row+1][role.col]==0){
                    arr[role.row][role.col]=0;
                    role.row=role.row+1;
                    role.style.top=role.row*w+"px";
                    arr[role.row][role.col]=2;
                }else if(arr[role.row+1][role.col]==3){
                    if(arr[role.row+2][role.col]==0||arr[role.row+2][role.col]==10){
                        arr[oCase.row][oCase.col]=0;//箱子离开之前,还原0
                        oCase.row=oCase.row+1;
                        oCase.style.top=oCase.row*w+"px";
                        arr[oCase.row][oCase.col]=3;
                        //人跟着动
                        arr[role.row][role.col]=0;
                        role.row=role.row+1;
                        role.style.top=role.row*w+"px";
                        arr[role.row][role.col]=2;
                    }
                }
            }
}

解析一下:
当我们按左键时,判断人物左边是不是通路,就是arr[role.row][role.col-1]==0 二维数组中人物的左边是不是0,是的话就往左走。(走的代码有注释)
else if 当人物的左边是箱子时,我们就判断我们推不推得了这个箱子,
arr[role.row][role.col-2]==0 箱子在人物的左边,箱子的左边对于人物来说就是-2的距离。
如果推的了的话,箱子先移动人物再走。

1.我们的人物不能经过终点,箱子才可以
2.终点最好设置在边边那里

获胜

现在我们把箱子推到终点并不会发生任何事情,或许我们可以加上一个简单的条件:比如箱子与终点的位置重叠时弹出你赢了。

  if(oCase.row==oWin.row&&oCase.col==oWin.col){
      alert("you win!");
  }

但这种方式只适合只有一个箱子一个终点时。所以我们得改进一下。
在看推箱子的代码时,我们会发现箱子与人的移动会改变二维数组的内存,也就是走过之处“片草不生”,人物与箱子的移动会把原来位置的二维数组数字改变为通路,而现在的位置二维数组数字为2或者3。
就有一个问题,当箱子被推到终点时,那里的二维数组的数字是什么?
答案是:2。
所以说当箱子推到终点时,终点的数字在二维数组上已经找不到了,在我的理解就是“取代”。
所以我们依照这个原理可以写出

    function isFinished(){
        var finish=true;
        for(var i=0;i<arr.length;i++){
            for(var j=0;j<arr[0].length;j++){
                if(arr[i][j]==10){
                    finish=false;
                }
            }
        }
        return finish;
    }

解析:
设finish初始的状态为true,遍历一遍二维数组,
arr[i][j]==10 只要有一个终点,则finish为false。
如果没有一个终点,则finish会以true返回。

然后我们在行动模式中调用函数。

var success=isFinished();
 if(success===true){
      alert("you win!!!");
  }

哈哈哈,其实这是老师写出来的,我只是copy了一下,在课堂上老师让我们想我也没有想出使用Boolean。借口:主要我没有经常使用Boolean。
其实这个很重要的。

但我们多加了一个箱子会有种bug一样的感觉,就是人物不知道他在推哪个箱子,所以我们要在箱子里加一个ID属性,让人物识别出来。

if(arr[row][col]==3){
     var oCase=createEle({"w":w,
                  "h":h,
                  "p":"absolute",
                  "parent":oBox,
                  "l":col*w,
                  "t":row*h
                 });
         oCase.style.backgroundColor="#ff0";
         oCase.style.backgroundSize="100% 100%";
         //加上ID属性
         oCase.id="box"+row+col
         oCase.row=row;
         oCase.col=col;
 }

然后在箱子的移动我们也要加上箱子id的变化。

var box=document.querySelector("#box"+(role.row-1)+role.col);
  arr[box.row][box.col]=0;//箱子离开之前,还原0
   box.row=box.row-1;
   box.style.top=box.row*w+"px";
   arr[box.row][box.col]=3;
   box.id="box"+box.row+box.col;

最终代码展示

其实拼接起来就好的。。。好吧,我承认是有一点乱。

    //基础设施
function createEle(oCss){
         var oBox=document.createElement("div");
                oCss.parent.appendChild(oBox);
                oBox.style.width=oCss.w+"px";
                oBox.style.height=oCss.h+"px";
                oBox.style.position=oCss.p;
                oBox.style.left=oCss.l+"px";
                oBox.style.top=oCss.t+"px";
        return oBox;
    }
//注意在数组最后一位不需要加逗号,
//我们得确认二维数组是一个完整的。
arr=[
      [1,1,1,1,1,1,1,1,1,1],
      [1,10,0,0,0,0,0,0,0,1],
      [1,1,0,0,0,0,0,0,0,1],
      [1,0,0,0,0,0,0,0,0,1],
      [1,0,0,3,2,3,0,0,0,1],
      [1,0,0,0,0,0,0,0,0,1],
      [1,0,0,0,0,0,0,0,0,1],
      [1,0,0,0,0,0,0,0,1,1],
      [1,0,0,0,0,0,0,0,10,1],
      [1,1,1,1,1,1,1,1,1,1]
    ];
//创建外面的大box
    var oBox=createEle({"w":600,
                        "h":600,
                        "p":"relative",
                        "parent":document.body});
    oBox.style.margin="20px auto";
    oBox.style.backgroundColor="#000";
    //算出小box的长宽
    var w=oBox.clientWidth/arr.length;
    var h=oBox.clientHeight/arr[0].length;

    for(var row=0;row<arr.length;row++){
            for(var col=0;col<arr[0].length;col++){
                //我们把1当做障碍,2作为人物
                var oGrid=createEle({"w":w,
                                     "h":h,
                                     "p":"absolute",
                                     "parent":oBox,
                                     "l":col*w,
                                     "t":row*h
                                    });
            //我们在二维数组中搜索我们的数字,以此为基础创建
            //arr[row][col]
            if(arr[row][col]==1){
             oGrid.style.backgroundColor="#0ff";
                    }
            if(arr[row][col]==2){
                role=createEle({"w":w,
                                 "h":h,
                                 "p":"absolute",
                                 "parent":oBox,
                                 "l":col*w,
                                 "t":row*h
                                });
                role.style.backgroundColor="#fff";
                role.style.backgroundSize="100% 100%";
                //把人物作为一个对象,这样就可以在其中存储一些东西。
                role.row=row;
                role.col=col;
            }
            if(arr[row][col]==3){
                var oCase=createEle({"w":w,
                             "h":h,
                             "p":"absolute",
                             "parent":oBox,
                             "l":col*w,
                             "t":row*h
                            });
                    oCase.style.backgroundColor="#ff0";
                    oCase.style.backgroundSize="100% 100%";
                    //加上ID属性
                    oCase.id="box"+row+col
                    oCase.row=row;
                    oCase.col=col;
            }
            if(arr[row][col]==10){
                //原理与创建人物那段相同
                var oWin=createEle({"w":w,
                                 "h":h,
                                 "p":"absolute",
                                 "parent":oBox,
                                 "l":col*w,
                                 "t":row*h
                                });
                oWin.style.backgroundColor="#0f0";
                oWin.style.backgroundSize="100% 100%";
                oWin.row=row;
                oWin.col=col;
            }
        }
    }
document.onkeydown=function move(e){
            var key=e.keyCode;//左:37  上:38  右:39  下:40
            if(key==37){
            //当人物左边是通路时,人物就可以行走
                if(arr[role.row][role.col-1]==0){//走之前要处理内存变化
                    arr[role.row][role.col]=0;
                    role.col=role.col-1;
                    role.style.left=role.col*h+"px";
                    arr[role.row][role.col]=2;
                    //当人物左边是箱子时,箱子随着人物的移动而移动
                }else if(arr[role.row][role.col-1]==3){
                    if(arr[role.row][role.col-2]==0||arr[role.row][role.col-2]==10){
                      var box=document.querySelector("#box"+role.row+(role.col-1));
                        //箱子左移了,人也左移
                        //箱子先移动
                        arr[box.row][box.col]=0;//箱子离开之前,还原0
                        box.col=box.col-1;
                        box.style.left=box.col*h+"px";
                        arr[box.row][box.col]=3;
                        box.id="box"+box.row+box.col;
                        //人跟着动
                        arr[role.row][role.col]=0;
                        role.col=role.col-1;
                        role.style.left=role.col*h+"px";
                        arr[role.row][role.col]=2;
                        var success=isFinished();
                            if(success===true){
                                alert("you win!");
                            }
                    }
                }
            }
                if(key==38){
                if(arr[role.row-1][role.col]==0){
                    arr[role.row][role.col]=0;
                    role.row=role.row-1;
                    role.style.top=role.row*w+"px";
                    arr[role.row][role.col]=2;
                }else if(arr[role.row-1][role.col]==3){
                    if(arr[role.row-2][role.col]==0||arr[role.row-2][role.col]==10){
                      var box=document.querySelector("#box"+(role.row-1)+role.col);
                        arr[box.row][box.col]=0;//箱子离开之前,还原0
                        box.row=box.row-1;
                        box.style.top=box.row*w+"px";
                        arr[box.row][box.col]=3;
                        box.id="box"+box.row+box.col;
                        //人跟着动
                        arr[role.row][role.col]=0;
                        role.row=role.row-1;
                        role.style.top=role.row*w+"px";
                        arr[role.row][role.col]=2;
                        var success=isFinished();
                            if(success===true){
                                alert("you win!");
                            }
                    }
                }

            }
                if(key==39){
                if(arr[role.row][role.col+1]==0){
                    arr[role.row][role.col]=0;
                    role.col=role.col+1;
                    role.style.left=role.col*h+"px";
                    arr[role.row][role.col]=2;
                }else if(arr[role.row][role.col+1]==3){
                    if(arr[role.row][role.col+2]==0||arr[role.row][role.col+2]==10){
                      var box=document.querySelector("#box"+role.row+(role.col+1));
                        arr[box.row][box.col]=0;//箱子离开之前,还原0
                        box.col=box.col+1;
                        box.style.left=box.col*h+"px";
                        arr[box.row][box.col]=3;
                        box.id="box"+box.row+box.col;
                        //人跟着动
                        arr[role.row][role.col]=0;
                        role.col=role.col+1;
                        role.style.left=role.col*h+"px";
                        arr[role.row][role.col]=2;
                        var success=isFinished();
                            if(success===true){
                                alert("you win!");
                            }
                    }
                }
            }
            if(key==40){
                if(arr[role.row+1][role.col]==0){
                    arr[role.row][role.col]=0;
                    role.row=role.row+1;
                    role.style.top=role.row*w+"px";
                    arr[role.row][role.col]=2;
                }else if(arr[role.row+1][role.col]==3){
                    if(arr[role.row+2][role.col]==0||arr[role.row+2][role.col]==10){
                      var box=document.querySelector("#box"+(role.row+1)+role.col);
                        arr[box.row][box.col]=0;//箱子离开之前,还原0
                        box.row=box.row+1;
                        box.style.top=box.row*w+"px";
                        arr[box.row][box.col]=3;
                        box.id="box"+box.row+box.col;
                        //人跟着动
                        arr[role.row][role.col]=0;
                        role.row=role.row+1;
                        role.style.top=role.row*w+"px";
                        arr[role.row][role.col]=2;
                        var success=isFinished();
                            if(success===true){
                                alert("you win!");
                            }
                    }
                }
            }
}

    function isFinished(){
        var finish=true;
        for(var i=0;i<arr.length;i++){
            for(var j=0;j<arr[0].length;j++){
                if(arr[i][j]==10){
                    finish=false;
                }
            }
        }
        return finish;
    }

标签:box,arr,铺设,JS,简述,style,role,col,row
来源: https://blog.csdn.net/weixin_50759039/article/details/112649460