Пример #1
0
    private void InstantiateCriticalPathRooms()
    {
        int i = 0;                              // grid position we are currently spawning
        int j = UnityEngine.Random.Range(0, 4); // grid position we are currently spawning

        Direction?prev_dir = null;

        bool hasPlacedExitDoor = false;

        while (true)
        {
            //Debug.Log("running i=" + i + " j=" + j);

            bool thisIsFirstRoom = prev_dir == null;

            // where we can go from current i, j
            Direction[] validDirections = Array.FindAll(allDirections, d =>
                                                        d != Direction.Top && // never go up
                                                        (j > 0 || d != Direction.Left) && // do not go left if we're at the leftmost room already
                                                        (j < 3 || d != Direction.Right) && // do not go right if we're at the rightmost room already
                                                        (i < 3 || d != Direction.Bottom) && // do not go bottom if we're at the lowest room already
                                                        (grid[i + d.IndexDelta().i, j + d.IndexDelta().j] == null) // do not go on an already spawned room
                                                        );

            // chosen direction
            Direction?dir = validDirections.GetRandNul();

            // filter prefabs by rooms that have an entrance in the chosen exit direction
            GameObject[] roomPrefabsThatHaveExitInChosenDir = Array.FindAll(roomPrefabs, rp =>
            {
                RoomSpec spec = rp.GetComponentInChildren <RoomSpec>(true);
                return(spec != null &&
                       (prev_dir == null || spec.HasExit(prev_dir.Value.Invert())) &&  // entrance from previous dir
                       (dir == null || spec.HasExit(dir.Value)) &&  // exit in next dir
                       (!thisIsFirstRoom || spec.canSpawnPlayer) &&  // if this is the first room we are spawning, it must have a player spawn location
                       (dir != null || spec.hasExitDoor)     // has exit door if it is last spawning room
                       );
            }
                                                                            );

            // pick one randomly
            GameObject roomPrefab = roomPrefabsThatHaveExitInChosenDir.GetRand();
            if (roomPrefab == null)
            {
                throw new Exception("thisIsFirstRoom=" + thisIsFirstRoom + " add a room prefab that has an exit of type " + (dir != null ? dir.Value.ToString() : "null"));
            }

            // spawn
            //Debug.Log("spawning i=" + i + " j=" + j);
            float x = (j - 1) * roomSize - roomSize / 2;
            float y = -((i - 1) * roomSize - roomSize / 2);
            grid[i, j] = Instantiate(roomPrefab, new Vector3(x, y, 0), Quaternion.identity).GetComponent <RoomSpec>();

            // place the player (already spawned) here
            if (thisIsFirstRoom)
            {
                player.transform.position = grid[i, j].playerSpawnLocation.transform.position;
            }

            // put exit door and stop
            if (dir == null)
            {
                exitDoor.transform.position = grid[i, j].exitSpawnLocation.transform.position;
                break;
            }

            // save values as previous
            prev_dir = dir;

            // move pointers in the next dir
            i += dir.Value.IndexDelta().i;
            j += dir.Value.IndexDelta().j;
        }
    }