Пример #1
0
        public void RandomShuffle <T>(List <T> elements)
        {
            int n = elements.Count();

            for (int i = n - 1; i > 0; --i)
            {
                Mathnv.Swap(elements, i, Rand(i + 1));
            }
        }
Пример #2
0
        public static IEnumerator <Vector2Int> GetEnumerator2D <T>(this ArrayGrid <T> grid)
        {
            IEnumerator <Vector2Int> iterator = Mathnv.GetAreaEnumerator(grid.w, grid.h);

            while (iterator.MoveNext())
            {
                yield return(iterator.Current);
            }
        }
Пример #3
0
        public static Rect SetMinMax(this Rect input, Vector2 min, Vector2 max)
        {
            Vector2 rMin = Mathnv.Min(min, max);
            Vector2 rMax = Mathnv.Max(min, max);

            Rect r = new Rect((rMax - rMin) * .5f + rMin, rMax - rMin);

            return(r);
        }
Пример #4
0
        public IEnumerator RenderChunks()
        {
            var visibleIter = Mathnv.GetAreaEnumerator(MapSize);

            while (visibleIter.MoveNext())
            {
                Vector2Int current = visibleIter.Current;
                this[current].GenerateMesh(true);
            }
            yield break;
        }
Пример #5
0
        // random normalized vector
        //from [ [min.x,min.y] , [max.x,max.y] ]
        public Vector3 RandVec3Normalized(float min, float max)
        {
            if (min > max)
            {
                Mathnv.Swap(ref min, ref max);
            }
            Vector3 vec = new Vector3(Rand(min, max), Rand(min, max), Rand(min, max)).normalized;

            vec.Normalize();
            return(vec);
        }
Пример #6
0
 // rolling min or max will be rare, but rolling exactly between the two will be common
 public double GaussianRandom(double min, double max)
 {
     if (min == max)
     {
         return(min);
     }
     if (min > max)
     {
         Mathnv.Swap <double>(ref min, ref max);
     }
     min /= 3;
     max /= 3;
     return(Rand(min, max) + Rand(min, max) + Rand(min, max));;
 }
Пример #7
0
        public int Rand(int a, int b)
        {
            if (a == b)
            {
                return(a);
            }
            if (a > b)
            {
                Mathnv.Swap(ref a, ref b);
            }

            int c = b - a;

            return(a + Randi() % c);
        }
Пример #8
0
        public double Rand(double a, double b)
        {
            if (a == b)
            {
                return(a);
            }
            if (a > b)
            {
                Mathnv.Swap(ref a, ref b);
            }

            double c = b - a;

            return(a + Randd() * c);
        }
Пример #9
0
        public float Rand(float a, float b)
        {
            if (a == b)
            {
                return(a);
            }
            if (a > b)
            {
                Mathnv.Swap(ref a, ref b);
            }

            float c = b - a;

            return(a + Randf() * c);
        }
Пример #10
0
        public void CreateChunks()
        {
            //Vector2Int center = Vector2Int.FloorToInt(new Vector2(MapSize.x, MapSize.y) * .5f);

            chunks     = new List <MapMesh>();
            chunkViews = new List <GameObject>();

            var visibleIter = Mathnv.GetAreaEnumerator(MapSize);

            while (visibleIter.MoveNext())
            {
                Vector2Int current = visibleIter.Current;
                CreateChunk(current);
            }
        }
Пример #11
0
        //random point in an area
        public Vector2 Rand(Vector2 a, Vector2 b)
        {
            if (a.x > b.x)
            {
                Mathnv.Swap(ref a.x, ref b.x);
            }
            if (a.y > b.y)
            {
                Mathnv.Swap(ref a.y, ref b.y);
            }

            float cx = b.x - a.x;
            float cy = b.y - a.y;

            return(new Vector2(a.x + Randf() * cx, a.y + Randf() * cy));
        }
Пример #12
0
        public uint Rand(uint a, uint b)
        {
            if (a == b)
            {
                return(a);
            }
            if (a == 0)
            {
                return(Rand(b));
            }
            if (a > b)
            {
                Mathnv.Swap(ref a, ref b);
            }
            uint n = 2 * b;
            uint m = a + b;
            uint c = n % m;

            return(a + Rand() % c);
        }
Пример #13
0
 public static void Clamp(this Rect area, Rect min_max)
 {
     Mathnv.Clamp(ref area, min_max);
 }
Пример #14
0
 public static void Clamp(this Rect area, Vector2 pos, Vector2 size)
 {
     Mathnv.Clamp(ref area, pos, size);
 }
Пример #15
0
        void SmoothVertex(int vertex, float skip_height = 0f, bool skip_seams = true)
        {
            Vector3 vertexToSmooth = vertices[vertex];

            //don't smooth vertices near this value, useful for retaining 'nice' seams
            if (Mathnv.FastApproximately(vertexToSmooth.y, skip_height, .01f))
            {
                return;
            }

            bool xSeam = false;
            bool zSeam = false;

            if (vertexToSmooth.x > (maxVertex.x - 1f))
            {
                xSeam = true;
            }

            if (vertexToSmooth.z > (maxVertex.y - 1f))
            {
                zSeam = true;
            }

            if (vertexToSmooth.x < (minVertex.x + 1f))
            {
                xSeam = true;
            }

            if (vertexToSmooth.z < (minVertex.y + 1f))
            {
                zSeam = true;
            }

            if (skip_seams && (zSeam || xSeam))
            {
                return;
            }

            List <int> neighbors = vertex_neighbors[vertex];

            Vector3 summation = Vector3.zero;

            for (int i = 0; i < neighbors.Count; ++i)
            {
                if (xSeam)
                {
                    summation.z += vertices[neighbors[i]].z;
                }
                if (zSeam)
                {
                    summation.x += vertices[neighbors[i]].x;
                }
                if (!xSeam && !zSeam)
                {
                    summation += vertices[neighbors[i]];
                }
            }

            summation = summation * (1f / (neighbors.Count));
            if (xSeam || zSeam)
            {
                Vector3 temp = vertexToSmooth;
                if (xSeam)
                {
                    temp.z = summation.z;
                }
                if (zSeam)
                {
                    temp.x = summation.x;
                }
                vertices[vertex] = temp;
            }
            else
            {
                vertices[vertex] = summation;
            }

            if (Wall != null && vertHasWall.ContainsKey(vertex))
            {
                int wallVertex = vertHasWall[vertex];
                Wall.SetWallVertex(wallVertex, new Vector2(vertices[vertex].x, vertices[vertex].z));
            }
        }
Пример #16
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;
        }
Пример #17
0
        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);
        }
Пример #18
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);
        }