private static bool OutOfBounds(IntVector roomIndex, MapController.Map map) { int x = roomIndex.x; int y = roomIndex.y; return(x < 0 || y < 0 || x >= map.size.x || y >= map.size.y); }
public void Generate(MapController.Map map) { rt.sizeDelta = new Vector2(map.size.x * roomSize, map.size.y * roomSize); rt.anchoredPosition = Vector3.zero; rt.pivot = new Vector2(.5f, .5f); Vector2 shiftVector = new Vector2((-rt.sizeDelta.x + roomSize) / 2, (rt.sizeDelta.y - roomSize) / 2); rt.localScale = new Vector3(Mathf.Min(1, 4.0f / map.size.x), Mathf.Min(1, 4.0f / map.size.y), 1); for (int i = transform.childCount - 1; i >= 0; i--) { Destroy(transform.GetChild(i)); } rooms = new GameObject[map.size.x][]; for (int i = 0; i < map.size.x; i++) { rooms[i] = new GameObject[map.size.y]; for (int j = 0; j < map.size.y; j++) { if (map.rooms[i][j].active) { rooms[i][j] = (GameObject)Instantiate(room); rooms[i][j].transform.SetParent(transform); rooms[i][j].transform.localPosition = new Vector2(i * 80, -j * 80) + shiftVector; rooms[i][j].transform.localScale = new Vector2(1, 1); if (!map.rooms[i][j].up) { Destroy(rooms[i][j].transform.Find("Up Door").gameObject); } if (!map.rooms[i][j].down) { Destroy(rooms[i][j].transform.Find("Down Door").gameObject); } if (!map.rooms[i][j].left) { Destroy(rooms[i][j].transform.Find("Left Door").gameObject); } if (!map.rooms[i][j].right) { Destroy(rooms[i][j].transform.Find("Right Door").gameObject); } int index = j + map.size.y * i; Button b = rooms[i][j].GetComponent <Button>(); b.onClick.AddListener(() => { ((MapController)MapController.Instance).SetRoom(index); } ); rooms[i][j].SetActive(map.start.Equals(new IntVector(i, j))); } if (map.end.Equals(new IntVector(i, j))) { endMarker = (GameObject)Instantiate(endpointPrefab); endMarker.transform.SetParent(transform); endMarker.transform.localPosition = rooms[i][j].transform.localPosition; endMarker.transform.localScale = new Vector3(1, 1, 1); } } } playerMarker = (GameObject)Instantiate(playerLocPrefab); playerMarker.transform.SetParent(transform); playerMarker.transform.localPosition = rooms[map.start.x][map.start.y].transform.localPosition; playerMarker.transform.localScale = new Vector3(1, 1, 1); }
public static MapController.Map RandomMap(int width, int height, int difficulty, float loadFactor) { MapController.Map map = new MapController.Map(); map.difficulty = difficulty; map.size = new IntVector(width, height); map.rooms = new MapController.Room[width][]; for (int i = 0; i < width; i++) { map.rooms[i] = new MapController.Room[height]; } int roomCount = 1; //generation starting room IntVector genStart = new IntVector(Random.Range(0, width), Random.Range(0, height)); map.rooms[genStart.x][genStart.y] = RandomRoom(difficulty); Queue <IntVector> queue = new Queue <IntVector>(); queue.Enqueue(genStart); // Debug.Log("Start generation at: (" + map.start.x + ", " + map.start.y + ")"); while (queue.Count > 0) { if (1.0f * roomCount >= loadFactor * width * height) { break; } IntVector currentRoom = queue.Dequeue(); int x = currentRoom.x; int y = currentRoom.y; int availableDirections = 0; for (int i = -1; i <= 1; i++) { for (int j = i * i - 1; j <= 1; j += 2) { if (!OutOfBounds(new IntVector(x + i, y + j), map) && !map.rooms[x + i][y + j].active) { availableDirections++; } } } float[] thresholds = new float[availableDirections]; for (int i = 0; i < availableDirections; i++) { thresholds[i] = 1 - 0.25f * i; } // Randomly distribute thresholds among available directions for (int i = 0; i < availableDirections; i++) { float temp = thresholds[i]; int randomIndex = Random.Range(i, availableDirections); thresholds[i] = thresholds[randomIndex]; thresholds[randomIndex] = temp; } int thresholdIndex = 0; // Loops through four directions (i, j) for (int i = -1; i <= 1; i++) { for (int j = i * i - 1; j <= 1; j += 2) { if (OutOfBounds(new IntVector(x + i, y + j), map) || map.rooms[x + i][y + j].active) { continue; } // string dir = (i == 0) ? ((j == -1) ? "up" : "down") : ((i == -1) ? "left" : "right"); // Debug.Log(dir + " " + thresholds[thresholdIndex]); if (Random.value > thresholds[thresholdIndex++]) { continue; } // Debug.Log("got through"); bool intersect = false; if (i == 0 && j == -1) { map.rooms[x][y].up = true; } else if (i == 0 && j == 1) { map.rooms[x][y].down = true; } else if (i == -1 && j == 0) { map.rooms[x][y].left = true; } else if (i == 1 && j == 0) { map.rooms[x][y].right = true; } int distance = WeightedDistance((j == 0) ? width : height); // Check for edge at (x + i * distance, y + j * distance); if edge, shrink distance until inside the grid for (int k = distance; k > 0; k--) { if (!OutOfBounds(new IntVector(x + i * k, y + j * k), map)) { distance = k; break; } } // Debug.Log("distance: " + distance); // Activate Corridors for (int k = 1; k < distance; k++) { if (map.rooms[x + i * k][y + j * k].active) { intersect = true; } else { map.rooms[x + i * k][y + j * k] = RandomRoom(difficulty); roomCount++; } if (i == 0) { map.rooms[x + i * k][y + j * k].up = true; map.rooms[x + i * k][y + j * k].down = true; } else { map.rooms[x + i * k][y + j * k].left = true; map.rooms[x + i * k][y + j * k].right = true; } } // Activate endpoint and add to queue if (map.rooms[x + i * distance][y + j * distance].active) { intersect = true; } else { map.rooms[x + i * distance][y + j * distance] = RandomRoom(difficulty); roomCount++; } if (i == 0 && j == -1) { map.rooms[x + i * distance][y + j * distance].down = true; } else if (i == 0 && j == 1) { map.rooms[x + i * distance][y + j * distance].up = true; } else if (i == -1 && j == 0) { map.rooms[x + i * distance][y + j * distance].right = true; } else if (i == 1 && j == 0) { map.rooms[x + i * distance][y + j * distance].left = true; } if (!intersect) { IntVector endpoint = new IntVector(x + i * distance, y + j * distance); // Debug.Log("Enqueuing: " + endpoint.ToString()); queue.Enqueue(endpoint); } } } } // End while loop // Find start point queue.Clear(); queue.Enqueue(genStart); List <IntVector> visited = new List <IntVector>(); IntVector latest = null; while (queue.Count > 0) { IntVector latestRoom = queue.Dequeue(); if (visited.Contains(latestRoom)) { continue; } visited.Add(latestRoom); latest = latestRoom; int x = latestRoom.x; int y = latestRoom.y; if (map.rooms[x][y].up) { queue.Enqueue(new IntVector(x, y - 1)); } if (map.rooms[x][y].down) { queue.Enqueue(new IntVector(x, y + 1)); } if (map.rooms[x][y].left) { queue.Enqueue(new IntVector(x - 1, y)); } if (map.rooms[x][y].right) { queue.Enqueue(new IntVector(x + 1, y)); } } map.start = latest; // Debug.Log("Starts at " + map.start.ToString()); // Find endpoint queue.Clear(); visited.Clear(); queue.Enqueue(map.start); while (queue.Count > 0) { IntVector latestRoom = queue.Dequeue(); if (visited.Contains(latestRoom)) { continue; } visited.Add(latestRoom); latest = latestRoom; int x = latestRoom.x; int y = latestRoom.y; if (map.rooms[x][y].up) { queue.Enqueue(new IntVector(x, y - 1)); } if (map.rooms[x][y].down) { queue.Enqueue(new IntVector(x, y + 1)); } if (map.rooms[x][y].left) { queue.Enqueue(new IntVector(x - 1, y)); } if (map.rooms[x][y].right) { queue.Enqueue(new IntVector(x + 1, y)); } } map.end = latest; // Debug.Log("Ends at " + map.end.ToString()); // Debug.Log("Room count: " + roomCount); /* map preview * string mapgen = ""; * for (int j = 0; j < height; j++) * { * string str1 = ""; * string str2 = ""; * for (int i = 0; i < width; i++) * { * string strP = "O"; * if (map.start.Equals(new IntVector(i, j))) * strP = "S"; * else if (map.end.Equals(new IntVector(i, j))) * strP = "E"; * str1 = str1 + (map.rooms[i][j].active ? strP : " ") + (map.rooms[i][j].right ? "--" : " "); * str2 = str2 + (map.rooms[i][j].down ? "|" : " ") + " "; * } * mapgen = mapgen + "\n" + str1 + "\n" + str2; * } * Debug.Log(mapgen); */ return(map); }