Zawęziłem błąd w moim programie do następujących.

Następująca pętla działa tak długo, jak długo maxlayout jest równe 1, ale jeśli jest równe dwa, dzięki czemu pętla jest uruchamiana dwukrotnie, a oryginalne wartości są kasowane.

Więc jeśli pętla zostanie uruchomiona raz, to mainArray.tilef0 będzie równe tile.empty, ale jeśli tan dwukrotnie, to mainArray.tilef0 będzie niezdefiniowane, a mainArray.tilef1 będzie równe tile.empty

To samo dotyczy pozostałych właściwości, takich jak teren i bryła.

for (var k = 0; k < maxlayout; k++){
       mainArray[i][j] = {
          ['tilef' + k]: tile.empty,
          ['terrainf' + k]: "empty",
          ['solidf' + k]: "false",
        };

Barmar i Henery Odpowiedzieli na moje pytanie, ale pomyślałem, że dodam cały kod poniżej. Aby oni lub inni mogli zobaczyć, jak to pomogło i / lub pomogło mi lub innym zobaczyć, czy istnieje lepszy sposób, na przykład zainicjowanie tablicy przed punktem, w którym potrzebowałem pomocy.

Poniżej znajduje się działająca wersja z kodem, w którym mi pomagali.

Przepraszam, jeśli jest bałagan, mam problem z utrzymaniem czystości kodu i nie znam wszystkich standardowych sposobów robienia rzeczy. Ale dodałem wiele komentarzy.

function gameloop() {                           // Entire Game contained withing function
  var mainArray = [];                           // most game data will be held withing the array
  var mapSizeX = 32;                            // sets the height of the rendered map and corresponding array coordinates
  var mapSizeY = 128;                           // sets the width
  var idPos = {x: 16, y: 64};                   // currently used to set player location and check for collisions
  var rendFlr = 0;                              // sets which floor to render
  var maxlayout = 3;
  
  
  var tile = {                                  // lists charcters used for rendered tiles and objects
    player: "☺",
    empty: ".",
    wall: "#",
    oak: "♠",
    maple: "♣",
    grass: "‚",
    tallgrass: "„"
    
  };

  function initMap(mapSizeX, mapSizeY) {        // expands and populates the array
    for (var i = 0; i < mapSizeX; i++) {
      mainArray.push([])                        // I belive this is only expaning it 2 dimesionaly and matching the height

      for (var j = 0; j < mapSizeY; j++) {
            for (var k = 0; k < maxlayout; k++){
                const obj = mainArray[i][j] || {};   // creates on object to alter and add back into the main array    
                obj['tilef' + k] = tile.empty;
                obj['terrainf' + k] = "empty";
                obj['solidf' + k] = "false";
                mainArray[i][j] = obj;
                
                if(k > 0){
                    if (j == 0 ||                           // wraps the underground floor 1 in walls
                        j == mapSizeY - 1 ||
                        i == 0 ||
                        i == mapSizeX - 1) {
                        mainArray[i][j]['tilef' + k] = tile.wall;
                        mainArray[i][j]['terrainf' + k] = "wall";
                        mainArray[i][j]['solidf' + k] = "Wall";
                        }
                }
                
            }
        
        //else{                                 // un need as the above for j is already creating empties
            //mainArray[i][j].terrain = "empty";
            //mainArray[i][j].solid = "false";
        //}
      }
    }
  }
  
  function getRndInteger(min, max) {                            // returns random number from min to max number appears to not function predictably if min and max are the same number
    return Math.floor(Math.random() * (max - min + 1) ) + min;
  }
  
  function randAdd(odds,feature,solid) {                        // A chance to add named feature and solid type or message if the "odds" or max number provided is rolled.
    for (var i = 0; i < mapSizeX; i++) {
        for (var j = 0; j < mapSizeY; j++) {
            if (mainArray[i][j].terrainf0 === "empty") {
             roll = getRndInteger(1,odds);
                if(roll === odds){
                    mainArray[i][j].terrainf0 = feature;
                    mainArray[i][j].tilef0 = tile[feature];
                    mainArray[i][j].solidf0 = solid;   
                }     
            }
        }
    }
  }
  
  function randAdd1(odds,feature,solid) {                      // Same as above function but for floor 1 and should eventually be merged into a single function
    for (var i = 0; i < mapSizeX; i++) {
        for (var j = 0; j < mapSizeY; j++) {
            if (mainArray[i][j].terrainf0 === "empty") {
             roll = getRndInteger(1,odds);
                if(roll === odds){
                    mainArray[i][j].terrainf1 = feature;
                    mainArray[i][j].tilef1 = tile[feature];
                    mainArray[i][j].solidf1 = solid;   
                }     
            }
        }
    }
  }

  function genMaps(){
    randAdd(200,"wall","solid rock");
    randAdd(100,"oak","a tree");
    randAdd(100,"maple","a tree");
    randAdd(2,"grass","False");
    randAdd(2,"tallgrass","False");
    randAdd1(1,"wall","solid rock");
  }

  function nl() {                                           // Creates a new line in the rendered text
    GameScreen.innerText += "\n";
  }

  function render(flr) {                                       // displays the array tiles to the browser
    GameScreen.innerText = mainArray.map(arr => arr.map(cell => cell['tilef' + flr]).join("")).join("\n");
    nl();
    nl();
  }


  function reposition(xChange, yChange, strA) {             // checks if target position is not blocked and if not moves the player 
    if (mainArray[idPos.x + xChange][idPos.y + yChange].solidf0 === "false" || 
        mainArray[idPos.x + xChange][idPos.y + yChange].solidf0 === "False" ||
        mainArray[idPos.x + xChange][idPos.y + yChange].solidf0 === "") {
      mainArray[idPos.x][idPos.y].tilef0 = tile[mainArray[idPos.x][idPos.y].terrainf0];
      idPos.x = idPos.x + xChange;
      idPos.y = idPos.y + yChange;
      mainArray[idPos.x][idPos.y].tilef0 = tile.player;
      GameLog.innerText = "You take a step to the " + strA 
    } 
    else {
      GameLog.innerText = "You can not enter " + mainArray[idPos.x + xChange][idPos.y + yChange].solidf0;
    }
    mainArray[idPos.x][idPos.y].terrainf0 != "empty" ?
        GameLog.innerText += "\n There is " + mainArray[idPos.x][idPos.y].terrainf0 + " in this spot" : 
        GameLog.innerText += "\n There is nothing in this spot";
    
    render(rendFlr);
  }

  //Startup
  initMap(32, 128);
  genMaps();
  mainArray[idPos.x][idPos.y].tilef0 = tile.player;
  //First Render
  render(rendFlr);

  document.addEventListener('keydown', function(event) {
    if (event.keyCode === 38) {
      reposition(-1, 0, "North");
    }
    if (event.keyCode === 40) {
      reposition(1, 0, "South");
    }
    if (event.keyCode === 37) {
      reposition(0, -1, "West");
    }
    if (event.keyCode === 39) {
      reposition(0, 1, "East");
    }
    if (event.keyCode === 190) {
        if(rendFlr < maxlayout) {rendFlr++}
      render(rendFlr);
    } if (event.keyCode === 188) {
        if(rendFlr > 0) {rendFlr--}
      render(rendFlr);
    }
    //alert(event.keyCode);
  });
}



gameloop();
.info {
  color: #7d7d7d;
  font-family: Lucida Console;
}

.info span {
  color: #ABABAB;
  font-family: Lucida Console;
  font-size: 0.5em;
}

#GameScreen{
  color: #000000;
  font-family: Lucida Console;
  font-weight: italic;
  margin-left: auto;
  margin-right: auto;
}
#GameLog {
  color: #000000;
  font-family: Lucida Console;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css">
<meta charset="utf-8">
<title>Dungeon Valley</title>
</head>
<body>
<br>
<p class="info">Dungeon Valley.<br>
  <span class="">
    Taming the Borderlands.<br> v0.008 By heromedel.
  </span>
</p>
<section id="GameScreen"></section>
<section id="GameLog">Arrow Keys to move.<br></section>
    <script src="main.js"></script>
</body>
</html>

Jeśli chcesz to przetestować, polecam uruchomienie fragmentu kodu, a następnie kliknięcie klawiszy strzałek na pełnym ekranie, aby przenieść, i. zmieni, która podłoga jest renderowana.

0
heromedel 5 marzec 2020, 04:08

2 odpowiedzi

Najlepsza odpowiedź

Odpowiedź Barmara identyfikuje problem, ale najprawdopodobniej wystąpi błąd undefined, jeśli mainArray [i] [j] nie zostanie zainicjowany. Więc coś takiego:

for (var k = 0; k < maxlayout; k++){
       const obj = mainArray[i][j] || {};       
       obj['tilef' + k] = tile.empty;
       obj['terrainf' + k] = "empty";
       obj['solidf' + k] = "false";
       mainArray[i][j] = obj;
}

2
Henry Mueller 5 marzec 2020, 01:43

Zamieniasz element tablicy zamiast dodawać do niego nowe właściwości.

for (var k = 0; k < maxlayout; k++){
    mainArray[i][j]['tilef' + k] = tile.empty;
    mainArray[i][j]['terrainf' + k] = "empty";
    mainArray[i][j]['solidf' + k] = "false";
};
1
Barmar 5 marzec 2020, 01:14