Exemplo n.º 1
0
            /// <summary>
            /// Given an empty position in the grid, find all of the viable room prefabs
            /// for that position that meets the following requirements:
            /// - PrefabHasRequiredDirections: Neighbouring rooms may have
            ///   doors that need to lead into a room at the given position, and the
            ///   random prefab must have associated doors so that the doors in
            ///   the neighbouring rooms are not blocked off.
            /// - PrefabIsEnclosedIfRequired: At the end of level generation,
            ///   the final chosen room prefabs must be fully enclosed so that the level
            ///   does not contain doors that lead to nowhere.
            /// - PrefabHasSpaceInFrontOfDoors: Similar to PrefabHasRequiredDirections,
            ///   neighbouring rooms may NOT have a door that leads into a room at
            ///   the given position, so the chosen prefab must not have a door
            ///   in that direction as it would be blocked off by the existing
            ///   neighbouring room.
            /// - GuaranteedPrefabHasNotBeenSpawned: Prefabs marked as
            ///   guaranteed spawn for a given depth should only be spawned once
            ///   for that depth. If the prefab was already spawned, it is no
            ///   longer viable.
            /// </summary>
            /// <param name="position">
            /// The position in the grid of rooms. The units used are relative
            /// to the starting room. So 0,0 is the starting room. 1,0 is the
            /// room east of that, etc.
            /// </param>
            /// <param name="enclosedPrefabRequired">
            /// Whether or not the random prefab needs to be enclosed, meaning
            /// all of its doors will connect to already existing rooms and the
            /// room will contain no unconnected doors.
            /// </param>
            /// <returns>
            /// An array of room prefabs that meets the requirements for the given position.
            /// </returns>
            private GameObject[] FindViablePrefabsFor(Vector2Int position, bool enclosedPrefabRequired, float depthPercentage)
            {
                HashSet <Direction> requiredDirections = FindRequiredDirectionsFor(position);

                bool PrefabHasRequiredDirections(GameObject prefab)
                {
                    RoomConnectionBehaviour prefabRoom = prefab.GetComponent <RoomConnectionBehaviour>();

                    return(requiredDirections.All(direction => prefabRoom.Directions.Contains(direction)));
                }

                bool PrefabIsEnclosedIfRequired(GameObject prefab)
                {
                    if (!enclosedPrefabRequired)
                    {
                        return(true);
                    }
                    RoomConnectionBehaviour prefabRoom = prefab.GetComponent <RoomConnectionBehaviour>();

                    return(requiredDirections.SetEquals(prefabRoom.Directions));
                }

                bool PrefabHasSpaceInFrontOfDoors(GameObject prefab)
                {
                    RoomConnectionBehaviour prefabRoom = prefab.GetComponent <RoomConnectionBehaviour>();

                    bool DoorNotRequired(DoorConnectionBehaviour door) => !requiredDirections.Contains(door.Direction);

                    IEnumerable <DoorConnectionBehaviour> nonRequiredDoors = prefabRoom.Doors.Where(DoorNotRequired);

                    return(nonRequiredDoors.All(door => PositionInDirectionIsEmpty(position, door.Direction)));
                }

                bool OnlyOnceGuaranteePrefabHasNotBeenSpawned(GameObject prefab)
                {
                    RoomGenerationBehaviour roomGenerationBehaviour = prefab.GetComponent <RoomGenerationBehaviour>();
                    SpawnProbability?       spawnProbability        = roomGenerationBehaviour.GetSpawnProbability(depthPercentage);

                    if (spawnProbability.HasValue && spawnProbability.Value.Guarantee == SpawnProbability.SpawnGuarantee.SpawnOnlyOnce)
                    {
                        return(!HasSpawnedGuaranteedRoomPrefab(prefab, spawnProbability.Value.DepthPercentage));
                    }
                    return(true);
                }

                IEnumerable <GameObject> viablePrefabs = _roomPrefabs
                                                         .Where(PrefabHasRequiredDirections)
                                                         .Where(PrefabIsEnclosedIfRequired)
                                                         .Where(PrefabHasSpaceInFrontOfDoors)
                                                         .Where(OnlyOnceGuaranteePrefabHasNotBeenSpawned);

                return(viablePrefabs.ToArray());
            }
Exemplo n.º 2
0
            /// <summary>
            /// Verifies that the RoomGrid has placed all guaranteed rooms,
            /// this is used as a fail-safe to ensure the level is not missing
            /// vital rooms.
            /// </summary>
            /// <returns>
            /// true if the RoomGrid contains all of the guaranteed rooms level
            /// otherwise false.
            /// </returns>
            public bool Verify()
            {
                foreach (GameObject roomPrefab in _roomPrefabs)
                {
                    RoomGenerationBehaviour roomGenerationBehaviour = roomPrefab.GetComponent <RoomGenerationBehaviour>();
                    List <SpawnProbability> spawnProbabilities      = roomGenerationBehaviour.SpawnProbabilities;

                    foreach (SpawnProbability spawnProbability in spawnProbabilities)
                    {
                        if (spawnProbability.Guarantee == SpawnProbability.SpawnGuarantee.None)
                        {
                            continue;
                        }

                        bool verified = HasSpawnedGuaranteedRoomPrefab(roomPrefab, spawnProbability.DepthPercentage);
                        if (!verified)
                        {
                            return(false);
                        }
                    }
                }

                return(true);
            }