/// <summary> /// Create the corridor to connect to the parent cell /// </summary> /// <param name="parentNode">The node's parent node</param> public void CreateCorridorToParent(BinarySpacePartitionTreeNode parentNode) { // Check if the node has any children since we want to start with the leaf nodes first if (m_children.Count > 0) { // Go through each child and connect them with this node for (int i = 0; i < m_children.Count; i++) { m_children[i].CreateCorridorToParent(this); } } // For the root node since it doesn't have anything to connect to if (parentNode.Centre == Vector2.zero) { return; } // Based on the parent's position to the current node, spawn the corridor // Should only be in 4 straight line directions due to the splitting keeping one axis the same // Room is left of the parent room if (m_centre.x < parentNode.Centre.x) { CreateCorridor(m_centre.x, parentNode.Centre.x, true, m_centre.y); } // Room is right of the parent room else if (m_centre.x > parentNode.Centre.x) { CreateCorridor(parentNode.Centre.x, m_centre.x, true, m_centre.y); } // Room is below the parent room else if (m_centre.y < parentNode.Centre.y) { CreateCorridor(m_centre.y, parentNode.Centre.y, false, m_centre.x); } // Room is above the parent room else { CreateCorridor(parentNode.Centre.y, m_centre.y, false, m_centre.x); } }
/// <summary> /// Split up the grid to create cells for the rooms /// </summary> public void CreateCells() { // Create a queue of which nodes to split // Used a queue so it does all children in a row before starting a new row in the tree Queue <BinarySpacePartitionTreeNode> splitQueue = new Queue <BinarySpacePartitionTreeNode>(); BinarySpacePartitionTreeNode currentNode; // Bot left corner is set to (1,1) to keep the bot and left parts of the grid free for walls to prevent out of bounds errors Vector2 rootBotLeftCorner = new Vector2(botCornerOffsetForWall, botCornerOffsetForWall); // Need to +1 the centre or the child nodes won't line up correctly and won't connect to the root with corridors due to the (1, 1) bot corner Vector2 rootCentre = new Vector2((m_dungeonSizeXInt / getCentre) + botCornerOffsetForWall, (m_dungeonSizeZInt / getCentre) + botCornerOffsetForWall); // Create the root and add it to the tree m_treeRootNode = new BinarySpacePartitionTreeNode(rootCentre, m_dungeonSizeXInt, m_dungeonSizeZInt, rootBotLeftCorner, ref m_spawnGrid, this); splitQueue.Enqueue(m_treeRootNode); for (int i = 0; i < m_splitAmount; i++) { // Stop if queue is empty if (splitQueue.Count == empty) { return; } // Remove the node at the start of the queue but save it to split it currentNode = splitQueue.Dequeue(); currentNode.SplitCell(); // For each child made from the split, add it to the queue for (int j = 0; j < currentNode.Children.Count; j++) { splitQueue.Enqueue(currentNode.Children[j]); } } }
/// <summary> /// Create the nodes made by the split and add them to the tree /// </summary> /// <param name="node1Width">Width of the 1st node</param> /// <param name="node1Height">Height of the 1st node</param> /// <param name="node2Width">Width of the 2nd node</param> /// <param name="node2Height">Height of the 2nd node</param> /// <param name="vertically">If the cell was cut vertically or horizontally</param> /// <param name="splitPos">Where the split happened in the cell</param> void AddSplitNodesToTree(int node1Width, int node1Height, int node2Width, int node2Height, bool vertically, int splitPos) { // ************************************************* // How they are split and bot left corners // ____________________________________________ // | | | // | | | // | 1st Node | 2nd Node | // | | | // | | | // |____________________|______________________| // ^ 1st node bot left ^ Split Position and new bot left corner for 2nd node // ____________________________________________ // | | // | | // | 2nd Node | // Split Position and new bot left corner for 2nd node > |-------------------------------------------| // | 1st Node | // |___________________________________________| // ^ 1st node bot left // ************************************************* // ************************************************* // First Node (Left or bot cell of the split) // Centre is just half of the new width and height Vector2 centre = new Vector2(node1Width / getCentre, node1Height / getCentre); // Apply the offset to the centre so the outputted room is in the correct location // Without this it will spawn always with the bot left corner at (0,0) centre.x += m_botLeftCorner.x; centre.y += m_botLeftCorner.y; // Create and attach the new cell made // Uses the same bot left corner at the current node since its the left/bot node so it would not have moved BinarySpacePartitionTreeNode node = new BinarySpacePartitionTreeNode(centre, node1Width, node1Height, m_botLeftCorner, ref m_spawnGrid, m_binarySpacePartition); AttachNode(node); // ************************************************* // ************************************************* // Second Node (Right or top cell of the split) centre = new Vector2(node2Width / getCentre, node2Height / getCentre); // Save where the new bot left will be Vector2 botLeft = m_botLeftCorner; // Set the right/top side node's centre position // Add the split position to the centre to make it the right/top side of the parent // If this is not added it will be outputted to the same location as the left/bot side // Have to apply it to the new corner since it has been moved from the parents' // Due to being the right/top cell and is not using that corner anymore // ____________________________________________ // | | | // | | | | | // | Without adding | With adding splitPos | // | splitPos | | | // | | | | // |____________________|______________________| // ^ Centre ^ Centre if (vertically) { centre.x += splitPos; botLeft.x += splitPos; } else { centre.y += splitPos; botLeft.y += splitPos; } // Apply the offset to the centre so the outputted room is in the correct location // Without this it will spawn always with the bot left corner at (0,0) centre.x += m_botLeftCorner.x; centre.y += m_botLeftCorner.y; // Create and attach the other node node = new BinarySpacePartitionTreeNode(centre, node2Width, node2Height, botLeft, ref m_spawnGrid, m_binarySpacePartition); AttachNode(node); // ************************************************* }
/// <summary> /// Remove a cell connected to this cell /// </summary> /// <param name="node">The cell to remove</param> public void DetachNode(BinarySpacePartitionTreeNode node) { m_children.Remove(node); }
/// <summary> /// Attach another cell to this current cell /// </summary> /// <param name="node">The new cell that connects to this one</param> public void AttachNode(BinarySpacePartitionTreeNode node) { m_children.Add(node); }