SHARE
TWEET

Untitled

a guest Jul 22nd, 2019 59 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. public class LevelGeneration : MonoBehaviour {
  6.     public GameEvent roomsCreated;
  7.  
  8.     public static LevelGeneration instance;
  9.     //Amount of rooms to generate forwards
  10.     public int generationDepth = 2;
  11.     //Amount of rooms to keep generate backwards
  12.     public int maxRoomDepth = 5;
  13.     //Chances for amount of directions in a room
  14.     public float oneWayChance = 25f, twoWayChance = 25f, threeWayChance = 25f, FourWayChance = 25f;
  15.     //Tile size of rooms
  16.     public float tileSize = 30f;
  17.  
  18.     //List of room prefabs
  19.     public List<GameObject> oneWayRooms;
  20.     public List<GameObject> twoWayStraightRooms;
  21.     public List<GameObject> twoWayCornerRooms;
  22.     public List<GameObject> threeWayRooms;
  23.     public List<GameObject> fourWayRooms;
  24.  
  25.     //Parent object to place all the rooms in
  26.     private Transform roomParent;
  27.     //A dictionary of all rooms with their tiled location
  28.     private Dictionary<Vector2, Room> rooms = new Dictionary<Vector2, Room>();
  29.     //List of rooms already checked in backwards check recursion
  30.     private List<Room> checkedRooms = new List<Room>();
  31.     //Number of open exits currently in the level
  32.     public int openExits = 0;
  33.  
  34.     //Current room number that passes on to the room (Mainly used for testing)
  35.     private int roomNumber = 0;
  36.     //Current depth of generation
  37.     private int currentDepth = 0;
  38.    
  39.     //Used for generating via the button in inspector
  40.     public Room testRoom;
  41.  
  42.     private void Awake() {
  43.         if(instance == null) {
  44.             instance = this;
  45.         } else {
  46.             Destroy(this);
  47.         }
  48.     }
  49.  
  50.     //Function called to start level generation and clear any old generation
  51.     public void Generate() {
  52.         DeleteLevel();
  53.         //Add start room
  54.         Room newRoom = CreateInitialRoom();
  55.        
  56.         AddRooms(newRoom);
  57.     }
  58.  
  59.     private Room CreateInitialRoom() {
  60.         GameObject obj = Instantiate(RandomRoom(ref oneWayRooms), Vector3.zero, Quaternion.identity, roomParent);
  61.         obj.GetComponent<RoomSpawning>().enemiesSpawned = true;
  62.         //Removing spawning from initial room
  63.         Destroy(obj.GetComponent<RoomSpawning>());
  64.         Room newRoom = obj.GetComponent<Room>();
  65.         openExits += newRoom.OpenExits();
  66.         rooms.Add(Vector2.zero, newRoom);
  67.         return newRoom;
  68.     }
  69.  
  70.     //Adds new rooms to the world and deletes old rooms
  71.     public void AddRooms(Room currentRoom) {
  72.         List<Room> roomsToCheck = new List<Room>();
  73.         List<Room> newRoomsToCheck = new List<Room>();
  74.         //Add the input room to rooms to check for open exits
  75.         roomsToCheck.Add(currentRoom);
  76.  
  77.         //Create new rooms so every path has {roomsForward} rooms forward
  78.         for (int i = 0; i < generationDepth; i++) {
  79.             currentDepth = i;
  80.             //Foreach room to check
  81.             foreach (Room room in roomsToCheck) {
  82.                 //If room has an open left exit
  83.                 if (room.left && room.roomLeft == null) {
  84.                     //Get left tile position
  85.                     Vector2 mapPos = MapPos(room.transform.position) + Vector2.left;
  86.                     //If there is already a room to the left
  87.                     if (rooms.ContainsKey(mapPos)) {
  88.                         //If the left room has a right exit open
  89.                         if (rooms[mapPos].right) {
  90.                             //Set exits to false on each room
  91.                             room.left = false;
  92.                             rooms[mapPos].right = false;
  93.                             //Add each room to the other as a reference
  94.                             room.roomLeft = rooms[mapPos];
  95.                             rooms[mapPos].roomRight = room;
  96.                             //Remove 2 open exits (1 for each room)
  97.                             openExits -= 2;
  98.                         }
  99.                     } else {
  100.                         /**If there is no room to the left
  101.                          * Generate a new room
  102.                          * Add to the next round of open exit checks
  103.                          * set left open exit to false
  104.                          **/
  105.                         newRoomsToCheck.Add(AddRoom(room, ref room.roomLeft, RoomDirection.Left));
  106.                         room.left = false;
  107.  
  108.                     }
  109.                 }
  110.                 //If room has an open right exit
  111.                 if (room.right && room.roomRight == null) {
  112.                     //Get right tile position
  113.                     Vector2 mapPos = MapPos(room.transform.position) + Vector2.right;
  114.                     //If there is already a room to the right
  115.                     if (rooms.ContainsKey(mapPos)) {
  116.                         //If the right room has a right exit open
  117.                         if (rooms[mapPos].left) {
  118.                             //Set exits to false on each room
  119.                             room.right = false;
  120.                             rooms[mapPos].left = false;
  121.                             //Add each room to the other as a reference
  122.                             room.roomRight = rooms[mapPos];
  123.                             rooms[mapPos].roomLeft = room;
  124.                             //Remove 2 open exits (1 for each room)
  125.                             openExits -= 2;
  126.                         }
  127.                     } else {
  128.                         /**If there is no room to the right
  129.                          * Generate a new room
  130.                          * Add to the next round of open exit checks
  131.                          * set right open exit to false
  132.                          **/
  133.                         newRoomsToCheck.Add(AddRoom(room, ref room.roomRight, RoomDirection.Right));
  134.                         room.right = false;
  135.                     }
  136.                 }
  137.                 //If room has an open right exit
  138.                 if (room.up && room.roomUp == null) {
  139.                     //Get right tile position
  140.                     Vector2 mapPos = MapPos(room.transform.position) + Vector2.up;
  141.                     //If there is already a room to the right
  142.                     if (rooms.ContainsKey(mapPos)) {
  143.                         //If the right room has a right exit open
  144.                         if (rooms[mapPos].down) {
  145.                             //Set exits to false on each room
  146.                             room.up = false;
  147.                             rooms[mapPos].down = false;
  148.                             //Add each room to the other as a reference
  149.                             room.roomUp = rooms[mapPos];
  150.                             rooms[mapPos].roomDown = room;
  151.                             //Remove 2 open exits (1 for each room)
  152.                             openExits -= 2;
  153.                         }
  154.                     } else {
  155.                         /**If there is no room to the up
  156.                          * Generate a new room
  157.                          * Add to the next round of open exit checks
  158.                          * set up open exit to false
  159.                          **/
  160.                         newRoomsToCheck.Add(AddRoom(room, ref room.roomUp, RoomDirection.Up));
  161.                         room.up = false;
  162.                     }
  163.                 }
  164.                 //If room has an open right exit
  165.                 if (room.down && room.roomDown == null) {
  166.                     //Get right tile position
  167.                     Vector2 mapPos = MapPos(room.transform.position) + Vector2.down;
  168.                     //If there is already a room to the right
  169.                     if (rooms.ContainsKey(mapPos)) {
  170.                         //If the right room has a right exit open
  171.                         if (rooms[mapPos].up) {
  172.                             //Set exits to false on each room
  173.                             room.down = false;
  174.                             rooms[mapPos].up = false;
  175.                             //Add each room to the other as a reference
  176.                             room.roomDown = rooms[mapPos];
  177.                             rooms[mapPos].roomUp = room;
  178.                             //Remove 2 open exits (1 for each room)
  179.                             openExits -= 2;
  180.                         }
  181.                     } else {
  182.                         /**If there is no room to the down
  183.                          * Generate a new room
  184.                          * Add to the next round of open exit checks
  185.                          * set down open exit to false
  186.                          **/
  187.                         newRoomsToCheck.Add(AddRoom(room, ref room.roomDown, RoomDirection.Down));
  188.                         room.down = false;
  189.                     }
  190.                 }
  191.             }
  192.             //Clear the room to check list (This is the list we have gone through already(
  193.             roomsToCheck.Clear();
  194.             //Add thew newRoomsToCheck to roomsToCheck
  195.             roomsToCheck.AddRange(newRoomsToCheck);
  196.             //Clear newRoomsToCheck
  197.             newRoomsToCheck.Clear();
  198.         }
  199.  
  200.         //Destroy any rooms in a path that is more than {roomsBackward} rooms behind the current room
  201.         CheckBackwardsRooms(currentRoom, currentRoom, 0);
  202.  
  203.         roomsCreated.Raise();
  204.     }
  205.  
  206.     //Function called to generate a new room
  207.     private Room AddRoom(Room origin, ref Room connection, RoomDirection direction) {
  208.         //Add a new room to the connection, based on the direction
  209.         connection = AddGenericRoom(origin, direction);
  210.  
  211.         //This switch adds the origin room as a reference to the new room
  212.         switch (direction) {
  213.             case RoomDirection.Down:
  214.                 connection.roomUp = origin;
  215.                 break;
  216.             case RoomDirection.Left:
  217.                 connection.roomRight = origin;
  218.                 break;
  219.             case RoomDirection.Up:
  220.                 connection.roomDown = origin;
  221.                 break;
  222.             case RoomDirection.Right:
  223.                 connection.roomLeft = origin;
  224.                 break;
  225.         }
  226.  
  227.         //If there is already a room stored at the position of the new room, overwrite it - This should never actually happen
  228.         if (rooms.ContainsKey(MapPos(connection.transform.position))) {
  229.             rooms[MapPos(connection.transform.position)] = connection;
  230.         } else {
  231.             //Else add to rooms dictionary
  232.             rooms.Add(MapPos(connection.transform.position), connection);
  233.         }
  234.  
  235.         //Add number of open exits new room has ( minus one because the origin room has 1 less open exit now)
  236.         openExits += connection.OpenExits() - 1;
  237.  
  238.         //Sets the testRoom variable to the new room if the new room has an open exit - Only used for testing
  239.         if ((connection.OpenExits()) > 1) testRoom = origin;
  240.  
  241.         //Return new room
  242.         return connection;
  243.     }
  244.  
  245.     //Traverse through rooms to see if max backwards has been hit
  246.     public bool CheckBackwardsRooms(Room room, Room origRoom, int depth) {
  247.  
  248.         /**
  249.         * Checks for a room connected in each direction
  250.         * Makes sure that room is not the room this is coming from
  251.         * Recursively calls this funtion until we get to the end
  252.         * If the last room is a higher depth than max depth, returns false and deleted after return
  253.         **/
  254.  
  255.         //If this is the inital check, clear checkedRooms.
  256.         if (depth == 0) {
  257.             checkedRooms.Clear();
  258.         }
  259.         //Add current room
  260.         checkedRooms.Add(room);
  261.  
  262.         //If this room has a room to the left, is not the origin room and the left room has not been checked
  263.         if (room.roomLeft && room.roomLeft != origRoom && !checkedRooms.Contains(room.roomLeft)) {
  264.             //If the left room is passed the maximum depth
  265.             if (!CheckBackwardsRooms(room.roomLeft, room, depth + 1)) {
  266.                 //Remove room from dictionary
  267.                 rooms.Remove(MapPos(room.roomLeft.transform.position));
  268.                 //Destroy room
  269.                 Destroy(room.roomLeft.gameObject);
  270.                 //Set reference to null
  271.                 room.roomLeft = null;
  272.                 //Set exit to open
  273.                 room.left = true;
  274.                 //Add 1 to open exits counter
  275.                 openExits++;
  276.             }
  277.         }
  278.  
  279.         //If this room has a room to the right, is not the origin room and the right room has not been checked
  280.         if (room.roomRight && room.roomRight != origRoom && !checkedRooms.Contains(room.roomRight)) {
  281.             //If the right room is passed the maximum depth
  282.             if (!CheckBackwardsRooms(room.roomRight, room, depth + 1)) {
  283.                 //Remove room from dictionary
  284.                 rooms.Remove(MapPos(room.roomRight.transform.position));
  285.                 //Destroy room
  286.                 Destroy(room.roomRight.gameObject);
  287.                 //Set reference to null
  288.                 room.roomRight = null;
  289.                 //Set exit to open
  290.                 room.right = true;
  291.                 //Add 1 to open exits counter
  292.                 openExits++;
  293.             }
  294.         }
  295.  
  296.         //If this room has a room down, is not the origin room and the down room has not been checked
  297.         if (room.roomDown && room.roomDown != origRoom && !checkedRooms.Contains(room.roomDown)) {
  298.             //If the down room is passed the maximum depth
  299.             if (!CheckBackwardsRooms(room.roomDown, room, depth + 1)) {
  300.                 //Remove room from dictionary
  301.                 rooms.Remove(MapPos(room.roomDown.transform.position));
  302.                 //Destroy room
  303.                 Destroy(room.roomDown.gameObject);
  304.                 //Set reference to null
  305.                 room.roomDown = null;
  306.                 //Set exit to open
  307.                 room.down = true;
  308.                 //Add 1 to open exits counter
  309.                 openExits++;
  310.             }
  311.         }
  312.  
  313.         //If this room has a room up, is not the origin room and the up room has not been checked
  314.         if (room.roomUp && room.roomUp != origRoom && !checkedRooms.Contains(room.roomUp)) {
  315.             //If the up room is passed the maximum depth
  316.             if (!CheckBackwardsRooms(room.roomUp, room, depth + 1)) {
  317.                 //Remove room from dictionary
  318.                 rooms.Remove(MapPos(room.roomUp.transform.position));
  319.                 //Destroy room
  320.                 Destroy(room.roomUp.gameObject);
  321.                 //Set reference to null
  322.                 room.roomUp = null;
  323.                 //Set exit to open
  324.                 room.up = true;
  325.                 //Add 1 to open exits counter
  326.                 openExits++;
  327.             }
  328.         }
  329.  
  330.         //Return false if this is past the max depth
  331.         if (depth > maxRoomDepth) {
  332.             return false;
  333.         }
  334.         //Returns true if this is within the max depth limit
  335.         return true;
  336.     }
  337.  
  338.     private void DeleteLevel() {
  339.         //Clears dictionary of rooms
  340.         rooms.Clear();
  341.         //Resets openExits and room number
  342.         openExits = 0;
  343.         roomNumber = 1;
  344.  
  345.         //If roomParent has been created, delete this, deleting all rooms along with it
  346.         if (roomParent != null) {
  347.             Destroy(roomParent.gameObject);
  348.         }
  349.         //Create a new room parents
  350.         roomParent = new GameObject().transform;
  351.         roomParent.SetParent(transform);
  352.     }
  353.  
  354.     //This funtion is called to check if a room placement is able to be placed
  355.     private bool RoomClear(Room room, Vector2 mapPos, RoomRotation rotation, RoomDirection direction) {
  356.         //rotates room
  357.         switch (rotation) {
  358.             case RoomRotation.Clockwise:
  359.                 room.RotateClockwise();
  360.                 break;
  361.             case RoomRotation.CounterClockwise:
  362.                 room.RotateCounterClockwise();
  363.                 break;
  364.             case RoomRotation.Flip:
  365.                 room.Rotate180();
  366.                 break;
  367.         }
  368.         //If there is a mistmatch on exits lininig up, rotate room back
  369.         if (!CheckForMismatchExits(mapPos, room, direction)) {
  370.             switch (rotation) {
  371.                 case RoomRotation.Clockwise:
  372.                     room.RotateCounterClockwise();
  373.                     break;
  374.                 case RoomRotation.CounterClockwise:
  375.                     room.RotateClockwise();
  376.                     break;
  377.                 case RoomRotation.Flip:
  378.                     room.Rotate180();
  379.                     break;
  380.             }
  381.             //Room is not clear
  382.             return false;
  383.         } else {
  384.             //Room is clear
  385.             return true;
  386.         }
  387.     }
  388.  
  389.     //This funtion is called to check if exits line up for a room and the surrounding room
  390.     private bool CheckForMismatchExits(Vector2 mapPos, Room room, RoomDirection direction) {
  391.         //Get the tile position for up, down, left, right
  392.         Vector2 roomUp = mapPos + Vector2.up;
  393.         Vector2 roomDown = mapPos + Vector2.down;
  394.         Vector2 roomLeft = mapPos + Vector2.left;
  395.         Vector2 roomRight = mapPos + Vector2.right;
  396.  
  397.         //If there is a room above the room being checked and it is not the origin room
  398.         if (rooms.ContainsKey(roomUp) && direction != RoomDirection.Up) {
  399.             //If there is an exit in this room but not in the above room
  400.             if (room.up && !rooms[roomUp].down) {
  401.                 //Failed check
  402.                 return false;
  403.             //If there is no exit in this room and there is in the above room
  404.             } else if (!room.up && rooms[roomUp].down) {
  405.                 //Fail check
  406.                 return false;
  407.             }
  408.         }
  409.  
  410.         //If there is a room below the room being checked and it is not the origin room
  411.         if (rooms.ContainsKey(roomDown) && direction != RoomDirection.Down) {
  412.             //If there is an exit in this room but not in the down room
  413.             if (room.down && !rooms[roomDown].up) {
  414.                 //Fail check
  415.                 return false;
  416.             //If there is no exit in this room and there is in the down room
  417.             } else if (!room.down && rooms[roomDown].up) {
  418.                 //Fail check
  419.                 return false;
  420.             }
  421.         }
  422.  
  423.         //If there is a room in the left room being checked and it is not the origin room
  424.         if (rooms.ContainsKey(roomLeft) && direction != RoomDirection.Left) {
  425.             //If there is an exit in this room but not in the left room
  426.             if (room.left && !rooms[roomLeft].right) {
  427.                 //Fail check
  428.                 return false;
  429.             //If there is no exit in this room and there is in the left room
  430.             } else if (!room.left && rooms[roomLeft].right) {
  431.                 //Fail check
  432.                 return false;
  433.             }
  434.         }
  435.  
  436.         //If there is a room  in the right room being checked and it is not the origin room
  437.         if (rooms.ContainsKey(roomRight) && direction != RoomDirection.Right) {
  438.             //If there is an exit in this room but not in the right room
  439.             if (room.right && !rooms[roomRight].left) {
  440.                 //Fail check
  441.                 return false;
  442.             //If there is no exit in this room and there is in the right room
  443.             } else if (!room.right && rooms[roomRight].left) {
  444.                 //Fail check
  445.                 return false;
  446.             }
  447.         }
  448.  
  449.         //If it made it this far, then the check was successful
  450.         return true;
  451.     }
  452.  
  453.     //Function called to initialise the room generation
  454.     private Room AddGenericRoom(Room currentRoom, RoomDirection direction) {
  455.         //Get base position for new room
  456.         Vector3 newRoomPos = currentRoom.transform.position;
  457.  
  458.         //Add to the position depending on the direction to room is going
  459.         switch (direction) {
  460.             case RoomDirection.Up:
  461.                 newRoomPos.z += tileSize / 2;
  462.                 break;
  463.             case RoomDirection.Down:
  464.                 newRoomPos.z -= tileSize / 2;
  465.                 break;
  466.             case RoomDirection.Left:
  467.                 newRoomPos.x -= tileSize / 2;
  468.                 break;
  469.             case RoomDirection.Right:
  470.                 newRoomPos.x += tileSize / 2;
  471.                 break;
  472.         }
  473.  
  474.         //Get room prefab
  475.         GameObject newRoomPrefab = GetRoom(MapPos(newRoomPos), MapPos(currentRoom.transform.position));
  476.         //Instantiate room
  477.         GameObject newRoomObj = Instantiate(newRoomPrefab, newRoomPos, Quaternion.identity, roomParent);
  478.         //Get Room script from new object
  479.         Room newRoom = newRoomObj.GetComponent<Room>();
  480.         //Set room number
  481.         newRoom.roomNumber = roomNumber;
  482.         //Sets colour of the room depending on the depth of the room (this if for testing)
  483.         //newRoom.SetColour((1f / (float)maxRoomDepth) * currentDepth);
  484.         //Increments roomNumber
  485.         roomNumber++;
  486.  
  487.         //Calls a rotation check on rooms depending on their direction from origin room
  488.         switch (direction) {
  489.             case RoomDirection.Up:
  490.                 if (RotateUp(ref newRoom, newRoomPos)) return newRoom;
  491.                 break;
  492.             case RoomDirection.Down:
  493.                 if (RotateDown(ref newRoom, newRoomPos)) return newRoom;
  494.                 break;
  495.             case RoomDirection.Left:
  496.                 if (RotateLeft(ref newRoom, newRoomPos)) return newRoom;
  497.                 break;
  498.             case RoomDirection.Right:
  499.                 if (RotateRight(ref newRoom, newRoomPos)) return newRoom;
  500.                 break;
  501.         }
  502.  
  503.         //This should NEVER be called - if it is something is very wrong.
  504.         Debug.LogError($"Room has no available exits! {newRoomPos} {direction} {newRoomObj.name}");
  505.         return newRoom;
  506.     }
  507.  
  508.     private bool RotateUp(ref Room newRoom, Vector3 newRoomPos) {
  509.         //If the new room has an open exit down
  510.         if (newRoom.down) {
  511.             //Set exit to closed
  512.             newRoom.down = false;
  513.             //If the room is not clear with no rotation
  514.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.None, RoomDirection.Down)) {
  515.                 //Set exit back to closed
  516.                 newRoom.down = true;
  517.             } else {
  518.                 //Return true, this room fits where it is
  519.                 return true;
  520.             }
  521.         }
  522.  
  523.         if (newRoom.left) {
  524.             //Set exit to closed
  525.             newRoom.left = false;
  526.             //If the room is not clear with counter clockwise rotation
  527.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.CounterClockwise, RoomDirection.Down)) {
  528.                 //Set exit back to closed
  529.                 newRoom.left = true;
  530.             } else {
  531.                 //Return true, this room fits where it is
  532.                 return true;
  533.             }
  534.         }
  535.  
  536.         if (newRoom.up) {
  537.             //Set exit to closed
  538.             newRoom.up = false;
  539.             //If the room is not clear with a 180 rotation
  540.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.Flip, RoomDirection.Down)) {
  541.                 //Set exit back to closed
  542.                 newRoom.up = true;
  543.             } else {
  544.                 //Return true, this room fits where it is
  545.                 return true;
  546.             }
  547.         }
  548.  
  549.         if (newRoom.right) {
  550.             //Set exit to closed
  551.             newRoom.right = false;
  552.             //If the room is not clear with clockwise rotation
  553.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.Clockwise, RoomDirection.Down)) {
  554.                 //Set exit back to closed
  555.                 newRoom.right = true;
  556.             } else {
  557.                 //Return true, this room fits where it is
  558.                 return true;
  559.             }
  560.         }
  561.  
  562.         //This room does not fit - This should NEVER happen!
  563.         return false;
  564.     }
  565.  
  566.     //Look at RotateDown comments, same thing here with different rotations
  567.     private bool RotateDown(ref Room newRoom, Vector3 newRoomPos) {
  568.         if (newRoom.up) {
  569.             newRoom.up = false;
  570.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.None, RoomDirection.Up)) {
  571.                 newRoom.up = true;
  572.             } else {
  573.                 return true;
  574.             }
  575.         }
  576.  
  577.         if (newRoom.right) {
  578.             newRoom.right = false;
  579.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.CounterClockwise, RoomDirection.Up)) {
  580.                 newRoom.right = true;
  581.             } else {
  582.                 return true;
  583.             }
  584.         }
  585.  
  586.         if (newRoom.down) {
  587.             newRoom.down = false;
  588.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.Flip, RoomDirection.Up)) {
  589.                 newRoom.down = true;
  590.             } else {
  591.                 return true;
  592.             }
  593.         }
  594.  
  595.         if (newRoom.left) {
  596.             newRoom.left = false;
  597.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.Clockwise, RoomDirection.Up)) {
  598.                 newRoom.left = true;
  599.             } else {
  600.                 return true;
  601.             }
  602.         }
  603.  
  604.         return false;
  605.     }
  606.  
  607.     //Look at RotateDown comments, same thing here with different rotations
  608.     private bool RotateLeft(ref Room newRoom, Vector3 newRoomPos) {
  609.         if (newRoom.right) {
  610.             newRoom.right = false;
  611.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.None, RoomDirection.Right)) {
  612.                 newRoom.right = true;
  613.             } else {
  614.                 return true;
  615.             }
  616.         }
  617.         if (newRoom.down) {
  618.             newRoom.down = false;
  619.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.CounterClockwise, RoomDirection.Right)) {
  620.                 newRoom.down = true;
  621.             } else {
  622.                 return true;
  623.             }
  624.         }
  625.         if (newRoom.left) {
  626.             newRoom.left = false;
  627.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.Flip, RoomDirection.Right)) {
  628.                 newRoom.left = true;
  629.             } else {
  630.                 return true;
  631.             }
  632.         }
  633.         if (newRoom.up) {
  634.             newRoom.up = false;
  635.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.Clockwise, RoomDirection.Right)) {
  636.                 newRoom.up = true;
  637.             } else {
  638.                 return true;
  639.             }
  640.         }
  641.  
  642.         return false;
  643.     }
  644.  
  645.     //Look at RotateDown comments, same thing here with different rotations
  646.     private bool RotateRight(ref Room newRoom, Vector3 newRoomPos) {
  647.         if (newRoom.left) {
  648.             newRoom.left = false;
  649.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.None, RoomDirection.Left)) {
  650.                 newRoom.left = true;
  651.             } else {
  652.                 return true;
  653.             }
  654.         }
  655.         if (newRoom.up) {
  656.             newRoom.up = false;
  657.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.CounterClockwise, RoomDirection.Left)) {
  658.                 newRoom.up = true;
  659.             } else {
  660.                 return true;
  661.             }
  662.         }
  663.         if (newRoom.right) {
  664.             newRoom.right = false;
  665.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.Flip, RoomDirection.Left)) {
  666.                 newRoom.right = true;
  667.             } else {
  668.                 return true;
  669.             }
  670.         }
  671.         if (newRoom.down) {
  672.             newRoom.down = false;
  673.             if (!RoomClear(newRoom, MapPos(newRoomPos), RoomRotation.Clockwise, RoomDirection.Left)) {
  674.                 newRoom.down = true;
  675.             } else {
  676.                 return true;
  677.             }
  678.         }
  679.  
  680.         return false;
  681.     }
  682.  
  683.     //Get a random room that can fit in the given location
  684.     private GameObject GetRoom(Vector2 mapPos, Vector2 origin) {
  685.         //Some variables to initialise
  686.         float roll = 0;
  687.         bool twoWayCorner = false;
  688.         bool twoWayStraight = false;
  689.  
  690.         //Gets the amount of free tiles around given position (not including origin)
  691.         int tilesAvailable = GetAvailableTiles(mapPos);
  692.  
  693.         //If tiles available is more than or equal to 1
  694.         if (tilesAvailable >= 1) {
  695.             //Find out what two way room can fit (straight or corner)
  696.             GetTwoWayAvaible(mapPos, origin, out twoWayCorner, out twoWayStraight);
  697.         }
  698.  
  699.         /**
  700.          * If any rooms are surrounding the new placement
  701.          * Check to see if any rooms need connections
  702.          **/
  703.  
  704.         if (tilesAvailable != 0) {
  705.             //Create a variable for each direction (these check include origin)
  706.             bool up = false, down = false, left = false, right = false;
  707.            
  708.             /**These checks do the following:
  709.              * Is there a room in this direction?
  710.              * If there is, set that directions bool = to the same as the open exit bool in that room
  711.              * So, if there is a room up and we find out what that rooms down bool is equal to
  712.              **/
  713.  
  714.             if (rooms.ContainsKey(mapPos + Vector2.up)) up = rooms[mapPos + Vector2.up].down;
  715.             if (rooms.ContainsKey(mapPos + Vector2.down)) down = rooms[mapPos + Vector2.down].up;
  716.             if (rooms.ContainsKey(mapPos + Vector2.left)) left = rooms[mapPos + Vector2.left].right;
  717.             if (rooms.ContainsKey(mapPos + Vector2.right)) right = rooms[mapPos + Vector2.right].left;
  718.  
  719.             //If all directions need to be connected, get a 4-way room
  720.             if (up && down && left && right) {
  721.                 return RandomRoom(ref fourWayRooms);
  722.             }
  723.  
  724.             //If there are 3 connections that need to be made
  725.             if ((up && left && down) || (left && down && right) || (down && right && up) || (right && up && left)) {
  726.                 //If there is a free tile surrounding this tile
  727.                 if (tilesAvailable == 1) {
  728.                     //roll a 4-way or 3-way room
  729.                     roll = Random.Range(0, threeWayChance + FourWayChance);
  730.                     if (roll <= threeWayChance && openExits > 1) {
  731.                         return RandomRoom(ref threeWayRooms);
  732.                     } else {
  733.                         return RandomRoom(ref fourWayRooms);
  734.                     }
  735.                 //If there is not free tiles
  736.                 } else {
  737.                     //Roll a 3-way room
  738.                     return RandomRoom(ref threeWayRooms);
  739.                 }
  740.             }
  741.  
  742.             //If there is 2 connections that need to be made in a corner shape
  743.             if ((up && left) || (up && right) || (down && left) || (down && right)) {
  744.                 //If there is only 1 free tile surrounding this tile
  745.                 if (tilesAvailable == 1) {
  746.                     //Rool for a 2-way corner or 3-way room
  747.                     roll = Random.Range(0, threeWayChance + twoWayChance);
  748.                     if (roll <= twoWayChance && openExits > 1) {
  749.                         return RandomRoom(ref twoWayCornerRooms);
  750.                     } else {
  751.                         return RandomRoom(ref threeWayRooms);
  752.                     }
  753.                 //If there is 2 free tile surrounding this tile
  754.                 } else if (tilesAvailable == 2) {
  755.                     //Rool for a 2-way corner or 3-way or 4-way room
  756.                     roll = Random.Range(0, threeWayChance + twoWayChance + FourWayChance);
  757.                     if (roll <= twoWayChance && openExits > 1) {
  758.                         return RandomRoom(ref twoWayCornerRooms);
  759.                     } else if (roll <= threeWayChance) {
  760.                         return RandomRoom(ref threeWayRooms);
  761.                     } else {
  762.                         return RandomRoom(ref fourWayRooms);
  763.                     }
  764.                 } else {
  765.                     //If there are no free tiles, room a corner room
  766.                     return RandomRoom(ref twoWayCornerRooms);
  767.                 }
  768.             }
  769.            
  770.             //If there is 2 connections that need to be made in a line
  771.             if ((up && down) || (left && right)) {
  772.                 //If there is only 1 free tile surrounding this tile
  773.                 if (tilesAvailable == 1) {
  774.                     //Rool for a 2-way straight or 3-way room
  775.                     roll = Random.Range(0, threeWayChance + twoWayChance);
  776.                     if (roll <= twoWayChance && openExits > 1) {
  777.                         return RandomRoom(ref twoWayStraightRooms);
  778.                     } else {
  779.                         return RandomRoom(ref threeWayRooms);
  780.                     }
  781.                 //If there is 2 free tile surrounding this tile
  782.                 } else if (tilesAvailable == 2) {
  783.                     //Rool for a 2-way straight or 3-way or 4-way room
  784.                     roll = Random.Range(0, threeWayChance + twoWayChance + FourWayChance);
  785.                     if (roll <= twoWayChance && openExits > 1) {
  786.                         return RandomRoom(ref twoWayStraightRooms);
  787.                     } else if (roll <= threeWayChance) {
  788.                         return RandomRoom(ref threeWayRooms);
  789.                     } else {
  790.                         return RandomRoom(ref fourWayRooms);
  791.                     }
  792.                 } else {
  793.                     //If there are no free tiles, room a straight room
  794.                     return RandomRoom(ref twoWayStraightRooms);
  795.                 }
  796.             }
  797.         }
  798.  
  799.         //If there are no surrounding connections, roll a random number
  800.         roll = Random.Range(0f, 1f);
  801.  
  802.         //If rolled a 1 way room and there are more than 1 exits open
  803.         if (roll <= oneWayChance && openExits > 1) {
  804.             //Return 1 way room
  805.             return RandomRoom(ref oneWayRooms);
  806.         //If rolled a 2 way room and there is more than 1 free tiles surrounding the tile or there is only 1 free tile
  807.         } else if ((roll <= oneWayChance + twoWayChance && tilesAvailable >= 1) || tilesAvailable == 1) {
  808.             //If there is room for a corner or a straight, roll for a corner or straight
  809.             if (twoWayCorner && twoWayStraight) {
  810.                 if (Random.Range(0f, 1f) <= 0.5f) {
  811.                     return RandomRoom(ref twoWayStraightRooms);
  812.                 } else {
  813.                     return RandomRoom(ref twoWayCornerRooms);
  814.                 }
  815.             //If there is room for only a corner, roll a corner
  816.             } else if (twoWayCorner) {
  817.                 return RandomRoom(ref twoWayCornerRooms);
  818.             //If there is room for only a straight, roll a straight
  819.             } else {
  820.                 return RandomRoom(ref twoWayStraightRooms);
  821.             }
  822.         //If rolled a 3 way room and there is more than 2 free tiles surrounding the tile or there is only 2 free tiles
  823.         } else if ((roll <= oneWayChance + twoWayChance + threeWayChance && tilesAvailable >= 2) || tilesAvailable == 2) {
  824.             //Roll a 3-way room
  825.             return RandomRoom(ref threeWayRooms);
  826.             //If rolled a 4 way room and there is 3 free tiles surrounding the tile
  827.         } else if (roll <= oneWayChance + twoWayChance + threeWayChance + FourWayChance && tilesAvailable == 3) {
  828.             //Roll a 4-way room
  829.             return RandomRoom(ref fourWayRooms);
  830.         //If nothing has been rolled and there is more than 1 exit, place a dead end.
  831.         } else if (openExits > 1) { // Only called if there is only 1 tile available
  832.             return RandomRoom(ref oneWayRooms);
  833.         } else {
  834.             //Catch all case, this should never be called, no paths are available!
  835.             Debug.LogError($"No open paths available! {mapPos * (tileSize / 2)}");
  836.             return RandomRoom(ref oneWayRooms);
  837.         }
  838.     }
  839.  
  840.     //Returns if a corner and straight is possible in desired location
  841.     private void GetTwoWayAvaible(Vector2 mapPos, Vector2 origin, out bool corner, out bool straight) {
  842.         straight = false;
  843.         corner = false;
  844.         //Find out if each direction is free for an exit
  845.         bool up = !rooms.ContainsKey(mapPos + Vector2.up) || mapPos + Vector2.up == origin;
  846.         bool down = !rooms.ContainsKey(mapPos + Vector2.down) || mapPos + Vector2.down == origin;
  847.         bool left = !rooms.ContainsKey(mapPos + Vector2.left) || mapPos + Vector2.left == origin;
  848.         bool right = !rooms.ContainsKey(mapPos + Vector2.right) || mapPos + Vector2.right == origin;
  849.  
  850.         //Checks if rooms fit dependant on open exits above
  851.         if ((left && right && (mapPos + Vector2.left == origin || mapPos + Vector2.right == origin))) straight = true;
  852.         if ((up && down && (mapPos + Vector2.up == origin || mapPos + Vector2.down == origin))) straight = true;
  853.         if ((up && left) || (up && right) || (down && left) || (down && right)) corner = true;
  854.     }
  855.  
  856.     //Retrieves a count of empty tiles around a given position
  857.     private int GetAvailableTiles(Vector2 mapPos) {
  858.         int tilesAvailable = 0;
  859.         if (!rooms.ContainsKey(mapPos + Vector2.right))
  860.             tilesAvailable++;
  861.         if (!rooms.ContainsKey(mapPos + Vector2.left))
  862.             tilesAvailable++;
  863.         if (!rooms.ContainsKey(mapPos + Vector2.up))
  864.             tilesAvailable++;
  865.         if (!rooms.ContainsKey(mapPos + Vector2.down))
  866.             tilesAvailable++;
  867.         return tilesAvailable;
  868.     }
  869.  
  870.     //Returns a random room from a given list
  871.     private GameObject RandomRoom(ref List<GameObject> roomList) {
  872.         if(roomList.Count == 0) {
  873.             return twoWayStraightRooms[Random.Range(0, roomList.Count)];
  874.         }
  875.         return roomList[Random.Range(0, roomList.Count)];
  876.     }
  877.  
  878.     //Returns a vector2 tile position from a given vector3
  879.     private Vector2 MapPos(Vector3 tilePos) {
  880.         return new Vector2(tilePos.x, tilePos.z) / (tileSize / 2);
  881.     }
  882. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top