2016-03-28 7 views
1

Я изначально использовал 2d-массив из «Плитки» для хранения процедурной сгенерированной карты с ее различным содержимым.Процедурная генерация карты - определение смежных плит

Каждая плитка содержит список, который позволяет каждому отдельному плитку знать, какие вершины ближе всего к нему, касаясь его на 8 разных сторонах (прямо смежные и диагонально смежные).

Общая идея была взята из поколения многоугольных карт Амита, но я попытался упростить ее, используя сетку вместо voronois, однако я столкнулся с большими проблемами, чем я думал изначально. Мое текущее затруднительное положение заключается в том, что вы обнаруживаете смежность, когда я отказываюсь от 2d массивов.

Это, как я делал это перед изменением списка:

private void ConstructAdjacencyList() { 

    // Create Adjacency List 
    for (int x = 0; x < mapWidth; x++) { 
     for (int y = 0; y < mapHeight; y++) { 
      // Bool to find position of point 
      bool omitLeft = false;  bool omitRight = false; 
      bool omitTop = false;  bool omitBottom = false; 
      // Enable bools based on position, reset on each loop    
      if (x == 0) 
       omitLeft = true;     
      else if (x == mapWidth - 1) 
       omitRight = true;    
      if (y == 0) 
       omitTop = true;    
      else if (y == mapHeight - 1) 
       omitBottom = true; 

      // Add entries to list based on bool settings 
      if (!omitLeft) { 
       // Left center 
       islandMap[x,y].adjacent.Add(islandMap[x-1,y]); 
       if (!omitTop) 
        islandMap[x,y].adjacent.Add(islandMap[x-1,y-1]); 
       if (!omitBottom) 
        islandMap[x,y].adjacent.Add(islandMap[x-1,y+1]); 
      } 

      if (!omitTop) // Top Center 
       islandMap[x,y].adjacent.Add(islandMap[x,y-1]); 
      if (!omitBottom) // Bottom Center 
       islandMap[x,y].adjacent.Add(islandMap[x,y+1]); 

      if (!omitRight) { 
       // Right Center 
       islandMap[x,y].adjacent.Add(islandMap[x+1,y]); 
       if (!omitTop) 
        islandMap[x,y].adjacent.Add(islandMap[x+1,y-1]); 
       if (!omitBottom) 
        islandMap[x,y].adjacent.Add(islandMap[x+1,y+1]); 
      }    
     } 
    } // End Adjacency 

    Debug.Log ("Adjacencies Built"); 
} 

х, у значения в настоящее время проводятся в islandMap.point (Вектор 2d хранения х и у значения, сгенерированные следующим образом:)

public MapController() { 
    width = height = (int)Mathf.Sqrt (tileCount); 

    // Lists for points 
    var points = new List<Vector2>(); 

    // Build a random set of points. 
    for (float x = 0; x < width; x++) { 
     for (float y = 0; y < height; y++) { 
      points.Add(new Vector2(x,y)); 
     } 
    } 

    map = new Map (points, width, height, lakeTreshold); 
} 

А сама карта имеет в настоящее время следующие:

public class Map { 
    Func<Vector2, bool> inside; // Contains function to randomly seed area 
    bool needsMoreRandomness; 

    public List<Tile> islandMap; // Previously was Tile[,] islandMap 
    public int mapWidth { get; private set; } // Calculated as Sqrt(totalPoints) 
    public int mapHeight { get; private set; } 

Наряду с другими методами с как метод ConstructAdjacencyList(), в который я сейчас застрял.

Итак, как я могу продолжить создание списка смежных точек, не полагаясь на позиционирование массива? Может ли я временно ссылаться на весь список из массива, размещать ссылки на каждый фрагмент во всем списке в этом массиве 2d, настраивать смежности, а затем удалять массив без потери информации? Я считаю, что он будет использовать только ссылки, так что это должно быть хорошо ... Каждая плитка содержит индекс для сохранения порядка, с которым он был построен, как так:

foreach (var point in points) { 
     var p = new Tile { index = islandMap.Count, point = point }; 
     p.border = point.x == 0 || point.x == mapWidth || point.y == 0 || point.y == mapHeight; 
     islandMap.Add (p); 
     tileLookup[point] = p; 
    } 

Извините, если это слишком долго ... Я просто понял, что он довольно массивный. -0-

+0

Там есть несколько способов решения, но размер вашей карты плитки могут диктовать какие решения более уместны - примерно столько плиток, с которыми вы имеете дело? – Pikalek

+0

Привет, Пикалек, спасибо, что ответили. Я буду смотреть на ввод около 3000 точек, в настоящее время колеблющийся под 300 точками. Одно время вычислительного времени это не так дорого, честно, если это работает. – Ben

+0

Кроме того, я попытался сделать следующее: 'Tile [,] tempArray = new Tile [mapWidth, mapHeight]; \t \t int count = 0; \t \t для (INT х = 0; х Ben

ответ

0

Предполагая, что вы ничего не сделали, чтобы побеседовать с порядком баллов, вы можете лечить 1D list/array as 2D list/array. Примером, который я связал, является C, но язык идеи агностик.

Это, как говорится, при условии, что вы только собираетесь сделать это один раз во время инициализации & учитывая относительно низкое количество баллов, вы можете так же легко перебором его с функцией, которая перебирает список точек & кирки вне соседей по мере необходимости. Моя C# это немного ржавый, но я говорю о чем-то вроде этого:

private List<Vector2> getAdjacenctPointList(List<Vector2> pointsList, Vector2 point){ 
    var adjacencyList = new List<Vector2>(); 
    foreach (var pt in pointList){ 
    var offset = Math.abs(pt.x - point.x) + Math.abs(pt.y - point.y); 
    if(offset > 0 && offset <= 1.0){ 
     adjacencyList.add(pt); 
    } 
    } 
    return adjacencyList; 
} 
+1

Вам не хватает '}' для завершения предложения if. – juunas

+0

Спасибо за ответ, я на самом деле решил это проще, используя ту же основную идею обработки списка как 2d-массива. однако я сделал это буквально как таковой. Я также опубликую свои ответы как ответ. – Ben

0

Окончательный ответ я пошел, с которым было наименьшее количество работы, связанной и позволил мне переработать мой исходный код 2d массив размещен выше было просто построить временный 2d-массив и сохранить в нем все ссылки на него - при необходимости создайте все смежности, а затем удалите (просто потеряв область) 2-го массива.

Вот фактический метод с системой 2d массива на месте. Первые заявления паров следует вложенной цикл все, что потребовалось:

private void ConstructAdjacencyList() { 
    Tile[,] tempArray = new Tile[mapWidth, mapHeight]; 

    int count = 0; 

    // Populate the temp 2D array with list references 
    for (int x = 0; x < mapWidth; x++) { 
     for (int y = 0; y < mapHeight; y++) { 
      tempArray[x,y] = islandMap[count]; 
      count++;    
     } 
    } 

    // Create Adjacency List using our TempArray 
    for (int x = 0; x < mapWidth; x++) { 
     for (int y = 0; y < mapHeight; y++) { 
      // Bool to find position of point 
      bool omitLeft = false;  bool omitRight = false; 
      bool omitTop = false;  bool omitBottom = false; 
      // Enable bools based on position, reset on each loop    
      if (x == 0) 
       omitLeft = true;     
      else if (x == mapWidth - 1) // Optimize with if else to split checks in half. 
       omitRight = true;    
      if (y == 0) 
       omitTop = true;    
      else if (y == mapHeight - 1) 
       omitBottom = true; 

      // Add entries to list based on bool settings 
      if (!omitLeft) { 
       // Left center 
       tempArray[x,y].adjacent.Add(tempArray[x-1,y]); 
       if (!omitTop) 
        tempArray[x,y].adjacent.Add(tempArray[x-1,y-1]); 
       if (!omitBottom) 
        tempArray[x,y].adjacent.Add(tempArray[x-1,y+1]); 
      } 

      if (!omitTop) // Top Center 
       tempArray[x,y].adjacent.Add(tempArray[x,y-1]); 
      if (!omitBottom) // Bottom Center 
       tempArray[x,y].adjacent.Add(tempArray[x,y+1]); 

      if (!omitRight) { 
       // Right Center 
       tempArray[x,y].adjacent.Add(tempArray[x+1,y]); 
       if (!omitTop) 
        tempArray[x,y].adjacent.Add(tempArray[x+1,y-1]); 
       if (!omitBottom) 
        tempArray[x,y].adjacent.Add(tempArray[x+1,y+1]); 
      }    
     } 
    } // End Adjacency 

    Debug.Log ("Adjacencies Built"); 
} 

Чтобы это работало так, как я хотел, чтобы я проверил ее визуально, установив один случайный кубик и протестировал различные точки вокруг области к чтобы не было ошибок и не было.

Конечный результат, как и ожидалось, изображенного ниже:

Element Selection

Спасибо за помощь :)