Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2019
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.30 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using uRandom = UnityEngine.Random;
  5. using UnityEngine.Tilemaps;
  6. using System.Threading;
  7. using System.Linq;
  8. using System;
  9.  
  10. public class GenerateTilemap : MonoBehaviour
  11. {
  12.  
  13. private Tilemap m_Tilemap;
  14. [SerializeField] private TileBase m_Tile;
  15.  
  16. [SerializeField] private Vector2 startEndEmptySpace = new Vector2(10, 5);
  17.  
  18. private int[,] gridArray;
  19. private RoomClass[,] roomMap;
  20.  
  21. /* Level Size Variables */
  22. private const int xMax = 225;
  23. private const int yMax = 125;
  24.  
  25. private const int roomsX = 5;
  26. private const int roomsY = 5;
  27.  
  28. private RelativeNeighbors directions = new RelativeNeighbors();
  29.  
  30. public Player playerPrefab;
  31. public RoomClass roomPrefab;
  32.  
  33. public RoomClass startRoom;
  34. public RoomClass exitRoom;
  35. public Player player;
  36.  
  37. public Camera camera;
  38.  
  39. public Vector2 startTilePos;
  40. public Vector2 endTilePos;
  41.  
  42. public bool[,] visitedRooms;
  43.  
  44. Dictionary<Vector2, Action> roomsPlacementList;
  45.  
  46.  
  47. // Start is called before the first frame update
  48. void Start()
  49. {
  50. roomsPlacementList = new Dictionary<Vector2, Action>();
  51.  
  52. gridArray = GenerateArray(xMax, yMax, true);
  53.  
  54. //player = Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
  55. player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>();
  56. startRoom = Instantiate(roomPrefab, Vector3.zero, Quaternion.identity);
  57. exitRoom = Instantiate(roomPrefab, Vector3.zero, Quaternion.identity);
  58.  
  59. startRoom.SetName("startRoom");
  60. exitRoom.SetName("exitRoom");
  61.  
  62. ChooseStartAndEnd(ref startRoom, ref exitRoom);
  63.  
  64. m_Tilemap = GetComponent<Tilemap>();
  65. camera = GameObject.Find("Main Camera").GetComponent<Camera>();
  66. camera.transform.SetParent(player.transform);
  67. camera.transform.localPosition = new Vector3(0, 0, -1);
  68.  
  69. directions.Up = new Vector2(0, 1);
  70. directions.Down = new Vector2(0, -1);
  71. directions.Left = new Vector2(-1, 0);
  72. directions.Right = new Vector2(1, 0);
  73.  
  74. directions.GetRandomDirection = delegate ()
  75. {
  76.  
  77. int rand = uRandom.Range(0, 3);
  78. Vector2 randD = new Vector2(0, 0);
  79.  
  80. switch (rand)
  81. {
  82. case 0:
  83. randD = this.directions.Up;
  84. break;
  85. case 1:
  86. randD = this.directions.Down;
  87. break;
  88. case 2:
  89. randD = this.directions.Left;
  90. break;
  91. case 3:
  92. randD = this.directions.Right;
  93. break;
  94. default:
  95. break;
  96. }
  97.  
  98. return randD;
  99. };
  100.  
  101. //directions.GetDirectionByIndex = new public delegate Vector2 (int index)
  102. //{
  103. // return Vector2.zero
  104. //}
  105.  
  106. //// Remove tiles based on areas we need cleared
  107. //startRoom.PlaceRoom(ref gridArray);
  108. //exitRoom.PlaceRoom(ref gridArray);
  109.  
  110. //for (int i = 0; i < 10; i++)
  111. //{
  112. // int randSizeX = (int) Mathf.Abs(uRandom.Range(5, 25));
  113. // int randSizeY = (int) Mathf.Abs(uRandom.Range(4, 15));
  114.  
  115. // int randPosX = (int) Mathf.Abs(uRandom.Range(0 + Mathf.Ceil(randSizeX / 2), xMax - Mathf.Ceil(randSizeX / 2)));
  116. // int randPosY = (int)Mathf.Abs(uRandom.Range(0 + Mathf.Ceil(randSizeY / 2), yMax - Mathf.Ceil(randSizeY / 2)));
  117.  
  118. // if (CanPlaceRoom(gridArray, new Vector2(randPosX, randPosY), randSizeX, randSizeY))
  119. // {
  120. // RoomClass newRoom = Instantiate(roomPrefab, Vector3.zero, Quaternion.identity);
  121. // newRoom.SetName("GeneratedRoom"+i);
  122. // newRoom.SetParams(new Vector2(randPosX, randPosY), new Vector2(randSizeX, randSizeY));
  123. // newRoom.UpdateCorners();
  124. // newRoom.SetRoomCorners(newRoom.GetRoomCorners());
  125. // newRoom.setDrawRoom(true);
  126.  
  127. // this.roomsPlacementList.Add(newRoom.GetRoomPos(true), () => {
  128. // newRoom.PlaceRoom(ref gridArray);
  129. // });
  130. // }
  131.  
  132. //}
  133.  
  134. //foreach (Action action in roomsPlacementList.Values)
  135. //{
  136. // action();
  137. //}
  138.  
  139. roomMap = new RoomClass[roomsX, roomsY];
  140.  
  141. for (int x = 0; x <= roomMap.GetUpperBound(0); x++)
  142. {
  143. for (int y = 0; y <= roomMap.GetUpperBound(1); y++)
  144. {
  145. RoomClass newRoom = Instantiate(roomPrefab, Vector3.zero, Quaternion.identity);
  146.  
  147. Vector2 roomSize = new Vector2( (int) Mathf.Floor(xMax / roomsX), (int) Mathf.Floor(yMax / roomsY) );
  148. Vector2 tilePos = new Vector2(x * roomSize.x, y * roomSize.y);
  149. newRoom.SetName("Room (" + x + ", " + y + ")");
  150. newRoom.SetParams(tilePos, roomSize);
  151. newRoom.SetRoomMapPos(new Vector2(x, y));
  152. newRoom.setDrawRoom(true);
  153.  
  154. roomMap[x, y] = newRoom;
  155. }
  156. }
  157.  
  158. GeneratePath();
  159.  
  160. RenderMap(gridArray, m_Tilemap, m_Tile);
  161. }
  162.  
  163. /* Methodology used:
  164. * Using a grid of 5x5 rooms, we create a weaved maze representing the flow of rooms the player needs to navigate in order to exit the level
  165. * We use this method or our room navigation: https://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm
  166. * We use this method for allowing "weaves" making the map more visually appealing: https://weblog.jamisbuck.org/2011/3/4/maze-generation-weave-mazes
  167. * We will probably be using a 75/25 split (75% of the time it's Newest or Backtracking method and 25% of the time, it's random or Prim)
  168. * We'll need to ensure navigability in each room similar to the Spelunky method: http://tinysubversions.com/spelunkyGen/
  169. * We want to ensure a clean "flow" for out monster generation and room types using a "Director AI" like here: https://steamcdn-a.akamaihd.net/apps/valve/2009/ai_systems_of_l4d_mike_booth.pdf
  170. * Some more details on how that Director AI can work for Metroidvanias: https://www.gamasutra.com/blogs/SebastienBENARD/20170329/294642/Building_the_Level_Design_of_a_procedurally_generated_Metroidvania_a_hybrid_approach.php
  171. *
  172. */
  173.  
  174. public RoomClass[,] GeneratePath()
  175. {
  176.  
  177. /* This is our "C" */
  178. List<RoomClass> placedRooms = new List<RoomClass>();
  179.  
  180. int count = 0;
  181.  
  182. int randX = (int)uRandom.Range(roomMap.GetLowerBound(0), roomMap.GetUpperBound(0));
  183. int randY = (int)uRandom.Range(roomMap.GetLowerBound(1), roomMap.GetUpperBound(1));
  184.  
  185. Vector2 start = new Vector2(randX, randY);
  186. RoomClass thisRoom = this.roomMap[randX, randY];
  187.  
  188. //thisRoom.SetRoomMapPos(start);
  189. thisRoom.SetVisitedOnGenerateMap(true);
  190. placedRooms.Add(thisRoom);
  191.  
  192. int iterationCount = 0;
  193.  
  194. Dictionary<Vector2, RoomClass> roomPath = new Dictionary<Vector2, RoomClass>();
  195.  
  196. List<Vector2> unplacedRooms = new List<Vector2>();
  197.  
  198. for (int x = 0; x < roomMap.GetUpperBound(0); x++)
  199. {
  200. for (int y = 0; y < roomMap.GetUpperBound(1); y++)
  201. {
  202. unplacedRooms.Add(new Vector2(x, y));
  203. }
  204. }
  205.  
  206. Vector2 currentRoom = unplacedRooms[uRandom.Range(0, unplacedRooms.Count())];
  207.  
  208. roomPath.Add(currentRoom, roomMap[(int) currentRoom.x, (int) currentRoom.y]);
  209. unplacedRooms.Remove(currentRoom);
  210.  
  211. Vector2[] directions =
  212. {
  213. Vector2.up,
  214. Vector2.down,
  215. Vector2.left,
  216. Vector2.right
  217. };
  218.  
  219. Vector2 chosenDirection = Vector2.zero;
  220.  
  221. while (true)
  222. {
  223. List<Vector2> neighborsChecked = new List<Vector2>();
  224. foreach (Vector2 thisDirection in directions)
  225. {
  226. Vector2 roomChecked = currentRoom + thisDirection;
  227. if (!roomPath.ContainsKey(roomChecked) && unplacedRooms.Contains(roomChecked)) /* If there is no room in the direction we checked */
  228. {
  229. neighborsChecked.Add(roomChecked);
  230. }
  231. }
  232.  
  233. if (neighborsChecked.Count() == 0)
  234. {
  235. break;
  236. }
  237.  
  238. int randomIndex = uRandom.Range(0, neighborsChecked.Count());
  239. Vector2 nextRoom = neighborsChecked[randomIndex];
  240.  
  241. roomPath.Add(nextRoom, roomMap[(int)nextRoom.x, (int)nextRoom.y]);
  242. unplacedRooms.Remove(nextRoom);
  243.  
  244. Vector2 wallToRemove = nextRoom - currentRoom;
  245.  
  246. /* Set the current room we're checking from and carve out the wall in the direction we're checking */
  247. RoomClass currentRoomObject = roomPath[currentRoom];
  248. RoomType newType = RemoveWallInDirection( currentRoomObject.GetRoomType(), wallToRemove);
  249. currentRoomObject.SetRoomType(newType);
  250.  
  251. /* invert the direction so that we're removing the wall where we came FROM */
  252. RoomClass nextRoomObject = roomPath[nextRoom];
  253. wallToRemove *= -1;
  254. newType = RemoveWallInDirection(nextRoomObject.GetRoomType(), wallToRemove);
  255. nextRoomObject.SetRoomType(newType);
  256.  
  257. /* Draw the rooms immediately to improve debugging */
  258. currentRoomObject.DrawRoom();
  259. nextRoomObject.DrawRoom();
  260.  
  261. currentRoom = nextRoom;
  262.  
  263. if (unplacedRooms.Count() == 0)
  264. {
  265. break;
  266. }
  267. }
  268.  
  269. foreach (Vector2 key in roomPath.Keys)
  270. {
  271. RoomClass room = roomPath[key];
  272. roomMap[(int) room.GetRoomMapPos().x, (int) room.GetRoomMapPos().x] = room;
  273. }
  274.  
  275. //while (placedRooms.Count() > 0 && iterationCount < 1000)
  276. //{
  277. // iterationCount++;
  278.  
  279. // /* Choose a cell from the list of placed rooms */
  280. // RoomClass aRoom;
  281.  
  282. // /* 75% of the time, we'll use the last room we placed, and 25% of the time we'll grab a random room from the list */
  283. // if (uRandom.Range(0, 1) < 1.01f)
  284. // {
  285. // aRoom = placedRooms[placedRooms.Count - 1];
  286. // } else {
  287. // aRoom = placedRooms[(int)uRandom.Range(0, placedRooms.Count() - 1)];
  288. // }
  289.  
  290. // /* turn the by value reference into the actual instantiate game object */
  291. // //aRoom = aRoom.GetComponent<MonoBehaviour>();
  292.  
  293. // int visitedCount = 0;
  294.  
  295. // Vector2[] directions =
  296. // {
  297. // Vector2.up,
  298. // Vector2.down,
  299. // Vector2.left,
  300. // Vector2.right
  301. // };
  302.  
  303. // //while (directions.Count() > 0)
  304. // //{
  305. // // int directionIndex = uRandom.Range(0, directions.Count());
  306. // // Vector2 thisDirection = directions[directionIndex];
  307. // // RoomClass checkedRoom = this.getRoomInDirection(aRoom, thisDirection);
  308. // // bool roomVisited = IsRoomVisited(checkedRoom);
  309. // // if (roomVisited)
  310. // // {
  311. // // visitedCount++;
  312.  
  313. // // break;
  314. // // } else
  315. // // {
  316. // // /* Set the current room we're checking from and carve out the wall in the direction we're checking */
  317. // // Vector2 wallToRemove = thisDirection;
  318. // // RoomType newType = RemoveWallInDirection(aRoom.GetRoomType(), wallToRemove);
  319. // // aRoom.SetRoomType(newType);
  320.  
  321. // // /* Set the checked room status to "visited" */
  322. // // checkedRoom.SetVisitedOnGenerateMap(true);
  323.  
  324. // // /* invert the direction so that we're removing the wall where we came FROM */
  325. // // wallToRemove = thisDirection * new Vector2(-1, -1);
  326. // // newType = RemoveWallInDirection(checkedRoom.GetRoomType(), wallToRemove);
  327. // // checkedRoom.SetRoomType(newType);
  328.  
  329. // // /* Draw the rooms immediately to improve debugging */
  330. // // aRoom.DrawRoom();
  331. // // checkedRoom.DrawRoom();
  332.  
  333. // // placedRooms.Add(checkedRoom);
  334.  
  335. // // break;
  336. // // }
  337.  
  338. // // directions = directions.Where(val => val != thisDirection).ToArray();
  339. // //}
  340.  
  341. // if (visitedCount == 4)
  342. // {
  343. // removeFromList(ref placedRooms, aRoom);
  344. // }
  345.  
  346. // RoomClass nextRoom = this.getRoomInDirection(thisRoom, this.directions.GetRandomDirection());
  347. //}
  348.  
  349. print( "Generate Path iterated x times: " + iterationCount);
  350. print("Ended with " + placedRooms.Count() + " rooms in placedRooms list");
  351.  
  352. return roomMap;
  353. }
  354.  
  355. private Vector2 GetStartRoom()
  356. {
  357. throw new NotImplementedException();
  358. }
  359.  
  360. public bool IsRoomVisited(RoomClass room)
  361. {
  362. if (room == null)
  363. {
  364. return true;
  365. }
  366. return room.GetVisitedOnGenerateMap();
  367. }
  368.  
  369. public void removeFromList(ref List<RoomClass> list, RoomClass room)
  370. {
  371. RoomClass roomToRemove = null;
  372.  
  373. foreach (RoomClass thisRoom in list)
  374. {
  375. if (thisRoom.GetRoomMapPos() == room.GetRoomMapPos())
  376. {
  377. roomToRemove = thisRoom;
  378. break;
  379. }
  380. }
  381.  
  382. if (roomToRemove != null)
  383. {
  384. list.Remove(roomToRemove);
  385. }
  386. }
  387.  
  388. public void Update()
  389. {
  390.  
  391. }
  392.  
  393. void ChooseStartAndEnd(ref RoomClass startRoom, ref RoomClass exitRoom, int x = xMax, int y = yMax, int paddingX = 0, int paddingY = 0)
  394. {
  395. if (paddingX == 0 || paddingY == 0)
  396. {
  397. paddingX = (int)this.startEndEmptySpace.x;
  398. paddingY = (int)this.startEndEmptySpace.y;
  399. }
  400.  
  401. Vector2 quadrant = Vector2.zero;
  402.  
  403. if (Mathf.RoundToInt(uRandom.Range(0.0f, 1.0f)) == 0)
  404. {
  405. quadrant.x = -1;
  406. }
  407. else
  408. {
  409. quadrant.x = 1;
  410. }
  411.  
  412. if (Mathf.RoundToInt(uRandom.Range(0.0f, 1.0f)) == 0)
  413. {
  414. quadrant.y = -1;
  415. }
  416. else
  417. {
  418. quadrant.y = 1;
  419. }
  420.  
  421. // Calculate a random position between 0 and half of x, then repeat for y
  422. Vector2 startPos = new Vector2(Mathf.RoundToInt(uRandom.Range(0, x / 2 - paddingX)), Mathf.RoundToInt(uRandom.Range(0, y / 2 - paddingY)));
  423. Vector2 endPos = new Vector2(Mathf.RoundToInt(uRandom.Range(0, x / 2 - paddingX)), Mathf.RoundToInt(uRandom.Range(0, y / 2 - paddingY)));
  424. startTilePos = startPos;
  425. endTilePos = endPos;
  426. // Multiply the random position by the Quadrant Vector to get the start position
  427. startPos *= quadrant;
  428. // Invert the quadrant vector
  429. quadrant *= new Vector2(-1, -1);
  430. // Multiply the new position by the quadrant vector to get the exit.
  431. endPos *= quadrant;
  432.  
  433. startTilePos = WorldPosToTilePos(startPos * new Vector2(16, 16));
  434. endTilePos = WorldPosToTilePos(endPos * new Vector2(16, 16));
  435.  
  436. //player.transform.Translate(TilePosToWorldPos(startTilePos, Utils.worldSpaceOriginVectors.bottomLeft));
  437.  
  438. //startRoom.transform.Translate(startPos);
  439. //startRoom.SetParams(startTilePos, new Vector2(paddingX, paddingY));
  440. //startRoom.PlaceRoom(ref this.gridArray);
  441.  
  442. //exitRoom.transform.Translate(endPos);
  443. //exitRoom.SetParams(endTilePos, new Vector2(paddingX, paddingY));
  444. //exitRoom.PlaceRoom(ref this.gridArray);
  445.  
  446. }
  447.  
  448. public int[,] GenerateArray(int width, int height, bool initEmpty = true)
  449. {
  450. bool empty = initEmpty;
  451. int[,] map = new int[width, height];
  452. for (int x = 0; x < map.GetUpperBound(0); x++)
  453. {
  454.  
  455. for (int y = 0; y < map.GetUpperBound(1); y++)
  456. {
  457. empty = initEmpty;
  458. //empty = (Mathf.RoundToInt(Random.Range(0.0f, 1.0f)) == 1 ? true : false);
  459.  
  460. //// Make sure we are not close to the start, or the exit
  461. //// Check for player within a certain number of tiles
  462. //float distToPlayer = Mathf.Abs(Vector2.Distance(TilePosToWorldPos(new Vector2(x, y)), player.transform.position))/16;
  463. //float distToExit = Mathf.Abs(Vector2.Distance(TilePosToWorldPos(new Vector2(x, y)), exit.transform.position))/16;
  464.  
  465. //if (distToPlayer <= startEndEmptySpace || distToExit <= startEndEmptySpace)
  466. //{
  467. // empty = true;
  468. //}
  469.  
  470. if (x == map.GetUpperBound(0) - 1 || x == 0)
  471. {
  472. empty = false;
  473. }
  474.  
  475. if (y == map.GetUpperBound(1) - 1 || y == 0)
  476. {
  477. empty = false;
  478. }
  479.  
  480.  
  481. if (empty)
  482. {
  483. map[x, y] = 0;
  484. }
  485. else
  486. {
  487. map[x, y] = 1;
  488. }
  489. }
  490. }
  491. return map;
  492. }
  493.  
  494. public int[,] RadiusCleanMap(int[,] map, Vector2 pos, int radius)
  495. {
  496. for (int x = 0; x < map.GetUpperBound(0); x++)
  497. {
  498. for (int y = 0; y < map.GetUpperBound(1); y++)
  499. {
  500. int distance = Mathf.RoundToInt(Mathf.Abs(Vector2.Distance(TilePosToWorldPos(new Vector2(x, y), Utils.worldSpaceOriginVectors.center), pos)) / 16);
  501. if (distance <= radius)
  502. {
  503. map[x, y] = 0; // 0 = empty position. No tile
  504. }
  505.  
  506. // If it's an outside edge, don't remove it
  507. if (x == map.GetUpperBound(0) - 1 || x == 0)
  508. {
  509. map[x, y] = 1; // 1 = tile
  510. }
  511. if (y == map.GetUpperBound(1) - 1 || y == 0)
  512. {
  513. map[x, y] = 1; // 1 = tile
  514. }
  515.  
  516. }
  517. }
  518.  
  519.  
  520. return map;
  521. }
  522.  
  523. public int[,] SquareCleanMap(ref int[,] map, Vector2 pos, int sizeX, int sizeY, bool useTile = false)
  524. {
  525. if (!useTile)
  526. {
  527. pos = WorldPosToTilePos(pos);
  528. }
  529.  
  530. int startX = (int)Mathf.Floor(pos.x);
  531. int startY = (int)Mathf.Floor(pos.y);
  532.  
  533. int stopX = (int)Mathf.Floor(pos.x + sizeX);
  534. int stopY = (int)Mathf.Floor(pos.y + sizeY);
  535.  
  536. // Iterate from posX to posX + sizeX
  537. for (int x = startX; x <= stopX; x++)
  538. {
  539. // Iterate from posX to posX + sizeY
  540. for (int y = startY; y <= stopY; y++)
  541. {
  542. // Clean that space
  543. map[x, y] = 0;
  544.  
  545. // If it's an outside edge, put it back
  546. if (x == map.GetUpperBound(0) - 1 || x == 0)
  547. {
  548. map[x, y] = 1; // 1 = tile
  549. }
  550. if (y == map.GetUpperBound(1) - 1 || y == 0)
  551. {
  552. map[x, y] = 1; // 1 = tile
  553. }
  554.  
  555. }
  556. }
  557.  
  558.  
  559. return map;
  560. }
  561.  
  562. public static Vector2 WorldPosToTilePos(Vector2 vector)
  563. {
  564. int thisX = Mathf.RoundToInt(vector.x / 16 + (xMax / 2));
  565. int thisY = Mathf.RoundToInt(vector.y / 16 + (yMax / 2));
  566.  
  567. return new Vector2(thisX, thisY);
  568. }
  569.  
  570. // 0,0 = 50%, 50%
  571.  
  572. public static Vector2 TilePosToWorldPos(Vector2 vector, Vector2 worldSpaceOrigin)
  573. {
  574. int thisX = Mathf.RoundToInt((vector.x) - (xMax / 2));
  575. int thisY = Mathf.RoundToInt((vector.y) - (yMax / 2));
  576. int returnX = thisX * 16;
  577. int returnY = thisY * 16;
  578.  
  579.  
  580.  
  581. return new Vector2(returnX, returnY) + (8 * worldSpaceOrigin);
  582. }
  583.  
  584. public bool CanPlaceRoom(int[,] map, Vector2 pos, int sizeX, int sizeY, int padding = 1)
  585. {
  586.  
  587. int minX = Mathf.Clamp(Mathf.FloorToInt(pos.x - Mathf.CeilToInt(sizeX / 2)) - padding, 0, map.GetUpperBound(0));
  588. int minY = Mathf.Clamp(Mathf.FloorToInt(pos.y - Mathf.CeilToInt(sizeY / 2)) - padding, 0, map.GetUpperBound(1));
  589. int maxX = Mathf.Clamp(Mathf.CeilToInt(pos.x + Mathf.CeilToInt(sizeX / 2)) + padding, 0, map.GetUpperBound(0));
  590. int maxY = Mathf.Clamp(Mathf.CeilToInt(pos.y + Mathf.CeilToInt(sizeY / 2)) + padding, 0, map.GetUpperBound(1));
  591.  
  592. for (int x = minX; x < maxX; x++)
  593. {
  594. for (int y = minY; y < maxY; y++)
  595. {
  596. int tmp = map[x, y];
  597. if (tmp == 0 /* This is empty space, so there's a room or hallway here */)
  598. {
  599. return false;
  600. }
  601. }
  602. }
  603.  
  604. // <= This point
  605. return true;
  606. }
  607.  
  608. public static void RenderMap(int[,] map, Tilemap tilemap, TileBase tile)
  609. {
  610. int halfX = map.GetUpperBound(0) / 2;
  611. int halfY = map.GetUpperBound(1) / 2;
  612. //Clear the map (ensures we dont overlap)
  613. tilemap.ClearAllTiles();
  614. //Loop through the width of the map
  615. for (int x = 0; x < map.GetUpperBound(0); x++)
  616. {
  617. //Loop through the height of the map
  618. for (int y = 0; y < map.GetUpperBound(1); y++)
  619. {
  620. // 1 = tile, 0 = no tile
  621. if (map[x, y] == 1)
  622. {
  623. tilemap.SetTile(new Vector3Int(Mathf.RoundToInt(x - halfX), Mathf.RoundToInt(y - halfY), 0), tile);
  624. }
  625. }
  626. }
  627. }
  628.  
  629. public RoomClass getRoomInDirection(RoomClass room, Vector2 direction)
  630. {
  631. RoomClass empty = null;
  632.  
  633. /* return an empty Vector2 if there is no room in that direction */
  634. if ( room.GetRoomMapPos().x + direction.x > this.roomMap.GetUpperBound(0) || room.GetRoomMapPos().x + direction.x < this.roomMap.GetLowerBound(0)
  635. || room.GetRoomMapPos().y + direction.y > this.roomMap.GetUpperBound(1) || room.GetRoomMapPos().y + direction.y < this.roomMap.GetLowerBound(1) )
  636. {
  637. return empty;
  638. }
  639.  
  640. Vector2 expectedRoomPos = room.GetRoomMapPos() + direction;
  641.  
  642. /* Perform a check to see if a room with that position already exists on the room map */
  643. foreach (RoomClass thisRoom in this.roomMap)
  644. {
  645. if (thisRoom.GetRoomMapPos() == expectedRoomPos)
  646. {
  647. return thisRoom;
  648. }
  649. }
  650.  
  651. /* Since each position in the roomsMap is prefilled with a new RoomClass,
  652. * there is no scenario where we shouldn't return a room.
  653. */
  654.  
  655. return null;
  656. }
  657.  
  658. public struct RelativeNeighbors
  659. {
  660. public Vector2 Up, Down, Left, Right;
  661. public Func<Vector2> GetRandomDirection;
  662. }
  663.  
  664. public Vector2 GetDirectionByIndex(int index)
  665. {
  666. switch (index)
  667. {
  668. case 0:
  669. return directions.Up;
  670. break;
  671. case 1:
  672. return directions.Down;
  673. break;
  674. case 2:
  675. return directions.Left;
  676. break;
  677. case 3:
  678. return directions.Right;
  679. break;
  680. default:
  681. break;
  682. }
  683. return Vector2.zero;
  684. }
  685.  
  686. public RoomType SetRoomType(RoomType[,] map, Vector2 roomPos, Vector2 direction)
  687. {
  688. RoomType currentRoomType = map[(int)roomPos.x, (int)roomPos.y];
  689.  
  690. RoomType newRoom = RemoveWallInDirection(currentRoomType, direction);
  691.  
  692. return newRoom;
  693. }
  694.  
  695. public RoomType RemoveWallInDirection(RoomType type, Vector2 direction)
  696. {
  697. /* Assuming the type value is the current room type, try to knock a wall down in direction and return a new room type */
  698. switch (type)
  699. {
  700. case RoomType.OPEN_ALL:
  701. return RoomType.OPEN_ALL;
  702. break;
  703. case RoomType.OPEN_N:
  704. switch (direction.x)
  705. {
  706. case 0:
  707. switch (direction.y)
  708. {
  709. case -1:
  710. return RoomType.OPEN_E_W;
  711. break;
  712. case 1:
  713. return type;
  714. break;
  715. default:
  716. break;
  717. }
  718. break;
  719. case 1:
  720. return RoomType.OPEN_N_E;
  721. break;
  722. case -1:
  723. return RoomType.OPEN_N_W;
  724. break;
  725. default:
  726. break;
  727. }
  728. break;
  729. case RoomType.OPEN_E:
  730. switch (direction.x)
  731. {
  732. case 0:
  733. switch (direction.y)
  734. {
  735. case -1:
  736. return RoomType.OPEN_E_S;
  737. break;
  738. case 1:
  739. return RoomType.OPEN_N_E;
  740. break;
  741. default:
  742. break;
  743. }
  744. break;
  745. case 1:
  746. return type;
  747. break;
  748. case -1:
  749. return RoomType.OPEN_E_W;
  750. break;
  751. default:
  752. break;
  753. }
  754. break;
  755. case RoomType.OPEN_S:
  756. switch (direction.x)
  757. {
  758. case 0:
  759. switch (direction.y)
  760. {
  761. case -1:
  762. return type;
  763. break;
  764. case 1:
  765. return RoomType.OPEN_N_S;
  766. break;
  767. default:
  768. break;
  769. }
  770. break;
  771. case 1:
  772. return RoomType.OPEN_E_S;
  773. break;
  774. case -1:
  775. return RoomType.OPEN_S_W;
  776. break;
  777. default:
  778. break;
  779. }
  780. break;
  781. case RoomType.OPEN_W:
  782. switch (direction.x)
  783. {
  784. case 0:
  785. switch (direction.y)
  786. {
  787. case -1:
  788. return RoomType.OPEN_S_W;
  789. break;
  790. case 1:
  791. return RoomType.OPEN_N_W;
  792. break;
  793. default:
  794. break;
  795. }
  796. break;
  797. case 1:
  798. return RoomType.OPEN_E_W;
  799. break;
  800. case -1:
  801. return type;
  802. break;
  803. default:
  804. break;
  805. }
  806. break;
  807. case RoomType.OPEN_N_E:
  808. switch (direction.x)
  809. {
  810. case 0:
  811. switch (direction.y)
  812. {
  813. case -1:
  814. return RoomType.CLOSED_W;
  815. break;
  816. case 1:
  817. return type;
  818. break;
  819. default:
  820. break;
  821. }
  822. break;
  823. case 1:
  824. return type;
  825. break;
  826. case -1:
  827. return RoomType.CLOSED_S;
  828. break;
  829. default:
  830. break;
  831. }
  832. break;
  833. case RoomType.OPEN_N_S:
  834. switch (direction.x)
  835. {
  836. case 0:
  837. return type;
  838. break;
  839. case 1:
  840. return RoomType.CLOSED_W;
  841. break;
  842. case -1:
  843. return RoomType.CLOSED_E;
  844. break;
  845. default:
  846. break;
  847. }
  848. break;
  849. case RoomType.OPEN_N_W:
  850. switch (direction.x)
  851. {
  852. case 0:
  853. switch (direction.y)
  854. {
  855. case -1:
  856. return RoomType.CLOSED_E;
  857. break;
  858. case 1:
  859. return type;
  860. break;
  861. default:
  862. break;
  863. }
  864. break;
  865. case 1:
  866. return RoomType.CLOSED_S;
  867. break;
  868. case -1:
  869. return type;
  870. break;
  871. default:
  872. break;
  873. }
  874. break;
  875. case RoomType.OPEN_E_S:
  876. switch (direction.x)
  877. {
  878. case 0:
  879. switch (direction.y)
  880. {
  881. case -1:
  882. return type;
  883. break;
  884. case 1:
  885. return RoomType.CLOSED_W;
  886. break;
  887. default:
  888. break;
  889. }
  890. break;
  891. case 1:
  892. return type;
  893. break;
  894. case -1:
  895. return RoomType.CLOSED_N;
  896. break;
  897. default:
  898. break;
  899. }
  900. break;
  901. case RoomType.OPEN_E_W:
  902. if (direction.x == 0)
  903. {
  904. switch (direction.y)
  905. {
  906. case -1:
  907. return RoomType.CLOSED_N;
  908. break;
  909. case 1:
  910. return RoomType.CLOSED_S;
  911. break;
  912. default:
  913. break;
  914. }
  915. }else
  916. {
  917. return type;
  918. }
  919. break;
  920. case RoomType.OPEN_S_W:
  921. switch (direction.x)
  922. {
  923. case 0:
  924. switch (direction.y)
  925. {
  926. case -1:
  927. return type;
  928. break;
  929. case 1:
  930. return RoomType.CLOSED_E;
  931. break;
  932. default:
  933. break;
  934. }
  935. break;
  936. case 1:
  937. return RoomType.CLOSED_N;
  938. break;
  939. case -1:
  940. return type;
  941. break;
  942. default:
  943. break;
  944. }
  945. break;
  946. case RoomType.CLOSED_N:
  947. if (direction.y == 1)
  948. {
  949. return RoomType.OPEN_ALL;
  950. }
  951. break;
  952. case RoomType.CLOSED_S:
  953. if (direction.y == -1)
  954. {
  955. return RoomType.OPEN_ALL;
  956. }
  957. break;
  958. case RoomType.CLOSED_E:
  959. if (direction.x == 1)
  960. {
  961. return RoomType.OPEN_ALL;
  962. }
  963. break;
  964. case RoomType.CLOSED_W:
  965. if (direction.x == -1)
  966. {
  967. return RoomType.OPEN_ALL;
  968. }
  969. break;
  970. case RoomType.CLOSED_ALL:
  971. switch (direction.x)
  972. {
  973. case 0:
  974. switch (direction.y)
  975. {
  976. case -1:
  977. return RoomType.OPEN_S;
  978. break;
  979. case 1:
  980. return RoomType.OPEN_N;
  981. break;
  982. default:
  983. break;
  984. }
  985. break;
  986. case 1:
  987. return RoomType.OPEN_E;
  988. break;
  989. case -1:
  990. return RoomType.OPEN_W;
  991. break;
  992. default:
  993. break;
  994. }
  995. break;
  996. default:
  997. break;
  998. }
  999.  
  1000. return RoomType.CLOSED_ALL;
  1001. }
  1002.  
  1003. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement