private void GenerateChambers(int count) { // Create an array of chamber placements to decide. ChamberPlacement[] chamberPlacements = new ChamberPlacement[count + GENERATION_LOOK_AHEAD]; // Figure out placement for every chamber to create. bool hitConflict = false; for (int i = 0; i < chamberPlacements.Length; i++) { // Obtain the appropriate chamber prefab. Chamber chamberPrefab = null; if (i == 0 && _placedChambers.Count == 0) { // If we have not created any chambers yet, this chamber will need to be a starting chamber. chamberPrefab = GetRandomChamber(ChamberType.StartingCap); } else if (hitConflict) { // If we hit a conflict, we'll allow for any chamber here to minimize the chances. chamberPrefab = GetRandomChamber(ChamberType.Tunnel); } else { // Obtain our count of consecutive straight chambers beforehand. int straightCount = GetStraightChamberCount(chamberPlacements, i); // Obtain our chamber direction, making sure we hit the minimum amount of straights. ChamberDirection targetDirection = ChamberDirection.Straight; if (straightCount >= _minimumConsecutiveStraightChambers) { targetDirection = GetRandomChamberDirection(); } // Obtain our chamber with the given direction. chamberPrefab = GetRandomChamberWithDirection(targetDirection); } // Determine the positioning of our next chamber. Direction targetEntranceDirection = Direction.Left; Vector2 targetEntrancePoint = Vector2.zero; if (i > 0) { // We have determined placements in this run already, so look at the previous placement. ChamberPlacement lastChamberPlacement = chamberPlacements[i - 1]; targetEntranceDirection = lastChamberPlacement.ExitDirection.Inverse(); targetEntrancePoint = lastChamberPlacement.ExitPoint; } else if (_placedChambers.Count > 0) { // We have no placements in this run, look to the spawned chambers. ChamberPlacement lastChamberPlacement = _placedChambers[_placedChambers.Count - 1]; targetEntranceDirection = lastChamberPlacement.ExitDirection.Inverse(); targetEntrancePoint = lastChamberPlacement.ExitPoint; } else { // It's our first chamber, find a random orientation to simulate entry from. targetEntranceDirection = (Direction)_chamberRNG.Range(0, 2); } // Create our corresponding chamber placement to create and verify the validity of placements. chamberPlacements[i] = new ChamberPlacement(_chamberRNG, chamberPrefab, targetEntranceDirection); chamberPlacements[i].SetEntrancePoint(targetEntrancePoint); // Loop backward through the chamber placements to check for overlaps (skip immediate previous one since it will touch) bool overlapped = false; Bounds boundsA = chamberPlacements[i].Bounds; for (int x = i - 2; x >= 0; x--) { Bounds boundsB = chamberPlacements[x].Bounds; if (boundsA.Intersects(boundsB)) { // There was an overlap with chamberPlacement[i] and chamberPlacement[x], we'll want to regenerate. i = x - 1; overlapped = true; hitConflict = true; break; } } // If we overlapped already, we'll want to start our iteration from the new point we set. if (overlapped) { continue; } // Now we'll want to loop backwards through spawned chambers, and check for overlaps as well. overlapped = false; // Define the last chamber to start from, if we're generating our first placement, we'll want to skip the last spawned chamber since it will touch it. int lastChamber = (i == 0) ? _placedChambers.Count - 2 : _placedChambers.Count - 1; for (int x = lastChamber; x >= 0; x--) { Bounds boundsB = _placedChambers[x].Bounds; if (boundsA.Intersects(boundsB)) { // There was an overlap with chamberPlacement[i] and chamberPlacement[x], we'll want to regenerate. i = -1; overlapped = true; hitConflict = true; break; } } // If we overlapped already, we'll want to start our iteration from the new point we set. if (overlapped) { continue; } // Reset our conflict flag. hitConflict = false; } // Spawn all of the placed chambers. SpawnChambers(chamberPlacements, 0, count); }
private Chamber GetRandomChamberWithDirection(ChamberDirection chamberDirection) { int randomIndex = _chamberRNG.Range(0, _continuousChambersByDirection[chamberDirection].Count); return(_continuousChambersByDirection[chamberDirection].ElementAt(randomIndex)); }