在2D中显示迷宫游戏服务的单元格

时间:2016-08-07 03:10:12

标签: javascript html css html5 graphics

我正在为2D迷宫游戏创建Web API。我有一个带有两个Get方法的服务 - 一个用于检索所有单元格,另一个用于检索特定单元格详细信息(带有下一个可能的移动链接)。

将按以下格式为请求http://localhost:51910/api/cells检索单元格列表。

<Cell>
  <BottomIsWall>true</BottomIsWall>
  <IsExtCell>false</IsExtCell>
  <IsStartCell>false</IsStartCell>
  <LeftIsWall>true</LeftIsWall>
  <RelativeName>Self</RelativeName>
  <RightIsWall>false</RightIsWall>
  <TopIsWall>false</TopIsWall>
  <XVal>0</XVal>
  <YVal>0</YVal>
</Cell>
<Cell>
  <BottomIsWall>false</BottomIsWall>
  <IsExtCell>false</IsExtCell>
  <IsStartCell>true</IsStartCell>
  <LeftIsWall>false</LeftIsWall>
  <RelativeName>Self</RelativeName>
  <RightIsWall>false</RightIsWall>
  <TopIsWall>true</TopIsWall>
  <XVal>1</XVal>
  <YVal>0</YVal>
</Cell>

特定小区请求的响应如下(对于请求http://localhost:51910/api/cells/21,当使用接受标头application/hal+xml时)。如果允许在该方向上进行导航,则会添加链接(向上,向右,向下和向左)。

<?xml version="1.0" encoding="utf-8"?>
<resource rel="self" href="~/api/cells/21">
    <link rel="down" href="~/api/cells/20" />
    <link rel="left" href="~/api/cells/11" />
    <link rel="up" href="~/api/cells/22" />
</resource>

用户可以单击可用链接以导航到下一个单元格。在每个响应中,我需要在2D笛卡尔图中显示所有单元格,用户当前位置。我搜索了有助于显示单元格(带门/墙)的代码 - 但我找不到一个。

我发现很多教程都有代码和算法来生成迷宫。我不必生成迷宫。我已经定义并提供了迷宫。我需要绘制它以供用户查看。

实现此显示的最简单方法是什么?

enter image description here

注意:我需要根据服务返回的单元格使用javascript应用css样式。它可以是任何4X4迷宫。

1 个答案:

答案 0 :(得分:1)

看起来有点蹩脚,但这与未优化的选择ad-hoc spritemap有很大关系。您应该能够根据数据为单元格分配类。当然,包含结构可以很容易地成为div。

<强>更新 我更新了这个答案,以驱逐所提供的数据。

有很多方法可以优化这一点,这只是快速而肮脏的事情,为您提供前进的方法。

例如,根据您的数据结构,使用xpath可能与将xml转换为JSON一样简单。此外,人们可能会在房间墙壁顶部对门图像进行z索引,而不是像我一样挑选出16个房间中的一个。

&#13;
&#13;
// --------------------------------
// Maze data from service.
// --------------------------------
var xmlString = "<root><Cell><BottomIsWall>true</BottomIsWall><IsExtCell>false</IsExtCell><IsStartCell>false</IsStartCell><LeftIsWall>true</LeftIsWall><RelativeName>Self</RelativeName><RightIsWall>false</RightIsWall><TopIsWall>false</TopIsWall><XVal>0</XVal><YVal>0</YVal></Cell><Cell><BottomIsWall>false</BottomIsWall><IsExtCell>false</IsExtCell><IsStartCell>true</IsStartCell><LeftIsWall>false</LeftIsWall><RelativeName>Self</RelativeName><RightIsWall>false</RightIsWall><TopIsWall>true</TopIsWall><XVal>1</XVal><YVal>0</YVal></Cell></root>";
// --------------------------------

// --------------------------------
// Convert the XML text to JSON
// --------------------------------
var data = (function(xmlString){
    // --------------------------------
    // Changes XML to JSON
    // see: https://davidwalsh.name/convert-xml-json
    // --------------------------------
    function xmlToJson(xml) {
        // Create the return object
        var obj = {};

        if (xml.nodeType == 1) { // element
            // do attributes
            if (xml.attributes.length > 0) {
            obj["@attributes"] = {};
                for (var j = 0; j < xml.attributes.length; j++) {
                    var attribute = xml.attributes.item(j);
                    obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
                }
            }
        } else if (xml.nodeType == 3) { // text
            obj = xml.nodeValue;
        }

        // do children
        if (xml.hasChildNodes()) {
            for(var i = 0; i < xml.childNodes.length; i++) {
                var item = xml.childNodes.item(i);
                var nodeName = item.nodeName;
                if (typeof(obj[nodeName]) == "undefined") {
                    obj[nodeName] = xmlToJson(item);
                } else {
                    if (typeof(obj[nodeName].push) == "undefined") {
                        var old = obj[nodeName];
                        obj[nodeName] = [];
                        obj[nodeName].push(old);
                    }
                    obj[nodeName].push(xmlToJson(item));
                }
            }
        }
        return obj;
    };
    // --------------------------------
  
    var _parser = new window.DOMParser();
    var xmlData = _parser.parseFromString(xmlString, "text/xml");

    return xmlToJson(xmlData);
})(xmlString);
// --------------------------------

// --------------------------------
// For each TD in the maze, find the service data and
// set the room look.
// --------------------------------
Array.from(document.querySelectorAll("tr")).forEach(function(row, rowIndex){
  Array.from(row.querySelectorAll("td")).forEach(function(col, colIndex){

    // ---------------------
    // Find the data element for this cell
    // ---------------------
    var cellData = data.root.Cell.filter(function(data){
      var isRowMatch = data.YVal["#text"] == (3 - rowIndex);
      var isColMatch = data.XVal["#text"] == colIndex;
      return (isRowMatch && isColMatch);
    });
    // ---------------------
    
    var cellType = "cell-00";
    var cellRotation = "cell-south";

    // ---------------------
    // if there is some issue with the data set the cell to the void
    // ---------------------
    if(cellData.length !== 1) {
      col.classList.add(cellType);
      col.classList.add(cellRotation);
      return;
    }
    // ---------------------
    
    // ---------------------
    // Where are the doors?
    // ---------------------
    var isDoor_North = cellData[0].TopIsWall["#text"] === "false";
    var isDoor_East = cellData[0].RightIsWall["#text"] === "false";
    var isDoor_South = cellData[0].BottomIsWall["#text"] === "false";
    var isDoor_West = cellData[0].LeftIsWall["#text"] === "false";
    // ---------------------

    // ---------------------
    // Determine the classes based on where the doors are
    // ---------------------
    switch(true) {
        case (isDoor_North && isDoor_East && isDoor_South && isDoor_West):
          break;
        case (isDoor_North && isDoor_East && isDoor_South && !isDoor_West):
          break;
        case (isDoor_North && isDoor_East && !isDoor_South && isDoor_West):
          break;
        case (isDoor_North && isDoor_East && !isDoor_South && !isDoor_West):
          cellType = "cell-03";
          cellRotation = "cell-west";
          break;
        case (isDoor_North && !isDoor_East && isDoor_South && isDoor_West):
          break;
        case (isDoor_North && !isDoor_East && isDoor_South && !isDoor_West):
          break;
        case (isDoor_North && !isDoor_East && !isDoor_South && isDoor_West):
          break;
        case (isDoor_North && !isDoor_East && !isDoor_South && !isDoor_West):
          break;
        case (!isDoor_North && isDoor_East && isDoor_South && isDoor_West):
          cellType = "cell-04";
          cellRotation = "cell-east";
          break;
        case (!isDoor_North && isDoor_East && isDoor_South && !isDoor_West):
          break;
        case (!isDoor_North && isDoor_East && !isDoor_South && isDoor_West):
          break;
        case (!isDoor_North && isDoor_East && !isDoor_South && !isDoor_West):
          break;
        case (!isDoor_North && !isDoor_East && isDoor_South && isDoor_West):
          break;
        case (!isDoor_North && !isDoor_East && isDoor_South && !isDoor_West):
          break;
        case (!isDoor_North && !isDoor_East && !isDoor_South && isDoor_West):
          break;
        case (!isDoor_North && !isDoor_East && !isDoor_South && !isDoor_West):
          break;
    }
    // ---------------------

    // ---------------------
    // Assign the proper classes based on our data.
    // ---------------------
    col.classList.add(cellType);
    col.classList.add(cellRotation);
    // ---------------------

  });
});
// ---------------------
&#13;
.cell {
  height: 36px;
  width: 36px;
  padding: 0;
  margin: 0;
  border: 0;
  background-repeat: no-repeat;
  background-image: url(http://img.photobucket.com/albums/v323/ShadowDragon8685/KestralDefiant_zps88896fb8.png);
}

.cell-00 { background-position: -0px -15px; }
.cell-01 { background-position: -115px -138px; }
.cell-02 { background-position: -44px -173px; }
.cell-03 { background-position: -254px -103px; }
.cell-04 { background-position: -254px -278px; }

.cell-north { transform: rotate(180deg); }
.cell-east { transform: rotate(90deg); }
.cell-south { transform: rotate(0deg); }
.cell-west { transform: rotate(270deg); }
&#13;
<table style="border-collapse: collapse">
  <tr><td class="cell"></td><td class="cell"></td><td class="cell"></td><td class="cell"></td></tr>
  <tr><td class="cell"></td><td class="cell"></td><td class="cell"></td><td class="cell"></td></tr>
  <tr><td class="cell"></td><td class="cell"></td><td class="cell"></td><td class="cell"></td></tr>
  <tr><td class="cell"></td><td class="cell"></td><td class="cell"></td><td class="cell"></td></tr>
</table>
&#13;
&#13;
&#13;