HTML+CSS+JS实现简单的推箱子小游戏

HTML+CSS+JS实现简单的推箱子小游戏

村头老杨头

Thu Jan 2

村头老杨头

闲来无事写一个基于HTML+CSS+JS的推箱子的小游戏
效果图如下:
image.png

步骤如下:
第一个问题:分析游戏的界面如何产生一副这样的界面
通过学习的html,我们可以吧每个元素看成一个盒子不同的盒子填充不同的背景图片。
image.png
第二个问题:这些东西都是手动的写死吗?那怎么让人物走动?
这个肯定不会写死的,我可以把它一张地图,首先这幅图他是2维的可以借助我们的二维数组把这张图表达出来如下

[
	[0,0,1,1,1,1,1,0,0],
	[0,0,1,0,5,0,1,0,0],
	[0,0,1,0,3,0,1,0,0],
	[1,1,1,0,2,0,1,1,1],
	[1,0,0,0,4,0,0,0,1],
	[1,0,4,4,4,4,4,0,1],
	[1,0,0,0,4,0,0,0,1],
	[1,1,0,3,4,3,0,1,1],
	[0,1,0,0,2,0,0,1,0],
	[0,1,0,0,4,0,0,1,0],
	[0,1,0,0,2,0,0,1,0],
	[0,1,1,1,1,1,1,1,0]
]
//	0	代表	空白
//	1	代表	围墙
//	2	代表	箱子要摆放的位置
//	3	代表	箱子
//	4	代表	箱子摆放进位置
//	5	代表	人物

围墙箱子箱子摆放进位置人物
把对应的元素表达成对应的值,通过JS遍历数组生成对应的元素。移动人物通过JS监听键盘事件调整人物在数组中的位置,在刷新界面做到人物移动。
首先写HTML用于游戏的界面

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>推箱子</title>
    <style>
      .box{
	/*让游戏区域进行居中*/
	margin: 0 auto;
      }
      .box>div{
	/*让内置的元素进行浮动*/
	float: left;
	/*背景图片不进行平铺*/
	background-repeat: no-repeat;
	/*背景100%填充*/
	background-size: 100%;
      }
    </style>
  </head>
  <body>
    <!--  box用于存放所有的游戏元素 -->
    <div class="box" id="box"></div>
  </body>
  <script>
    //游戏地图
    //第一关
    var map1= [
      [0,0,1,1,1,1,1,0,0],
      [0,0,1,0,5,0,1,0,0],
      [0,0,1,0,3,0,1,0,0],
      [1,1,1,0,2,0,1,1,1],
      [1,0,0,0,4,0,0,0,1],
      [1,0,4,4,4,4,4,0,1],
      [1,0,0,0,4,0,0,0,1],
      [1,1,0,3,4,3,0,1,1],
      [0,1,0,0,2,0,0,1,0],
      [0,1,0,0,4,0,0,1,0],
      [0,1,0,0,2,0,0,1,0],
      [0,1,1,1,1,1,1,1,0]
    ];
    //第二关
    var map2 = [
      [0,0,0,0,0,0,1,1,1,1,1,1,1,1,1],
      [0,0,0,0,0,0,1,0,0,0,0,0,0,0,1],
      [0,0,0,0,0,0,1,0,1,0,1,0,1,0,1],
      [0,0,0,0,0,0,1,0,0,3,0,3,1,0,1],
      [1,1,1,1,1,1,1,0,0,0,3,0,0,0,1],
      [1,2,2,1,0,0,1,1,0,3,0,3,1,0,1],
      [1,2,2,0,0,0,1,1,0,3,0,3,0,0,1],
      [1,2,2,1,0,0,1,1,0,1,1,1,1,1,1],
      [1,2,2,1,0,1,0,3,0,3,0,1,0,0,0],
      [1,2,2,0,0,0,0,0,3,0,0,1,0,0,0],
      [1,0,0,1,1,1,5,0,0,1,1,1,0,0,0],
      [1,1,1,1,0,1,1,1,1,1,0,0,0,0,0]
    ];
    var maps = [map1,map2];
  </script>
  <script>
    //游戏公共数据
    //人物位置记录
    var personX = 0;
    var personY = 0;
    //人物位置原始元素记录
    var elPerson = 0;
    //每个小盒子的宽高
    const wh = 50;
    //当前游戏关卡
    var level = 1;
    //当前游戏地图  拷贝一张游戏地图
    var thisMap = maps[level-1].slice();
	
    //初始化
    function init(){
      //获得人物位置	
      getPersonPos(thisMap);
      //根据地图创建游戏元素
      createMap(thisMap);
    }
    //获取人物位置
    function getPersonPos(gmap){
      if(gmap != null && gmap.length>0){
        //遍历行		i = X轴
	for(var i=0; i<gmap.length; i++){
	  //遍历列		j = Y轴
	  for(var j=0; j<gmap[i].length; j++){
	    //找到人物所在的位置
	    if(gmap[i][j] === 5){
		personX = i;
		personY = j;
	    }
	  }
	}
      }else{
	console.log("地图数据有误");
	return;
      }
    }
    //设置游戏区域的宽高
    function setBoxWH(gmap,box){
      if(gmap != null && gmap.length>0){
	var heigth = 0;
	var width = 0;
	//计算游戏区域的高度	行数*小盒子的高度
	height = gmap.length * wh +"px";
	//计算游戏区域的宽度	列数*小盒子的宽度
	width = gmap[0].length * wh +"px";
	//设置游戏区域盒子的宽度
	box.style.width = width;
	//设置游戏区域盒子的高度
	box.style.height = height;
      }else{
	console.log("地图数据有误");
	return;
      }
    }
    //根据地图创建游戏元素
    function createMap(gmap){
      //获取游戏区域的盒子
      var box = document.getElementById("box");
      //设置游戏区域的宽高
      setBoxWH(gmap,box);
      //内容清空
      box.innerHTML = "";
      //遍历地图
      //遍历行
      for(var i=0; i<gmap.length; i++){
	//遍历列
	for(var j=0; j<gmap[i].length; j++){
	  //根据对应的值创建元素
	  var div = createMinBox(gmap[i][j]);
	  //创建的小盒子追加到游戏区域内
	  box.appendChild(div)
	}
      }
    }
    //根据对应的值创建元素
    function createMinBox(num){
      //创建一个div元素
      var div = document.createElement("div");
      //给元素设置宽高
      div.style.width = wh+"px";
      div.style.height = wh+"px";
      switch(num){
	case 0:
	  //空白
	  div.style.backgroundColor = "rgba(255,255,255,0)";
	  break;
	case 1:
	  //围墙
	  div.style.backgroundImage = "url(http://ctlyt.yunypan.cn/upload/2020/1/wall-cb47e1971faf4149a6a2cb386fcf0fdf.jpg)";
	  break;
	case 2:
	  //空位
	  div.style.backgroundColor = "pink";
	  div.style.borderRadius ="50%";
	  break;
 	case 3:
	  //箱子
	  div.style.backgroundImage = "url(http://ctlyt.yunypan.cn/upload/2020/1/box-5107e6bd0a6747909422233f4c52964b.png)";
	  break;
	case 4:
	  //占位
	  div.style.backgroundImage = "url(http://ctlyt.yunypan.cn/upload/2020/1/over_box-16d17fc5293548faa78bdafd25f3659b.png)";
	  break;
	case 5:
	  //人物
	  div.style.backgroundImage = "url(http://ctlyt.yunypan.cn/upload/2020/1/player-7f6311fad8784728846bab1aacf0dc13.png)";
	  break;
	}
      return div;
    }
    //判断游戏是否结束
    function judge(gmap){
      //遍历游戏地图
      for(let i=0; i<gmap.length; i++){
	for(let j=0; j<gmap[i].length; j++){
	  //如果有空位返回假
	  if(gmap[i][j] === 3){
	    return false;
	  }
	}
      }
      //没有空位返回真
      return true;
    }
    //移动人物
    function movePerson(gmap,dir){
      switch(dir){
	case "left":
	  //左
	  //判断是否可以向左移动 游戏地图,第一格坐标,第二格坐标
	  if(moveJudge(gmap,personX,personY-1,personX,personY-2)){
	    //可以向左移动
	    personY--;
	  }
	  break;
	case "right":
	  //右
	  //判断是否可以向右移动 游戏地图,第一格坐标,第二格坐标
	  if(moveJudge(gmap,personX,personY+1, personX, personY+2)){
	    //可以向右移动
	    personY++;
	  }
	  break;
	case "up":
	  //上
	  //判断是否可以向上移动
	  if(moveJudge(gmap,personX-1,personY,personX-2,personY)){
	    //可以移动
	    personX--;
	  }
	  break;
	case "down":
	  //下
	  //判断是否可以向下移动 游戏地图,下一格坐标,第二格坐标
	  if(moveJudge(gmap,personX+1, personY, personX+2, personY)){
	    //可以向下移动
	    personX++;
	  }
	  break;
      }
    }
    //移动判断
    function moveJudge(gmap,x,y,x1,y1){
      //移动的方向第一个是否是障碍物  或 
      //第一个是箱子 或者 第一个是到位的箱子 
      //并且 第二个不是空 或 第二个不是空位
      if(gmap[x][y] === 1 ||
	  (gmap[x][y]=== 3 || gmap[x][y] === 4)&&
	  (gmap[x1][y1] != 0 && gmap[x1][y1] != 2)
	){
	return false;
      }else{
	//人物可以移动
	if(gmap[x][y]==0){
	  //如果第一个是空白
	  //第一格等于人物
	  gmap[x][y] = 5;
	  //前人物位置放回前元素内容
	  gmap[personX][personY] = elPerson;
	  //记录当前人物元素内容
	  elPerson = 0;
	}else if(gmap[x][y]==2){
	  //如果第一个是箱子要摆放的位置
	  //第一格等于人物
	  gmap[x][y] = 5;
	  //前人物位置放回前元素内容
	  gmap[personX][personY] = elPerson;
	  //记录当前人物元素内容
	  elPerson = 2;
	}else if(gmap[x][y]==3){
	  //如过第一个是箱子
	  //如果第二个是箱子要摆放的位置
	  if(gmap[x1][y1]==2){
	    gmap[x1][y1] = 4
	  }else{
	    gmap[x1][y1] = 3;	
	  }
	  //第一格等于人物
	  gmap[x][y] = 5;
	  //前人物位置放回前元素内容
	  gmap[personX][personY] = elPerson;
	  //记录当前人物元素内容
	  elPerson = 0;
        }else if(gmap[x][y]==4){
	  //如果第一格是归为的箱子
	  if(gmap[x1][y1]==0){
	    gmap[x1][y1] = 3;
	  }else{
	    gmap[x1][y1] = 4; 
	  }
	  //第一格等于人物
	  gmap[x][y] = 5;
	  //前人物位置放回前元素内容
	  gmap[personX][personY] = elPerson;
	  //记录当前人物元素内容
	  elPerson = 2;
	}
	return true;
      }
    }
    window.onload = function(){
      //初始化
      init();
			
      //监听键盘事件
      document.onkeydown = function(e){
	switch(e.keyCode){
	  case 65:
	  case 37:
	    //左键按下
	    movePerson(thisMap,"left");
            break;
	  case 68:
	  case 39:
    	    //右键按下
	    movePerson(thisMap,"right");
	    break;
	  case 87:
	  case 38:
	    //上键按下
	    movePerson(thisMap,"up")
	    break;
	  case 83:
	  case 40:
	    //下键按下
	    movePerson(thisMap,"down")
	    break;
        }
        //刷新游戏地图
        createMap(thisMap);
        setTimeout(function(){
          //判断游戏是否结束
          if(judge(thisMap)){
	    if(level < maps.length){
	      alert("恭喜闯过第"+level+"关");
	      thisMap = maps[level++].slice();
	      init();
	    }else{
	      alert("恭喜通关");
	    }
          }
        },500)
      }
    }
  </script>
</html>

至此大功告成
附上文件:http://ctlyt.yunypan.cn/upload/2020/1/game-ce148444ca584e7b8853861db632cdfc-7ea28c9f307446918faffdf1e489811d.html

评论