Dungeon Builder Placing Rooms[1]에 이어서 작성한 코드 내용이다.
/// <summary>
/// Process rooms in the open room node queue, returning true if there are no room overlaps
/// </summary>
private bool ProcessRoomsInOpenRoomNodeQueue(RoomNodeGraphSO roomNodeGraph, Queue<RoomNodeSO> openRoomNodeQueue, bool noRoomsOverlaps)
{
//While room nodes in open room node queue & no room overlaps detected.
while (openRoomNodeQueue.Count > 0 && noRoomsOverlaps == true)
{
// Get next room node from open room node queue.
RoomNodeSO roomNode = openRoomNodeQueue.Dequeue();
// Add child Nodes to queue from room node graph (with links to this parent Room)
foreach (RoomNodeSO childRoomNode in roomNodeGraph.GetChildRoomNodes(roomNode))
{
openRoomNodeQueue.Enqueue(childRoomNode);
}
// if the room is the entrance mark as positioned and add to room dictionary
if (roomNode.roomNodeType.isEntrance)
{
RoomTemplateSO roomTemplate = GetRandomRoomTemplate(roomNode.roomNodeType);
Room room = CreateRoomFromRoomTemplate(roomTemplate, roomNode);
room.isPositioned = true;
// Add room to room dictionary
dungeonBuilderRoomDictionary.Add(room.id, room);
}
// else if the room type isn't an entrance
else
{
// Else get parent room for node
Room parentRoom = dungeonBuilderRoomDictionary[roomNode.parentRoomNodeIDList[0]];
// See if room can be placed without overlaps
noRoomsOverlaps = CanPlaceRoomWithNoOverlaps(roomNode, parentRoom);
}
}
}
/// <summary>
/// Get a random room template from the roomtemplatelist that matches the roomType and return it
/// (return null if no mathing room templates found).
/// </summary>
private RoomTemplateSO GetRandomRoomTemplate(RoomNodeTypeSO roomNodeType)
{
List<RoomTemplateSO> matchingRoomTemplateList = new List<RoomTemplateSO>();
// Loop through room template list
foreach(RoomTemplateSO roomTemplate in roomTemplateList)
{
// Add matching room templates
if (roomTemplate.roomNodeType == roomNodeType)
{
matchingRoomTemplateList.Add(roomTemplate);
}
}
// Return null if list is zero
if (matchingRoomTemplateList.Count == 0)
return null;
// Select random room template from list and return
return matchingRoomTemplateList[UnityEngine.Random.Range(0, matchingRoomTemplateList.Count)];
}
/// <summary>
/// Attempt to place the room node in the dungeon - if room can be placed return the room, else return null
/// </summary>
private bool CanPlaceRoomWithNoOverlaps(RoomNodeSO roomNode, Room parentRoom)
{
// initialise and assume overlap until proven otherwise.
bool roomOverlaps = true;
// Do while Room Overlaps - try to place against all available doorways of the parent until
// the room is successfully placed without overlap.
while (roomOverlaps)
{
// Select random unconnected available doorway for Parent
List<Doorway> unconnectedAbailableParentDoorways = GetUnconnectedAvailableDoorways(parentRoom.doorWayList).ToList();
if (unconnectedAbailableParentDoorways.Count == 0)
{
// If no more doorways to try then overlap failure.
return false; // room overlaps
}
Doorway doorwayParent = unconnectedAbailableParentDoorways[UnityEngine.Random.Range(0, unconnectedAbailableParentDoorways.Count)];
// Get a random room template for room node that is consistent with the parent door orientation
RoomTemplateSO roomtemplate = GetRandomTemplateForRoomConsistentWithParent(roomNode, doorwayParent);
}
}
/// <summary>
/// Get unconnected doorways
/// </summary>
private IEnumerable<Doorway> GetUnconnectedAvailableDoorways(List<Doorway> roomDoorwayList)
{
// Loop through doorway list
foreach (Doorway doorway in roomDoorwayList)
{
if (!doorway.isConnected && !doorway.isUnavailable)
{
yield return doorway;
}
}
}
/// <summary>
/// Create room based on roomTemplate and layoutNode, and return the created room
/// </summary>
private Room CreateRoomFromRoomTemplate(RoomTemplateSO roomTemplate, RoomNodeSO roomNode)
{
// Initialise room from template
Room room = new Room();
room.templateID = roomTemplate.guid;
room.id = roomNode.id;
room.prefab = roomTemplate.prefab;
room.lowerBounds = roomTemplate.lowerBounds;
room.upperBounds = roomTemplate.upperBounds;
room.spawnPositionArray = roomTemplate.spawnPositionArray;
room.templateLowerBounds = roomTemplate.lowerBounds;
room.templateUpperBounds = roomTemplate.upperBounds;
room.childRoomIDList = CopyStringList(roomNode.childRoomNodeIDList);
room.doorWayList = CopyDoorwayList(roomTemplate.doorwayList);
// Set parnet ID for room
if (roomNode.parentRoomNodeIDList.Count == 0) // Entrance
{
room.parentRoomID = "";
room.isPreviouslyVisited = true;
}
else
{
room.parentRoomID = roomNode.parentRoomNodeIDList[0];
}
return room;
}
/// <summary>
/// Select a random room node graph from the list of room node graphs
/// </summary>
private RoomNodeGraphSO SelectRandomRoomNodeGraph(List<RoomNodeGraphSO> roomNodeGraphList)
{
if (roomNodeGraphList.Count > 0)
{
return roomNodeGraphList[UnityEngine.Random.Range(0, roomNodeGraphList.Count)];
}
else
{
Debug.Log("No room node graphs in list");
return null;
}
}
private List<string> CopyStringList(List<string> oldStringList)
{
List<string> newStringList = new List<string>();
foreach(string stringVale in oldStringList)
{
newStringList.Add(stringVale);
}
return newStringList;
}
private List<Doorway> CopyDoorwayList(List<Doorway> oldDoorwayList)
{
List<Doorway> newDoorwayList = new List<Doorway>();
foreach (Doorway doorway in oldDoorwayList)
{
Doorway newDoorway = new Doorway();
newDoorway.position = doorway.position;
newDoorway.orientation = doorway.orientation;
newDoorway.doorPrefab = doorway.doorPrefab;
newDoorway.isConnected = doorway.isConnected;
newDoorway.isUnavailable = doorway.isUnavailable;
newDoorway.doorwayStartCopyPosition = doorway.doorwayStartCopyPosition;
newDoorway.doorwayCopyTileWidth = doorway.doorwayCopyTileWidth;
newDoorway.doorwayCopyTileHeight = doorway.doorwayCopyTileHeight;
newDoorwayList.Add(newDoorway);
}
return newDoorwayList;
}