예제 #1
0
        protected void AddDoors(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap, float doorProbability = 1f)
        {
            IEnumerator <Vector2Int> mapIter = IterateOverMap(map);

            while (mapIter.MoveNext())
            {
                Vector2Int current          = mapIter.Current;
                var        adjacentElements = map.GetAdjacentElements(current, true);

                int roomCells     = adjacentElements.Where(x => x == defaultRoomElement).Count();
                int corridorCells = adjacentElements.Where(x => x == defaultCorridorElement).Count();
                int doorCells     = adjacentElements.Where(x => x == defaultDoorElement).Count();

                if (map[current] == defaultCorridorElement)
                {
                    if ((corridorCells == 1 && doorCells == 0 && roomCells > 0 && roomCells < 4) ||
                        (corridorCells == 0 && doorCells == 0))
                    {
                        float exist = GameRNG.Randf();
                        if (exist < doorProbability)
                        {
                            map[current] = defaultDoorElement;
                        }
                    }
                }
            }
        }
예제 #2
0
        void GenerateBuildingRooms(ArrayGrid <MapElement> map, Vector2Int buildingPos, Vector2Int roomSize)
        {
            Rect building = new Rect();
            Rect smaller  = new Rect();

            buildingPos.x++;
            buildingPos.y++;

            building.position = buildingPos;
            building.size     = roomSize;

            smaller = building;

            smaller.min = smaller.min + Vector2Int.one;
            smaller.max = smaller.max - Vector2Int.one;

            map.FillArea(building, defaultBuildingWallElement);
            map.FillArea(smaller, defaultRoomElement);

            AddRecursiveRooms(map, defaultBuildingWallElement, new Vector2Int(innerBuildingRoomSize, innerBuildingRoomSize), smaller);

            // add a door leading out (improve to lead to nearest road)
            if (GameRNG.CoinToss())
            {
                if (GameRNG.CoinToss())
                {
                    int x = (int)building.min.x + GameRNG.Rand((int)roomSize.x - 2) + 1;
                    int y = (int)building.min.y;

                    map[x, y] = defaultDoorElement;
                }
                else
                {
                    int x = (int)building.min.x + GameRNG.Rand((int)roomSize.x - 2) + 1;
                    int y = (int)building.max.y - 1;

                    map[x, y] = defaultDoorElement;
                }
            }
            else
            {
                if (GameRNG.CoinToss())
                {
                    int x = (int)building.min.x;
                    int y = (int)building.min.y + GameRNG.Rand((int)roomSize.y - 2) + 1;

                    map[x, y] = defaultDoorElement;
                }
                else
                {
                    int x = (int)building.max.x - 1;
                    int y = (int)building.min.y + GameRNG.Rand((int)roomSize.y - 2) + 1;

                    map[x, y] = defaultDoorElement;
                }
            }
        }
예제 #3
0
        IEnumerator On()
        {
            float time = GameRNG.Rand(onTimeMin, onTimeMax);

            yield return(new WaitForSeconds(time));

            bodyCollider.enabled = true;
            currentState         = Off();
            yield break;
        }
예제 #4
0
        IEnumerator Off()
        {
            float time = GameRNG.Rand(offTimeMin, offTimeMax);

            yield return(new WaitForSeconds(time));

            ObjectIsInRange      = false;
            bodyCollider.enabled = false;
            currentState         = On();
            yield break;
        }
예제 #5
0
        private bool GenerateBuildings(ArrayGrid <MapElement> map)
        {
            while (buildingCount < requiredMinNumberOfBuildings)
            {
                Vector2Int roomSize   = new Vector2Int((int)(buildingSizeLimitX.Max * 2), (int)(buildingSizeLimitY.Max * 2));
                int        bufferSize = 2;

                for (;;)
                {
                    Vector2Int newBuildingAreaSize = new Vector2Int(roomSize.x + bufferSize, roomSize.y + bufferSize);
                    Vector2Int buildingPos         = Vector2Int.zero;
                    bool       result = map.GetPositionOfRandomAreaOfType(defaultFillElement, newBuildingAreaSize, ref buildingPos);
                    if (result)
                    {
                        //Debug.Log("Creating a building at " + buildingPos + " of size " + roomSize);
                        GenerateBuildingRooms(map, buildingPos, roomSize);
                        //map.FillArea(new Rect(buildingPos, roomSize), defaultDoorElement);
                        //map.FillArea(new Rect(buildingPos, Vector2.one), defaultTreeElement);
                        buildingCount++;
                        if (buildingCount >= requiredMinNumberOfBuildings)
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        if (GameRNG.CoinToss())
                        {
                            roomSize.x -= 1;
                        }
                        else
                        {
                            roomSize.y -= 1;
                        }

                        //time to start over
                        if (roomSize.x < buildingSizeLimitX.Min || roomSize.y < buildingSizeLimitY.Min)
                        {
                            Debug.Log("starting over because building size is too small and we don't have enough buildings. " + roomSize + " rooms so far: " + buildingCount);
                            buildingCount = 0;
                            generationAttempts++;
                            return(false);
                        }
                    }
                }
            }

            return(false);
        }
예제 #6
0
 public static T GetRandomElementFromList <T>(this List <T> list)
 {
     return(GameRNG.RandomElement(list));
 }
예제 #7
0
        IEnumerator GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap)
        {
            Vector2Int p1 = Vector2Int.zero;
            Vector2Int p2 = Vector2Int.zero;
            Vector2Int r  = Vector2Int.zero;

            List <Rect> rooms     = new List <Rect>();
            List <int>  roomTypes = new List <int>();

            int numberOfRooms = 0;

            for (numberOfRooms = 0; numberOfRooms < maxNumberOfRooms;)
            {
                if (numberOfRooms == 0)
                {
                    p1.x = map.w / 2 - GameRNG.Rand((int)roomSizeLimit.Max);
                    p1.y = map.h / 2 - GameRNG.Rand((int)roomSizeLimit.Max) - (int)roomSizeLimit.Min;

                    r.x = GameRNG.Rand((int)roomSizeLimit.Min, (int)roomSizeLimit.Min + (int)roomSizeLimit.Max);
                    r.y = roomSizeLimit.RandomValuei();

                    p2.x = p1.x + r.x;
                    p2.y = map.h / 2;

                    if (p2.x >= map.w)
                    {
                        continue;
                    }
                }
                else
                {
                    p1.x = GameRNG.Rand(map.w - (int)roomSizeLimit.Min) + 1;
                    p1.y = GameRNG.Rand(map.h - (int)roomSizeLimit.Min) / 2 + 1;

                    r.x = roomSizeLimit.RandomValuei();
                    r.y = roomSizeLimit.RandomValuei();

                    p2.x = p1.x + r.x;
                    p2.y = p1.y + r.y;

                    if (p2.x >= map.w - 1 || p2.y >= map.h / 2 + 3)
                    {
                        continue;
                    }
                }

                bool randAgain = false;
                for (int j = 0; j < rooms.Count; ++j)
                {
                    randAgain = true;
                    if (rooms[j].Contains(p1))
                    {
                        if (!rooms[j].Contains(p2))
                        {
                            randAgain = false;
                            roomTypes[j]++;
                        }
                        break;
                    }
                    if (rooms[j].Contains(p2))
                    {
                        if (!rooms[j].Contains(p1))
                        {
                            randAgain = false;
                            roomTypes[j]++;
                        }
                        break;
                    }
                }

                if (randAgain)
                {
                    continue;
                }

                // Create room
                Rect roomRect = Rect.MinMaxRect(p1.x, p1.y, p2.x, p2.y);

                rooms.Add(roomRect);
                roomTypes.Add(0);
                numberOfRooms++;
            }
            yield return(new WaitForEndOfFrame());

            // create mirror
            for (int i = 0; i < numberOfRooms; ++i)
            {
                Rect roomRect = rooms[i];

                if (mirrorVertical)
                {
                    Vector2Int min = Vector2Int.FloorToInt(roomRect.min);
                    Vector2Int max = Vector2Int.FloorToInt(roomRect.max);

                    min.x = map.w - min.x - 1;
                    max.x = map.w - max.x - 1;

                    p1.x = min.x;

                    min.x = max.x;
                    max.x = p1.x;

                    roomRect = Rect.MinMaxRect(min.x, min.y, max.x, max.y);
                }
                else
                {
                    Vector2Int min = Vector2Int.FloorToInt(roomRect.min);
                    Vector2Int max = Vector2Int.FloorToInt(roomRect.max);

                    min.y = map.h - min.y - 1;
                    max.y = map.h - max.y - 1;

                    p1.y = min.y;

                    min.y = max.y;
                    max.y = p1.y;

                    roomRect = Rect.MinMaxRect(min.x, min.y, max.x, max.y);
                }

                roomTypes.Insert(i, roomTypes[i]);
                rooms.Insert(i, roomRect);
            }

            yield return(new WaitForEndOfFrame());

            for (int i = 0; i < rooms.Count; ++i)
            {
                IEnumerator <Vector2Int> areaIter = Mathnv.GetAreaEnumerator(Vector2Int.FloorToInt(rooms[i].min), Vector2Int.FloorToInt(rooms[i].max));

                while (areaIter.MoveNext())
                {
                    Vector2Int current = areaIter.Current;
                    if (valueMap[current] == valueWall)
                    {
                        valueMap[current] = roomTypes[i];
                    }
                }
            }

            yield return(new WaitForEndOfFrame());

            int freeCells = 0;

            for (int x = 0; x < map.MaxValidPosition.x; ++x)
            {
                for (int y = 0; y < map.h / 2; ++y)
                {
                    int currentValue = valueMap[x, y];

                    int[] nearValues = new int[]
                    { valueMap[x + 1, y]
                      , valueMap[x, y + 1]
                      , valueMap[x + 1, y + 1] };


                    if (currentValue != nearValues[0] && nearValues[0] != valueWall)
                    {
                        valueMap[x, y] = valueWall;
                    }
                    if (currentValue != nearValues[1] && nearValues[1] != valueWall)
                    {
                        valueMap[x, y] = valueWall;
                    }
                    if (currentValue != nearValues[2] && nearValues[2] != valueWall)
                    {
                        valueMap[x, y] = valueWall;
                    }

                    if (currentValue != valueWall)
                    {
                        freeCells += 2;// +2 for mirror
                    }

                    valueMap[x, map.h - y - 1] = valueMap[x, y];//mirroring
                }
            }

            if (freeCells < (map.h * map.w * requiredPercentageOfMapNotWalls))
            {
                if (debugOutput)
                {
                    Dev.Log(string.Format("Not enough open map space. {0} < {1}", freeCells, (map.h * map.w * requiredPercentageOfMapNotWalls)));
                }
                success = false;
                yield break;
            }

            ConvertValuesToTiles(map, valueMap);
            ConnectClosestRooms(map, valueMap, true);
            ConvertValuesToTiles(map, valueMap);
            AddDoors(map, valueMap, 1f);

            success = true;
            yield break;
        }
예제 #8
0
        protected bool AddCorridor(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap, KeyValuePair <Vector2Int, Vector2Int> closestCells, bool straightConnections = false)
        {
            if (!map.IsValidPosition(closestCells.Key) || !map.IsValidPosition(closestCells.Value))
            {
                return(false);
            }

            // we start from both sides

            Vector2Int p0  = closestCells.Key;
            Vector2Int p1  = closestCells.Value;
            Vector2Int dir = new Vector2Int(p0.x > p1.x ? -1 : 1, p0.y > p1.y ? -1 : 1);

            bool firstHorizontal  = GameRNG.CoinToss();
            bool secondHorizontal = GameRNG.CoinToss();

            for (; ;)
            {
                if (!straightConnections)
                {
                    firstHorizontal  = GameRNG.CoinToss();
                    secondHorizontal = GameRNG.CoinToss();
                }

                // connect rooms
                dir.x = p0.x > p1.x ? -1 : 1;
                dir.y = p0.y > p1.y ? -1 : 1;

                if (p0.x != p1.x && p0.y != p1.y)
                {
                    if (firstHorizontal)
                    {
                        p0.x += dir.x;
                    }
                    else
                    {
                        p0.y += dir.y;
                    }
                }
                if (p0.x != p1.x && p0.y != p1.y)
                {
                    if (secondHorizontal)
                    {
                        p1.x -= dir.x;
                    }
                    else
                    {
                        p1.y -= dir.y;
                    }
                }

                if (valueMap[p0] == valueWall)
                {
                    valueMap[p0] = valueHall;
                }
                if (valueMap[p1] == valueWall)
                {
                    valueMap[p1] = valueHall;
                }

                // connect corridors if on the same level
                if (p0.x == p1.x)
                {
                    dir.y = p0.y > p1.y ? -1 : 1;
                    while (p0.y != p1.y)
                    {
                        p0.y += dir.y;
                        if (valueMap[p0] == valueWall)
                        {
                            valueMap[p0] = valueHall;
                        }
                    }

                    if (valueMap[p0] == valueWall)
                    {
                        valueMap[p0] = valueHall;
                    }

                    return(true);
                }

                if (p0.y == p1.y)
                {
                    dir.x = p0.x > p1.x ? -1 : 1;
                    while (p0.x != p1.x)
                    {
                        p0.x += dir.x;
                        if (valueMap[p0] == valueWall)
                        {
                            valueMap[p0] = valueHall;
                        }
                    }

                    if (valueMap[p0] == valueWall)
                    {
                        valueMap[p0] = valueHall;
                    }

                    return(true);
                }
            }

            //return true;
        }
예제 #9
0
        protected void ConnectClosestRooms(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap, bool withDoors, bool straightConnections = false)
        {
            int roomCount = 0;

            FillDisconnectedRoomsWithDifferentValues(map, valueMap, ref roomCount);

            List <List <Vector2Int> > rooms = (new List <Vector2Int> [roomCount]).ToList();

            for (int i = 0; i < rooms.Count; ++i)
            {
                rooms[i] = new List <Vector2Int>();
            }

            IEnumerator <Vector2Int> mapIter = IterateOverMap(map);

            while (mapIter.MoveNext())
            {
                Vector2Int current = mapIter.Current;
                if (valueMap[current] != valueWall)
                {
                    if (valueMap.GetAdjacentElementsOfType(current, false, valueWall).Count > 0)
                    {
                        int roomIndex = valueMap[current] - 1;
                        rooms[roomIndex].Add(current);
                    }
                }
            }

            if (rooms.Count < 2)
            {
                return;
            }

            // for warshall algorithm
            // set the connection matrix

            GameRNG.RandomShuffle(rooms);

            List <List <bool> > roomConnections   = (new List <bool> [rooms.Count]).ToList();
            List <List <bool> > transitiveClosure = (new List <bool> [rooms.Count]).ToList();;
            List <List <int> >  distanceMatrix    = (new List <int> [rooms.Count]).ToList();
            List <List <KeyValuePair <Vector2Int, Vector2Int> > > closestCellsMatrix = (new List <KeyValuePair <Vector2Int, Vector2Int> > [rooms.Count]).ToList();

            for (int a = 0; a < rooms.Count; ++a)
            {
                roomConnections[a]    = (new bool[rooms.Count]).ToList();
                transitiveClosure[a]  = (new bool[rooms.Count]).ToList();
                distanceMatrix[a]     = (new int[rooms.Count]).ToList();
                closestCellsMatrix[a] = (new KeyValuePair <Vector2Int, Vector2Int> [rooms.Count]).ToList();

                for (int b = 0; b < rooms.Count; ++b)
                {
                    roomConnections[a][b] = false;
                    distanceMatrix[a][b]  = int.MaxValue;
                }
            }

            IEnumerator <Vector2Int> roomAreas = IterateOverArea(rooms.Count, rooms.Count);

            // find the closest cells for each room - Random closest cell
            while (roomAreas.MoveNext())
            {
                Vector2Int ci = roomAreas.Current;
                if (ci.x == ci.y)
                {
                    continue;
                }

                KeyValuePair <Vector2Int, Vector2Int> closestCells = new KeyValuePair <Vector2Int, Vector2Int>();

                foreach (Vector2Int cellA in rooms[ci.y])
                {
                    foreach (Vector2Int cellB in rooms[ci.x])
                    {
                        int distAB = Mathf.CeilToInt((cellA - cellB).magnitude);

                        if ((distAB < distanceMatrix[ci.y][ci.x]) || (distAB == distanceMatrix[ci.y][ci.x] && GameRNG.CoinToss()))
                        {
                            closestCells = new KeyValuePair <Vector2Int, Vector2Int>(cellA, cellB);
                            distanceMatrix[ci.y][ci.x] = distAB;
                        }
                    }
                }

                closestCellsMatrix[ci.y][ci.x] = closestCells;
            }


            // Now connect the rooms to the closest ones

            for (int roomA = 0; roomA < rooms.Count; ++roomA)
            {
                int minDist     = int.MaxValue;
                int closestRoom = 0;

                for (int roomB = 0; roomB < rooms.Count; ++roomB)
                {
                    if (roomA == roomB)
                    {
                        continue;
                    }

                    int distance = distanceMatrix[roomA][roomB];
                    if (distance < minDist)
                    {
                        minDist     = distance;
                        closestRoom = roomB;
                    }
                }

                // connect roomA to closest one

                KeyValuePair <Vector2Int, Vector2Int> closestCells = closestCellsMatrix[roomA][closestRoom];

                if (!roomConnections[roomA][closestRoom] && AddCorridor(map, valueMap, closestCells, straightConnections))
                {
                    roomConnections[roomA][closestRoom] = true;
                    roomConnections[closestRoom][roomA] = true;
                }
            }

            // The closest rooms connected. Connect the rest until all areas are connected

            for (int toConnectA = 0; toConnectA != -1;)
            {
                roomAreas = IterateOverArea(rooms.Count, rooms.Count);

                while (roomAreas.MoveNext())
                {
                    Vector2Int ci = roomAreas.Current;
                    transitiveClosure[ci.y][ci.x] = roomConnections[ci.y][ci.x];
                }

                roomAreas = IterateOverArea(rooms.Count, rooms.Count);

                while (roomAreas.MoveNext())
                {
                    Vector2Int ci = roomAreas.Current;
                    if (transitiveClosure[ci.y][ci.x] == true && ci.y != ci.x)
                    {
                        for (int ciZ = 0; ciZ < rooms.Count; ++ciZ)
                        {
                            if (transitiveClosure[ci.x][ciZ] == true)
                            {
                                transitiveClosure[ci.y][ciZ] = true;
                                transitiveClosure[ciZ][ci.y] = true;
                            }
                        }
                    }
                }

                toConnectA = -1;

                roomAreas = IterateOverArea(rooms.Count, rooms.Count);

                while (roomAreas.MoveNext() && toConnectA == -1)
                {
                    Vector2Int ci = roomAreas.Current;
                    if (transitiveClosure[ci.y][ci.x] == false && ci.x != ci.y)
                    {
                        toConnectA = ci.y;
                        break;
                    }
                }

                if (toConnectA != -1)
                {
                    int toConnectB = toConnectA;
                    while (toConnectB == toConnectA)
                    {
                        toConnectB = GameRNG.Rand(rooms.Count);
                    }

                    KeyValuePair <Vector2Int, Vector2Int> closestCells = closestCellsMatrix[toConnectA][toConnectB];

                    AddCorridor(map, valueMap, closestCells, straightConnections);
                    {
                        roomConnections[toConnectA][toConnectB] = true;
                        roomConnections[toConnectB][toConnectA] = true;
                    }
                }
            }
        }
예제 #10
0
파일: Range.cs 프로젝트: Kerr1291/common
 public float RandomNormalizedValue()
 {
     return(NormalizedValue(GameRNG.Rand(Min, Max)));
 }
예제 #11
0
파일: Range.cs 프로젝트: Kerr1291/common
 public float RandomValuef()
 {
     return(GameRNG.Rand(Min, Max));
 }
예제 #12
0
파일: Range.cs 프로젝트: Kerr1291/common
 public int RandomValuei()
 {
     return(GameRNG.Rand((int)Min, (int)Max));
 }
예제 #13
0
파일: Maze.cs 프로젝트: Kerr1291/common
        bool GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap)
        {
            List <Vector2Int> drillers = new List <Vector2Int>();

            drillers.Add(new Vector2Int(map.w / 2, map.h / 2));
            while (drillers.Count > 0)
            {
                int i = 0;
                while (i < drillers.Count)
                {
                    Vector2Int di = drillers[i];

                    bool removeDriller = false;
                    int  behavior      = GameRNG.Rand(4);
                    if (behavior == 0)
                    {
                        di.y -= 2;
                        if (di.y < 0 || map[di] == defaultCorridorElement)
                        {
                            removeDriller = (!allowLoops || (allowLoops && GameRNG.Randf() < loopProb));
                        }
                        if (!removeDriller)
                        {
                            map[di.x, di.y + 1] = defaultCorridorElement;
                        }
                    }
                    else if (behavior == 1)
                    {
                        di.y += 2;
                        if (di.y >= map.h || map[di] == defaultCorridorElement)
                        {
                            removeDriller = true;
                        }
                        else
                        {
                            map[di.x, di.y - 1] = defaultCorridorElement;
                        }
                    }
                    else if (behavior == 2)
                    {
                        di.x -= 2;
                        if (di.x < 0 || map[di] == defaultCorridorElement)
                        {
                            removeDriller = true;
                        }
                        else
                        {
                            map[di.x + 1, di.y] = defaultCorridorElement;
                        }
                    }
                    else if (behavior == 3)
                    {
                        di.x += 2;
                        if (di.x >= map.w || map[di] == defaultCorridorElement)
                        {
                            removeDriller = true;
                        }
                        else
                        {
                            map[di.x - 1, di.y] = defaultCorridorElement;
                        }
                    }

                    if (removeDriller)
                    {
                        drillers.RemoveAt(i);
                    }
                    else
                    {
                        drillers[i] = di;
                        drillers.Add(di);
                        drillers.Add(di);
                        map[di] = defaultCorridorElement;
                        ++i;
                    }
                }
            }

            return(true);
        }
예제 #14
0
파일: AntNest.cs 프로젝트: Kerr1291/common
        bool GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap)
        {
            map[map.CenterPosition] = defaultCorridorElement;

            Vector2Int s0 = Vector2Int.zero;
            Vector2    s1 = Vector2Int.zero;
            Vector2Int p  = Vector2Int.zero;
            Vector2    d  = Vector2Int.zero;

            int iterCount = map.Count / 3;

            for (int i = 0; i < iterCount; i++)
            {
                s1 = GameRNG.RandomPointOnCircle(map.Size.DivideBy(2)) + map.CenterPosition;

                d.x = strideLimitX.RandomNormalizedValue();
                d.y = strideLimitY.RandomNormalizedValue();

                d.x -= .5f;
                d.y -= .5f;

                int counter = 0;
                for (; ;)
                {
                    //try again
                    if (counter > maxTunnelIterations)
                    {
                        --i;
                        break;
                    }

                    s1 += d;

                    p = Vector2Int.FloorToInt(s1);
                    p = map.Wrap(p);

                    if (map.IsValidPosition(p) && map.GetAdjacentPositionsOfType(p, false, defaultCorridorElement).Count > 0)
                    {
                        map[p] = defaultCorridorElement;
                        break;
                    }
                }
            }

            if (placeRooms)
            {
                var areaIter = Mathnv.GetAreaEnumerator(Vector2Int.one, map.MaxValidPosition - Vector2Int.one);
                while (areaIter.MoveNext())
                {
                    Vector2Int current = areaIter.Current;

                    Range limitX = new Range(map.w / 2 - strideLimitX.Min, map.w / 2 + strideLimitX.Min);
                    Range limitY = new Range(map.h / 2 - strideLimitY.Min, map.h / 2 + strideLimitY.Min);

                    if ((limitX.Contains(current.x) && limitY.Contains(current.y)) || map[current] == defaultWallElement)
                    {
                        continue;
                    }

                    int n = map.GetAdjacentPositionsOfType(current, false, defaultCorridorElement).Count;

                    if (n == 1)
                    {
                        Rect room = new Rect(Vector2.zero, new Vector2(roomSizeX.RandomValuei(), roomSizeY.RandomValuei()));

                        var roomIter = Mathnv.GetAreaEnumerator(Vector2Int.FloorToInt(room.min), Vector2Int.FloorToInt(room.max));
                        while (roomIter.MoveNext())
                        {
                            Vector2Int rCurrent = roomIter.Current;
                            map[current + rCurrent] = defaultRoomElement;
                        }
                    }
                }
            }

            return(true);
        }
예제 #15
0
        bool GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap)
        {
            Vector2Int s0   = Vector2Int.zero;
            Vector2Int s1   = Vector2Int.zero;
            Vector2Int p0   = Vector2Int.zero;
            Vector2Int p1   = Vector2Int.zero;
            Vector2Int p2   = Vector2Int.zero;
            Vector2Int diff = Vector2Int.zero;

            List <Rect> rooms     = new List <Rect>();
            List <int>  roomTypes = new List <int>();

            // Place rooms
            for (int i = 0; i < maxNumberOfRooms; ++i)
            {
                // size of room
                s1 = new Vector2Int(roomSizeLimitX.RandomValuei(), roomSizeLimitY.RandomValuei());

                bool result = map.GetPositionOfRandomAreaOfType(defaultWallElement, s1 + roomSizeOffset, ref p0);
                if (result)
                {
                    p0 = p0.AddScalar(2);

                    // Connect the room to existing one

                    if (rooms.Count > 0)
                    {
                        int selectedRoom = GameRNG.Rand(rooms.Count);

                        Rect r = rooms[selectedRoom];

                        // center of this room
                        p1 = p0 + s1.DivideBy(2);

                        // center of second room
                        p2 = Vector2Int.FloorToInt(r.center);

                        // found the way to connect rooms
                        diff = p2 - p1;

                        diff.x = Mathf.Abs(diff.x);
                        diff.y = Mathf.Abs(diff.y);

                        s0 = p1;

                        while (!(diff.x == 0 && diff.y == 0))
                        {
                            if (GameRNG.Rand(diff.x + diff.y) < diff.x)// move horizontally
                            {
                                diff.x--;
                                s0.x += (s0.x > p2.x ? -1 : 1);
                            }
                            else
                            {
                                diff.y--;
                                s0.y += (s0.y > p2.y ? -1 : 1);
                            }

                            // Check what is on that position
                            if (map[s0] == defaultRoomElement)
                            {
                                break;
                            }
                            else if (map[s0] == defaultCorridorElement)
                            {
                                if (GameRNG.CoinToss())
                                {
                                    break;
                                }
                            }

                            map[s0] = defaultCorridorElement;
                        }
                    }

                    // add to list of rooms

                    Rect roomRect = Rect.MinMaxRect(p0.x, p0.y, p0.x + s1.x, p0.y + s1.y);

                    rooms.Add(roomRect);
                    roomTypes.Add(i);

                    // draw_room

                    int roomType = GameRNG.Rand(4); //select the type of room we should generate

                    if (s1.x == s1.y)
                    {
                        roomType = 3;
                    }

                    if (roomType != 2)
                    {
                        IEnumerator <Vector2Int> areaIter = Mathnv.GetAreaEnumerator(s1);

                        while (areaIter.MoveNext())
                        {
                            Vector2Int current = areaIter.Current;
                            if (roomType == 0 || roomType == 1)// rectangle room
                            {
                                map[p0 + current] = defaultRoomElement;
                            }
                            else// round room
                            {
                                if (Vector2Int.Distance(s1.DivideBy(2), current) < s1.x / 2)
                                {
                                    map[p0 + current] = defaultRoomElement;
                                }
                            }
                        }
                    }
                    else //diamond
                    {
                        IEnumerator <Vector2Int> areaIter = Mathnv.GetAreaEnumerator(s1.DivideBy(2) + Vector2Int.one);

                        while (areaIter.MoveNext())
                        {
                            Vector2Int current = areaIter.Current;
                            if (current.y >= current.x)
                            {
                                int x0 = p0.x + current.x + s1.DivideBy(2).x;
                                int x1 = p0.x + s1.DivideBy(2).x - current.x;

                                int y0 = p0.y + current.y;
                                int y1 = p0.y + s1.y - current.y;

                                map[x0, y0] = defaultRoomElement;
                                map[x0, y1] = defaultRoomElement;
                                map[x1, y0] = defaultRoomElement;
                                map[x1, y1] = defaultRoomElement;
                            }
                        }
                    }
                } // end of room addition
            }

            return(true);
        }
예제 #16
0
        void AddRecursiveRooms(ArrayGrid <MapElement> map, MapElement roomElement, Vector2Int minRoomSize, Rect room, bool withDoors = true)
        {
            int sizeX = (int)room.size.x;

            if (sizeX % 2 != 0)
            {
                sizeX -= GameRNG.CoinToss() ? 1 : 0;
            }

            int sizeY = (int)room.size.y;

            if (sizeY % 2 != 0)
            {
                sizeY -= GameRNG.CoinToss() ? 1 : 0;
            }

            bool splitHorizontal = false;

            if (sizeY * 4 > sizeX)
            {
                splitHorizontal = true;
            }
            if (sizeX * 4 > sizeY)
            {
                splitHorizontal = false;
            }
            else
            {
                splitHorizontal = GameRNG.CoinToss();
            }

            if (splitHorizontal)
            {
                if (sizeY / 2 < minRoomSize.y)
                {
                    return;
                }
                int split = sizeY / 2 + GameRNG.Rand(sizeY / 2 - (int)minRoomSize.y);
                for (int x = (int)room.min.x; x < (int)room.max.x; ++x)
                {
                    map[x, (int)room.min.y + split] = roomElement;
                }

                if (withDoors)
                {
                    map[(int)room.min.x + GameRNG.Rand(sizeX - 1) + 1, (int)room.min.y + split] = defaultDoorElement;
                }

                Rect       newRoom = room;
                Vector2Int newMax  = newRoom.max.ToInt();
                newMax.y    = room.min.ToInt().y + split;
                newRoom.max = newMax;
                AddRecursiveRooms(map, roomElement, minRoomSize, newRoom, withDoors);

                newRoom = room;
                Vector2Int newMin = newRoom.min.ToInt();
                newMin.y    = room.min.ToInt().y + split;
                newRoom.min = newMin;
                AddRecursiveRooms(map, roomElement, minRoomSize, newRoom, withDoors);
            }
            else
            {
                if (sizeX / 2 < minRoomSize.x)
                {
                    return;
                }
                int split = sizeX / 2 + GameRNG.Rand(sizeX / 2 - (int)minRoomSize.x);
                for (int y = (int)room.min.y; y < (int)room.max.y; ++y)
                {
                    map[(int)room.min.x + split, y] = roomElement;
                }

                if (withDoors)
                {
                    map[(int)room.min.x + split, (int)room.min.y + GameRNG.Rand(sizeY - 1) + 1] = defaultDoorElement;
                }

                Rect       newRoom = room;
                Vector2Int newMax  = newRoom.max.ToInt();
                newMax.x    = room.min.ToInt().x + split;
                newRoom.max = newMax;
                AddRecursiveRooms(map, roomElement, minRoomSize, newRoom, withDoors);

                newRoom = room;
                Vector2Int newMin = newRoom.min.ToInt();
                newMin.x    = room.min.ToInt().x + split;
                newRoom.min = newMin;
                AddRecursiveRooms(map, roomElement, minRoomSize, newRoom, withDoors);
            }
        }