Example #1
0
    public static GameObject GeneratePolygon(List <Vector2> vertices2D, PolygonMapGenerator PMG, float layer)
    {
        // Use the triangulator to get indices for creating triangles
        Triangulator tr = new Triangulator(vertices2D.ToArray());

        int[] indices = tr.Triangulate();

        // Create the Vector3 vertices
        Vector3[] vertices = new Vector3[vertices2D.Count];
        Vector4[] tangents = new Vector4[vertices2D.Count];
        Vector2[] uvs      = new Vector2[vertices2D.Count];
        for (int i = 0; i < vertices.Length; i++)
        {
            vertices[i] = new Vector3(vertices2D[i].x, layer, vertices2D[i].y);
            if (PMG != null)
            {
                uvs[i] = new Vector2(vertices2D[i].x / PMG.GenerationSettings.Width, vertices2D[i].y / PMG.GenerationSettings.Height);
            }


            // tangent calc
            Vector2 beforeVertex = vertices2D[i == 0 ? vertices2D.Count - 1 : i - 1];
            Vector2 thisVertex   = vertices2D[i];
            Vector2 afterVertex  = vertices2D[i == vertices2D.Count - 1 ? 0 : i + 1];

            Vector2 targetPoint = GeometryFunctions.GetOffsetIntersection(beforeVertex, thisVertex, afterVertex, 1f, 1f, false);

            Vector2 tangent = targetPoint - thisVertex;

            /*
             * float angle = Mathf.Abs(Vector2.Angle((beforeVertex - thisVertex).normalized, (afterVertex - thisVertex).normalized));
             * float factor = (180 - angle) * 0.005f;
             * tangent *= (1 + factor);
             */

            tangents[i] = new Vector4(tangent.x, 0, tangent.y, 0);
        }

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices  = vertices;
        msh.tangents  = tangents;
        msh.uv        = uvs;
        msh.triangles = indices;
        msh.RecalculateNormals();
        msh.RecalculateBounds();

        // Set up game object with mesh;
        GameObject   polygon  = new GameObject("Polygon (" + vertices2D.Count + ")");
        MeshRenderer renderer = polygon.AddComponent <MeshRenderer>();
        Color        ranCol   = Color.red; // new Color(Random.Range(0f, 0.3f), Random.Range(0.4f, 1f), Random.Range(0.1f, 0.6f));

        renderer.material.color = ranCol;
        MeshFilter filter = polygon.AddComponent(typeof(MeshFilter)) as MeshFilter;

        filter.mesh = msh;

        return(polygon);
    }
Example #2
0
        private static void CreateWaterTopology(PolygonMapGenerator PMG)
        {
            // Water altitude is <= -1
            List <GraphPolygon> firstLevelPolygons = PMG.Polygons.Where(x => x.IsWater && x.IsNextToLand()).ToList();

            ApplyWaterTopologyLevel(firstLevelPolygons, -1);
        }
Example #3
0
        private static void CreateLandTopology(PolygonMapGenerator PMG)
        {
            // Land altitude is >= 1
            List <GraphPolygon> firstLevelPolygons = PMG.Polygons.Where(x => !x.IsWater && x.IsNextToWater).ToList();

            ApplyLandTopologyLevel(firstLevelPolygons, 1);
        }
Example #4
0
 private static void TurnEdgePolygonsToWater(PolygonMapGenerator PMG)
 {
     foreach (GraphPolygon p in PMG.Polygons.Where(x => (x.IsEdgePolygon || x.AdjacentPolygons.Any(y => y.IsEdgePolygon))))
     {
         TurnPolygonToWater(p);
     }
 }
Example #5
0
        private static void CreateOuterOcean(PolygonMapGenerator PMG)
        {
            // Create outer edge nodes
            GraphNode oc1 = new GraphNode(new Vector2(-OUTER_OCEAN_SIZE, -OUTER_OCEAN_SIZE), PMG);
            GraphNode oc2 = new GraphNode(new Vector2(PMG.GenerationSettings.Width + OUTER_OCEAN_SIZE, -OUTER_OCEAN_SIZE), PMG);
            GraphNode oc3 = new GraphNode(new Vector2(PMG.GenerationSettings.Width + OUTER_OCEAN_SIZE, PMG.GenerationSettings.Height + OUTER_OCEAN_SIZE), PMG);
            GraphNode oc4 = new GraphNode(new Vector2(-OUTER_OCEAN_SIZE, PMG.GenerationSettings.Height + OUTER_OCEAN_SIZE), PMG);

            // Add nodes to the generator
            PMG.AddNode(oc1);
            PMG.AddNode(oc2);
            PMG.AddNode(oc3);
            PMG.AddNode(oc4);

            // Adding new water polygons
            PMG.AddPolygon(new List <GraphNode>()
            {
                PMG.CornerNodes[0], oc1, oc2, PMG.CornerNodes[1]
            }, new List <GraphConnection>(), outerPolygon: true);
            PMG.AddPolygon(new List <GraphNode>()
            {
                PMG.CornerNodes[1], oc2, oc3, PMG.CornerNodes[2]
            }, new List <GraphConnection>(), outerPolygon: true);
            PMG.AddPolygon(new List <GraphNode>()
            {
                PMG.CornerNodes[2], oc3, oc4, PMG.CornerNodes[3]
            }, new List <GraphConnection>(), outerPolygon: true);
            PMG.AddPolygon(new List <GraphNode>()
            {
                PMG.CornerNodes[3], oc4, oc1, PMG.CornerNodes[0]
            }, new List <GraphConnection>(), outerPolygon: true);
        }
Example #6
0
 public static void CreateBiomes(PolygonMapGenerator PMG)
 {
     GenerateTemperature(PMG);
     GeneratePrecipitation(PMG);
     foreach (GraphPolygon polygon in PMG.Polygons)
     {
         polygon.Biome = GetBiome(polygon);
     }
 }
Example #7
0
        public static void ExpandOceans(PolygonMapGenerator PMG)
        {
            int numExpansions = (int)(PMG.Polygons.Count * EXPAND_OCEAN_PERC);

            Debug.Log("Expanding " + numExpansions + "x the ocean.");
            for (int i = 0; i < numExpansions; i++)
            {
                DoExpandOcean(PMG);
            }
        }
Example #8
0
 /// <summary>
 /// Turns polygons that are bigger than the max allowed area into water
 /// </summary>
 private static void TurnBigPolygonsToWater(PolygonMapGenerator PMG)
 {
     foreach (GraphPolygon polygon in PMG.Polygons)
     {
         if (polygon.Area > PMG.GenerationSettings.MaxPolygonArea)
         {
             TurnPolygonToWater(polygon);
         }
     }
 }
Example #9
0
        private static void TurnRandomPolygonsToWater(PolygonMapGenerator PMG)
        {
            int numWaters = (int)(PMG.Polygons.Count * RANDOM_OCEAN_PERC);

            Debug.Log("Creating " + numWaters + " random waters.");
            for (int i = 0; i < numWaters; i++)
            {
                DoTurnRandomPolygonToWater(PMG);
            }
        }
Example #10
0
        public static void CreateRivers(PolygonMapGenerator PMG)
        {
            int sizePerRiver = UnityEngine.Random.Range(SIZE_PER_RIVER - SIZE_PER_RIVER_RANGE, SIZE_PER_RIVER + SIZE_PER_RIVER_RANGE);
            int numRivers    = PMG.GenerationSettings.Area / sizePerRiver;

            Debug.Log("Creating " + numRivers + " rivers.");
            for (int i = 0; i < numRivers; i++)
            {
                DoCreateRiver(PMG);
            }
        }
Example #11
0
        private static void CreateBallOceans(PolygonMapGenerator PMG)
        {
            int sizePerBallOcean = UnityEngine.Random.Range(SIZE_PER_BALL_OCEAN - SIZE_PER_BALL_OCEAN_RANGE, SIZE_PER_BALL_OCEAN + SIZE_PER_BALL_OCEAN_RANGE);
            int numBallOceans    = Math.Max(PMG.GenerationSettings.Area / sizePerBallOcean, MIN_BALL_OCEANS);

            Debug.Log("Creating " + numBallOceans + " round oceans.");
            for (int i = 0; i < numBallOceans; i++)
            {
                DoCreateBallOcean(PMG);
            }
        }
Example #12
0
        private static void PerformContinentCuts(PolygonMapGenerator PMG)
        {
            int sizePerContinentCuts = UnityEngine.Random.Range(SIZE_PER_CONTINENT_CUT - SIZE_PER_CONTINENT_CUT_RANGE, SIZE_PER_CONTINENT_CUT + SIZE_PER_CONTINENT_CUT_RANGE);
            int numContinentCuts     = Math.Max(PMG.GenerationSettings.Area / sizePerContinentCuts, MIN_CONTINENT_CUTS);

            Debug.Log("Performing " + numContinentCuts + " continent cuts.");
            for (int i = 0; i < numContinentCuts; i++)
            {
                DoCreateContinentCut(PMG);
            }
        }
Example #13
0
        public static void DoTurnRandomPolygonToWater(PolygonMapGenerator PMG)
        {
            List <GraphPolygon> landPolygons = PMG.Polygons.Where(x => !x.IsWater).ToList();

            if (landPolygons.Count == 0)
            {
                return;
            }
            GraphPolygon newWater = landPolygons[UnityEngine.Random.Range(0, landPolygons.Count)];

            TurnPolygonToWater(newWater);
        }
Example #14
0
        public static void ExpandLand(PolygonMapGenerator PMG)
        {
            int targetAmount  = (int)(PMG.Polygons.Count * MIN_TOTAL_LAND_COVERAGE);
            int landPolygons  = PMG.Polygons.Where(x => !x.IsWater).Count();
            int numExpansions = targetAmount - landPolygons;

            Debug.Log("Expanding " + numExpansions + "x the land.");
            for (int i = 0; i < numExpansions; i++)
            {
                DoExpandLand(PMG);
            }
        }
Example #15
0
        public static void DoExpandOcean(PolygonMapGenerator PMG)
        {
            List <GraphPolygon> shorePolygons = PMG.Polygons.Where(x => !x.IsWater && x.IsNextToWater).ToList();

            if (shorePolygons.Count == 0)
            {
                return;
            }
            GraphPolygon newWater = shorePolygons[UnityEngine.Random.Range(0, shorePolygons.Count)];

            TurnPolygonToWater(newWater);
        }
Example #16
0
        private static void CreateContinentsWithNoise(PolygonMapGenerator PMG)
        {
            ContinentNoise noise = new ContinentNoise((1f / PMG.GenerationSettings.ContinentSizeScaleFactor) * (100f / PMG.GenerationSettings.Area));

            foreach (GraphPolygon polygon in PMG.Polygons.Where(x => (!x.IsEdgePolygon && !x.AdjacentPolygons.Any(y => y.IsEdgePolygon))))
            {
                float noiseValue = noise.GetValue(polygon.CenterPoi.x, polygon.CenterPoi.y, PMG.GenerationSettings);
                if (noiseValue < 0.2f)
                {
                    TurnPolygonToWater(polygon);
                }
            }
        }
Example #17
0
        private static void GeneratePrecipitation(PolygonMapGenerator PMG)
        {
            int polePrecipitation    = 0;
            int equatorPrecipitation = 5000;
            PrecipitationNoise noise = new PrecipitationNoise(polePrecipitation, equatorPrecipitation);

            foreach (GraphPolygon polygon in PMG.Polygons)
            {
                float noiseValue = noise.GetValue(polygon.CenterPoi.x, polygon.CenterPoi.y, PMG.GenerationSettings);
                polygon.Precipitation = (int)noiseValue;
            }

            //if (Visualize) NoiseTester.DisplayNoise(noise, NoiseTester.PrecipitationPlane, MapData, polePrecipitation, equatorPrecipitation);
        }
Example #18
0
        public static void DoExpandLand(PolygonMapGenerator PMG)
        {
            List <GraphPolygon> waterShorePolygons = PMG.Polygons.Where(x => !x.IsEdgePolygon && !x.AdjacentPolygons.Any(y => y.IsEdgePolygon) && x.IsWater && x.IsNextToLand()).ToList();

            // When there is no land yet, just convert a random polygon to land
            if (waterShorePolygons.Count == 0)
            {
                waterShorePolygons = PMG.Polygons.Where(x => !x.IsEdgePolygon).ToList();
            }

            GraphPolygon newLand = waterShorePolygons[UnityEngine.Random.Range(0, waterShorePolygons.Count)];

            TurnPolygonToLand(newLand);
        }
Example #19
0
        private static void GenerateTemperature(PolygonMapGenerator PMG)
        {
            float            poleTemperature        = -12f;
            float            equatorTemperature     = 35f;
            float            temperatureModifyRange = 15f;
            TemperatureNoise noise = new TemperatureNoise(poleTemperature, equatorTemperature, temperatureModifyRange);

            foreach (GraphPolygon polygon in PMG.Polygons)
            {
                float noiseValue = noise.GetValue(polygon.CenterPoi.x, polygon.CenterPoi.y, PMG.GenerationSettings);
                polygon.Temperature = (int)noiseValue;
            }

            //if (Visualize) NoiseTester.DisplayNoise(noise, NoiseTester.TemperaturePlane, MapData, poleTemperature - temperatureModifyRange, equatorTemperature + temperatureModifyRange);
        }
Example #20
0
        private static void IdentifyWaterBodies(PolygonMapGenerator PMG)
        {
            PMG.WaterBodies = new List <List <GraphPolygon> >();

            List <GraphPolygon> polygonsWithoutWaterBody = new List <GraphPolygon>();

            polygonsWithoutWaterBody.AddRange(PMG.Polygons.Where(x => x.IsWater && !x.IsOuterPolygon));

            while (polygonsWithoutWaterBody.Count > 0)
            {
                List <GraphPolygon>  waterBodyPolygons = new List <GraphPolygon>();
                Queue <GraphPolygon> polygonsToAdd     = new Queue <GraphPolygon>();
                polygonsToAdd.Enqueue(polygonsWithoutWaterBody[0]);
                while (polygonsToAdd.Count > 0)
                {
                    GraphPolygon polygonToAdd = polygonsToAdd.Dequeue();
                    waterBodyPolygons.Add(polygonToAdd);
                    foreach (GraphPolygon neighbourPolygon in polygonToAdd.AdjacentPolygons.Where(x => x.IsWater && !x.IsOuterPolygon))
                    {
                        if (!waterBodyPolygons.Contains(neighbourPolygon) && !polygonsToAdd.Contains(neighbourPolygon))
                        {
                            polygonsToAdd.Enqueue(neighbourPolygon);
                        }
                    }
                }
                bool isLake = waterBodyPolygons.Count < 5;
                PMG.WaterBodies.Add(waterBodyPolygons);

                // Add outer ocean to ocean
                if (!isLake)
                {
                    foreach (GraphPolygon poly in PMG.Polygons.Where(x => x.IsOuterPolygon))
                    {
                        waterBodyPolygons.Add(poly);
                    }
                }

                foreach (GraphPolygon poly in waterBodyPolygons)
                {
                    polygonsWithoutWaterBody.Remove(poly);
                }
            }
        }
Example #21
0
        public static void CreateWaters(PolygonMapGenerator PMG)
        {
            switch (PMG.GenerationSettings.MapType)
            {
            case MapType.Regional:
                PerformContinentCuts(PMG);
                TurnRandomPolygonsToWater(PMG);
                ExpandOceans(PMG);
                CreateBallOceans(PMG);
                ExpandLand(PMG);
                break;

            case MapType.Island:
                CreateOuterOcean(PMG);
                TurnEdgePolygonsToWater(PMG);
                PerformContinentCuts(PMG);
                TurnRandomPolygonsToWater(PMG);
                ExpandOceans(PMG);
                CreateBallOceans(PMG);
                ExpandLand(PMG);
                break;

            case MapType.FractalNoise:
                CreateOuterOcean(PMG);
                TurnEdgePolygonsToWater(PMG);
                CreateContinentsWithNoise(PMG);
                break;

            case MapType.BigOceans:
                CreateOuterOcean(PMG);
                TurnEdgePolygonsToWater(PMG);
                TurnBigPolygonsToWater(PMG);
                break;
            }

            IdentifyLandmasses(PMG);
            IdentifyWaterBodies(PMG);

            foreach (GraphPolygon p in PMG.Polygons)
            {
                p.UpdateNeighbours();
            }
        }
Example #22
0
        private static void IdentifyLandmasses(PolygonMapGenerator PMG)
        {
            // Identify landmasses
            PMG.Landmasses = new List <List <GraphPolygon> >();

            List <GraphPolygon> polygonsWithoutLandmass = new List <GraphPolygon>();

            polygonsWithoutLandmass.AddRange(PMG.Polygons.Where(x => !x.IsWater));

            while (polygonsWithoutLandmass.Count > 0)
            {
                List <GraphPolygon>  landmassPolygons = new List <GraphPolygon>();
                Queue <GraphPolygon> polygonsToAdd    = new Queue <GraphPolygon>();
                polygonsToAdd.Enqueue(polygonsWithoutLandmass[0]);
                while (polygonsToAdd.Count > 0)
                {
                    GraphPolygon polygonToAdd = polygonsToAdd.Dequeue();
                    landmassPolygons.Add(polygonToAdd);
                    foreach (GraphPolygon neighbourPolygon in polygonToAdd.AdjacentPolygons.Where(x => !x.IsWater))
                    {
                        if (!landmassPolygons.Contains(neighbourPolygon) && !polygonsToAdd.Contains(neighbourPolygon))
                        {
                            polygonsToAdd.Enqueue(neighbourPolygon);
                        }
                    }
                }
                PMG.Landmasses.Add(landmassPolygons);
                foreach (GraphPolygon poly in landmassPolygons)
                {
                    polygonsWithoutLandmass.Remove(poly);
                }
            }

            foreach (List <GraphPolygon> landmass in PMG.Landmasses)
            {
                foreach (GraphPolygon polygon in landmass)
                {
                    polygon.Landmass = landmass;
                }
            }
        }
Example #23
0
        public static Texture2D CreateRegionBorderMaskTexture(PolygonMapGenerator PMG)
        {
            int       texWidth            = PMG.GenerationSettings.Width * 400;
            int       texHeight           = PMG.GenerationSettings.Height * 400;
            Texture2D regionBorderTexture = new Texture2D(texWidth, texHeight);

            for (int y = 0; y < texHeight; y++)
            {
                for (int x = 0; x < texWidth; x++)
                {
                    regionBorderTexture.SetPixel(x, y, Color.black);
                }
            }

            foreach (GraphConnection c in PMG.InGraphConnections.Where(x => x.Type != BorderType.Water && !(x.StartNode.Type == BorderPointType.Edge && x.EndNode.Type == BorderPointType.Edge)))
            {
                int steps = 20;
                int range = 1;
                if (c.Type == BorderType.Shore)
                {
                    range *= 2;
                }
                for (int i = 0; i < steps + 1; i++)
                {
                    Vector2 worldPosition = Vector2.Lerp(c.StartNode.Vertex, c.EndNode.Vertex, 1f * i / steps);
                    int     texX          = (int)((worldPosition.x / PMG.GenerationSettings.Width) * texWidth);
                    int     texY          = (int)((worldPosition.y / PMG.GenerationSettings.Height) * texHeight);
                    for (int x = texX - range; x < texX + range + 1; x++)
                    {
                        for (int y = texY - range; y < texY + range + 1; y++)
                        {
                            regionBorderTexture.SetPixel(x, y, Color.white);
                        }
                    }
                }
            }

            regionBorderTexture.Apply();

            return(regionBorderTexture);
        }
Example #24
0
        public static Texture2D CreateRiverMaskTexture(PolygonMapGenerator PMG)
        {
            int       texWidth         = PMG.GenerationSettings.Width * 400;
            int       texHeight        = PMG.GenerationSettings.Height * 400;
            Texture2D riverMaskTexture = new Texture2D(texWidth, texHeight);

            for (int y = 0; y < texHeight; y++)
            {
                for (int x = 0; x < texWidth; x++)
                {
                    riverMaskTexture.SetPixel(x, y, Color.black);
                }
            }

            foreach (GraphConnection c in PMG.InGraphConnections.Where(x => x.River != null))
            {
                int steps = 10;
                int range = (int)c.RiverWidth;
                for (int i = 0; i < steps + 1; i++)
                {
                    Vector2 worldPosition = Vector2.Lerp(c.StartNode.Vertex, c.EndNode.Vertex, 1f * i / steps);
                    int     texX          = (int)((worldPosition.x / PMG.GenerationSettings.Width) * texWidth);
                    int     texY          = (int)((worldPosition.y / PMG.GenerationSettings.Height) * texHeight);
                    for (int x = texX - range; x < texX + range + 1; x++)
                    {
                        for (int y = texY - range; y < texY + range + 1; y++)
                        {
                            riverMaskTexture.SetPixel(x, y, Color.white);
                        }
                    }
                }
            }

            riverMaskTexture.Apply();

            return(riverMaskTexture);
        }
Example #25
0
    public static string GetMapHash(PolygonMapGenerator PMG)
    {
        StringBuilder hash = new StringBuilder();

        // Line 0 (GenerationSettings.*): seed;width;height;minPolygonArea;maxPolygonArea;minContinentSize;maxContinentSize;mapType;continentSizeScale
        MapGenerationSettings mgs = PMG.GenerationSettings;

        hash.AppendLine(mgs.Seed + ";" + mgs.Width + ";" + mgs.Height + ";" + mgs.MinPolygonArea + ";" + mgs.MaxPolygonArea + ";" + mgs.MinContinentSize + ";" + mgs.MaxContinentSize + ";" + (int)mgs.MapType + ";" + mgs.ContinentSizeScaleFactor);

        // Line 1: n_nodes;n_ingraphconnections;n_egdeconnections;n_polygons;n_paths;n_landmasses;n_waterbodies;n_continents
        hash.AppendLine(PMG.Nodes.Count + ";" + PMG.InGraphConnections.Count + ";" + PMG.EdgeConnections.Count + ";" + PMG.Polygons.Count + ";" + PMG.RiverPaths.Count + ";" + PMG.Landmasses.Count + ";" + PMG.WaterBodies.Count + ";" + PMG.Continents.Count);

        // Node Lines: id;positionX;positionY;riverWidth;distanceFromNearestOcean
        foreach (GraphNode n in PMG.Nodes)
        {
            hash.AppendLine(n.Id + ";" + n.Vertex.x + ";" + n.Vertex.y + ";" + n.RiverWidth + ";" + n.DistanceFromNearestOcean);
        }

        // InGraphConnection Lines: id;fromNodeId;toNodeId;riverWidth
        foreach (GraphConnection c in PMG.InGraphConnections)
        {
            hash.AppendLine(c.Id + ";" + c.StartNode.Id + ";" + c.EndNode.Id + ";" + c.RiverWidth);
        }

        // EdgeConnection Lines: id;fromNodeId;toNodeId;riverWidth
        foreach (GraphConnection c in PMG.EdgeConnections)
        {
            hash.AppendLine(c.Id + ";" + c.StartNode.Id + ";" + c.EndNode.Id + ";" + c.RiverWidth);
        }

        // Polygon Lines: id;[nodeIds];[connectionIds]
        foreach (GraphPolygon p in PMG.Polygons)
        {
            hash.Append(p.Id + ";");
            foreach (GraphNode n in p.Nodes)
            {
                hash.Append(n.Id + ",");
            }
            hash.Append(";");
            foreach (GraphConnection c in p.Connections)
            {
                hash.Append(c.Id + ",");
            }
            hash.AppendLine();
        }

        // River Path Lines: id;[nodeIds];[connectionIds];[polygonIds]
        foreach (GraphPath r in PMG.RiverPaths)
        {
            hash.Append(r.Id + ";");
            foreach (GraphNode n in r.Nodes)
            {
                hash.Append(n.Id + ",");
            }
            hash.Append(";");
            foreach (GraphConnection c in r.Connections)
            {
                hash.Append(c.Id + ",");
            }
            hash.Append(";");
            foreach (GraphPolygon p in r.Polygons)
            {
                hash.Append(p.Id + ",");
            }
            hash.AppendLine();
        }

        // Landmass Lines: [polygonIds]
        foreach (List <GraphPolygon> list in PMG.Landmasses)
        {
            foreach (GraphPolygon p in list)
            {
                hash.Append("p.Id" + ",");
            }
            hash.AppendLine();
        }

        // Water Body Lines: [polygonIds]
        foreach (List <GraphPolygon> list in PMG.WaterBodies)
        {
            foreach (GraphPolygon p in list)
            {
                hash.Append("p.Id" + ",");
            }
            hash.AppendLine();
        }

        // Continent Lines: [polygonIds]
        foreach (List <GraphPolygon> list in PMG.Continents)
        {
            foreach (GraphPolygon p in list)
            {
                hash.Append("p.Id" + ",");
            }
            hash.AppendLine();
        }

        return(hash.ToString());
    }
Example #26
0
    public static Map LoadMapFromHash(PolygonMapGenerator PMG, string mapHash)
    {
        string[] lines     = mapHash.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
        int      lineIndex = 0;

        // Line 0: MapGenerationSettings: seed;width;height;minPolygonArea;maxPolygonArea;minContinentSize;maxContinentSize;mapType;continentSizeScale
        int debugI = 0;

        Debug.Log(debugI++);
        string[] mgsLine            = lines[lineIndex++].Split(';');
        int      seed               = int.Parse(mgsLine[0]);
        int      width              = int.Parse(mgsLine[1]);
        int      height             = int.Parse(mgsLine[2]);
        float    minPolygonArea     = float.Parse(mgsLine[3]);
        float    maxPolygonArea     = float.Parse(mgsLine[4]);
        int      minContinentSize   = int.Parse(mgsLine[5]);
        int      maxContinentSize   = int.Parse(mgsLine[6]);
        MapType  mapType            = (MapType)int.Parse(mgsLine[7]);
        float    continentSizeScale = float.Parse(mgsLine[8]);

        PMG.GenerationSettings = new MapGenerationSettings(seed, width, height, minPolygonArea, maxPolygonArea, minContinentSize, maxContinentSize, mapType, continentSizeScale);

        Debug.Log(debugI++);
        // Line 1: n_nodes;n_ingraphconnections;n_egdeconnections;n_polygons;n_paths;n_landmasses;n_waterbodies;n_continents
        string[] line1   = lines[lineIndex++].Split(';');
        int      n_nodes = int.Parse(line1[0]);
        int      n_inGraphConnections = int.Parse(line1[1]);
        int      n_edgeConnections    = int.Parse(line1[2]);
        int      n_polygons           = int.Parse(line1[3]);
        int      n_riverPaths         = int.Parse(line1[4]);
        int      n_landmasses         = int.Parse(line1[5]);
        int      n_waterBodies        = int.Parse(line1[6]);
        int      n_continents         = int.Parse(line1[7]);

        Debug.Log(debugI++);
        // Node Lines: id;positionX;positionY;riverWidth;distanceFromNearestOcean
        PMG.Nodes.Clear();
        Dictionary <int, GraphNode> nodeMap = new Dictionary <int, GraphNode>();

        for (int i = 0; i < n_nodes; i++)
        {
            string[]  attributes = lines[lineIndex++].Split(';');
            int       id         = int.Parse(attributes[0]);
            float     x          = float.Parse(attributes[1]);
            float     y          = float.Parse(attributes[2]);
            float     riverWidth = float.Parse(attributes[3]);
            int       distanceFromNearestOcean = int.Parse(attributes[4]);
            GraphNode node = new GraphNode(id, x, y, riverWidth, distanceFromNearestOcean);
            nodeMap.Add(id, node);
            PMG.Nodes.Add(node);
        }

        Debug.Log(debugI++);
        // InGraphConnection Lines: id;fromNodeId;toNodeId;riverWidth
        PMG.InGraphConnections.Clear();
        Dictionary <int, GraphConnection> connectionMap = new Dictionary <int, GraphConnection>();

        for (int i = 0; i < n_inGraphConnections; i++)
        {
            string[]        attributes  = lines[lineIndex++].Split(';');
            int             id          = int.Parse(attributes[0]);
            int             startNodeId = int.Parse(attributes[1]);
            int             endNodeId   = int.Parse(attributes[2]);
            float           riverWidth  = float.Parse(attributes[3]);
            GraphConnection connection  = new GraphConnection(id, nodeMap[startNodeId], nodeMap[endNodeId], riverWidth);
            connectionMap.Add(id, connection);
            PMG.InGraphConnections.Add(connection);
        }

        Debug.Log(debugI++);
        // EdgeConnection Lines: id;fromNodeId;toNodeId;riverWidth
        PMG.EdgeConnections.Clear();
        for (int i = 0; i < n_edgeConnections; i++)
        {
            string[]        attributes  = lines[lineIndex++].Split(';');
            int             id          = int.Parse(attributes[0]);
            int             startNodeId = int.Parse(attributes[1]);
            int             endNodeId   = int.Parse(attributes[2]);
            float           riverWidth  = float.Parse(attributes[3]);
            GraphConnection connection  = new GraphConnection(id, nodeMap[startNodeId], nodeMap[endNodeId], riverWidth);
            connectionMap.Add(id, connection);
            PMG.EdgeConnections.Add(connection);
        }

        Debug.Log(debugI++);
        // Polygon Lines: id;[nodeIds];[connectionIds]
        PMG.Polygons.Clear();
        Dictionary <int, GraphPolygon> polygonMap = new Dictionary <int, GraphPolygon>();

        for (int i = 0; i < n_polygons; i++)
        {
            string[] attributes = lines[lineIndex++].Split(';');
            int      id         = int.Parse(attributes[0]);

            List <GraphNode> nodes   = new List <GraphNode>();
            string[]         nodeIds = attributes[1].Split(',');
            foreach (string s in nodeIds)
            {
                nodes.Add(nodeMap[int.Parse(s)]);
            }

            List <GraphConnection> connections = new List <GraphConnection>();
            string[] connectionIds             = attributes[2].Split(',');
            foreach (string s in connectionIds)
            {
                connections.Add(connectionMap[int.Parse(s)]);
            }

            GraphPolygon polygon = new GraphPolygon(id, nodes, connections);
            polygonMap.Add(id, polygon);
            PMG.Polygons.Add(polygon);
        }

        Debug.Log(debugI++);
        // River Path Lines: id;[nodeIds];[connectionIds];[polygonIds]
        PMG.RiverPaths.Clear();
        for (int i = 0; i < n_riverPaths; i++)
        {
            string[] attributes = lines[lineIndex++].Split(';');
            int      id         = int.Parse(attributes[0]);

            List <GraphNode> nodes   = new List <GraphNode>();
            string[]         nodeIds = attributes[1].Split(',');
            foreach (string s in nodeIds)
            {
                nodes.Add(nodeMap[int.Parse(s)]);
            }

            List <GraphConnection> connections = new List <GraphConnection>();
            string[] connectionIds             = attributes[2].Split(',');
            foreach (string s in connectionIds)
            {
                connections.Add(connectionMap[int.Parse(s)]);
            }

            List <GraphPolygon> polygons   = new List <GraphPolygon>();
            string[]            polygonIds = attributes[3].Split(',');
            foreach (string s in polygonIds)
            {
                polygons.Add(polygonMap[int.Parse(s)]);
            }

            GraphPath path = new GraphPath(id, nodes, connections, polygons);
            PMG.RiverPaths.Add(path);
        }

        Debug.Log(debugI++);
        // Landmass Lines: [polygonIds]
        PMG.Landmasses.Clear();
        for (int i = 0; i < n_landmasses; i++)
        {
            string[]            attributes = lines[lineIndex++].Split(';');
            List <GraphPolygon> polygons   = new List <GraphPolygon>();
            string[]            polygonIds = attributes[0].Split(',');
            foreach (string s in polygonIds)
            {
                polygons.Add(polygonMap[int.Parse(s)]);
            }
            PMG.Landmasses.Add(polygons);
        }

        Debug.Log(debugI++);
        // WaterBody Lines: [polygonIds]
        PMG.WaterBodies.Clear();
        for (int i = 0; i < n_waterBodies; i++)
        {
            string[]            attributes = lines[lineIndex++].Split(';');
            List <GraphPolygon> polygons   = new List <GraphPolygon>();
            string[]            polygonIds = attributes[0].Split(',');
            foreach (string s in polygonIds)
            {
                polygons.Add(polygonMap[int.Parse(s)]);
            }
            PMG.WaterBodies.Add(polygons);
        }

        Debug.Log(debugI++);
        // Continent Lines: [polygonIds]
        PMG.Continents.Clear();
        for (int i = 0; i < n_continents; i++)
        {
            string[]            attributes = lines[lineIndex++].Split(';');
            List <GraphPolygon> polygons   = new List <GraphPolygon>();
            string[]            polygonIds = attributes[0].Split(',');
            foreach (string s in polygonIds)
            {
                polygons.Add(polygonMap[int.Parse(s)]);
            }
            PMG.Continents.Add(polygons);
        }


        return(PMG.DrawMap());
    }
Example #27
0
        private static void FindNodeOceanDistances(PolygonMapGenerator PMG)
        {
            List <GraphNode> firstLevelNodes = PMG.Nodes.Where(x => x.Type == BorderPointType.Shore).ToList();

            ApplyNodeDepthLevel(firstLevelNodes, 1);
        }
Example #28
0
        public static void DoCreateContinentCut(PolygonMapGenerator PMG)
        {
            // Define random cut circle
            int   avgMapEdgeSize     = (int)(Math.Sqrt(PMG.GenerationSettings.Area));
            float minDistanceFromMap = avgMapEdgeSize * 0.1f;
            float maxDistanceFromMap = avgMapEdgeSize * 0.7f;

            float cutCircleCenterX = 0, cutCircleCenterY = 0;

            switch (UnityEngine.Random.Range(0, 4))
            {
            case 0:     // Bottom side
                cutCircleCenterX = UnityEngine.Random.Range(-maxDistanceFromMap, PMG.GenerationSettings.Width + maxDistanceFromMap);
                cutCircleCenterY = UnityEngine.Random.Range(-maxDistanceFromMap, -minDistanceFromMap);
                break;

            case 1:     // Right side
                cutCircleCenterX = UnityEngine.Random.Range(PMG.GenerationSettings.Width + minDistanceFromMap, PMG.GenerationSettings.Width + maxDistanceFromMap);
                cutCircleCenterY = UnityEngine.Random.Range(-minDistanceFromMap, PMG.GenerationSettings.Height + maxDistanceFromMap);
                break;

            case 2:     // Top side
                cutCircleCenterX = UnityEngine.Random.Range(-maxDistanceFromMap, PMG.GenerationSettings.Width + maxDistanceFromMap);
                cutCircleCenterY = UnityEngine.Random.Range(PMG.GenerationSettings.Height + minDistanceFromMap, PMG.GenerationSettings.Height + maxDistanceFromMap);
                break;

            case 3:     // Left side
                cutCircleCenterX = UnityEngine.Random.Range(-maxDistanceFromMap, -minDistanceFromMap);
                cutCircleCenterY = UnityEngine.Random.Range(-minDistanceFromMap, PMG.GenerationSettings.Height + maxDistanceFromMap);
                break;
            }
            Vector2 cutCircleCenter = new Vector2(cutCircleCenterX, cutCircleCenterY);
            int     cutCircleRadius = avgMapEdgeSize;

            // Check for each node if it is close to cut circle
            float distanceMargin = UnityEngine.Random.Range(MIN_CONTINENT_CUT_WIDTH, MAX_CONTINENT_CUT_WIDTH);

            List <GraphPolygon> newOceanPolygons = new List <GraphPolygon>();

            foreach (GraphNode n in PMG.Nodes.Where(x => !x.IsWaterNode()))
            {
                float distance = Vector2.Distance(n.Vertex, cutCircleCenter);
                if (distance >= cutCircleRadius - distanceMargin && distance <= cutCircleRadius + distanceMargin)
                {
                    foreach (GraphPolygon p in n.Polygons)
                    {
                        if (!newOceanPolygons.Contains(p))
                        {
                            newOceanPolygons.Add(p);
                        }
                    }
                }
            }
            foreach (GraphPolygon p in newOceanPolygons)
            {
                if (UnityEngine.Random.Range(0f, 1f) > CONTINENT_SPLIT_ISLAND_CHANCE)
                {
                    TurnPolygonToWater(p);
                }
            }
        }
Example #29
0
 // Start is called before the first frame update
 public static void CreateTopology(PolygonMapGenerator PMG)
 {
     CreateLandTopology(PMG);
     CreateWaterTopology(PMG);
     FindNodeOceanDistances(PMG);
 }
Example #30
0
        public static void CreateContinents(PolygonMapGenerator PMG)
        {
            PMG.Continents = new List<List<GraphPolygon>>();

            // 1. Create one continent per landmass
            foreach (List<GraphPolygon> landmass in PMG.Landmasses)
            {
                List<GraphPolygon> continentPolygons = new List<GraphPolygon>();
                continentPolygons.AddRange(landmass);
                foreach (GraphPolygon landmassPoly in landmass) landmassPoly.Continent = continentPolygons;
                PMG.Continents.Add(continentPolygons);
            }

            // 2. Split big landmasses into mutliple continents
            List<GraphPolygon> biggestContinent = PMG.Continents.OrderByDescending(x => x.Count).First();
            while(biggestContinent.Count > PMG.GenerationSettings.MaxContinentSize)
            {
                int minCuts = int.MaxValue;
                int minCutMinRegions = int.MaxValue;
                KargerGraph bestGraph = null;
                int cyclesWithoutImprovement = 0;
                while(cyclesWithoutImprovement < 50 || bestGraph == null)
                {
                    cyclesWithoutImprovement++;
                    KargerGraph graph = SplitClusterOnce(biggestContinent);
                    if(graph.Vertices[0].ContainedPolygons.Count >= PMG.GenerationSettings.MinContinentSize && graph.Vertices[1].ContainedPolygons.Count >= PMG.GenerationSettings.MinContinentSize)
                    {
                        int graphMinCutMinRegions = Mathf.Min(graph.Vertices[0].ContainedPolygons.Count, graph.Vertices[1].ContainedPolygons.Count);
                        if (graph.CutSize < minCuts || (graph.CutSize == minCuts && graphMinCutMinRegions > minCutMinRegions))
                        {
                            minCuts = graph.CutSize;
                            minCutMinRegions = graphMinCutMinRegions;
                            bestGraph = graph;
                            cyclesWithoutImprovement = 0;
                        }
                    }
                }

                List<GraphPolygon> newContinent = new List<GraphPolygon>();
                foreach (GraphPolygon splittedPolygon in bestGraph.Vertices[0].ContainedPolygons)
                {
                    newContinent.Add(splittedPolygon);
                    biggestContinent.Remove(splittedPolygon);
                    splittedPolygon.Continent = newContinent;
                }
                PMG.Continents.Add(newContinent);

                biggestContinent = PMG.Continents.OrderByDescending(x => x.Count).First();
            }

            
            // 3. Assign islands that are too small to the nearest continent
            List<GraphPolygon> smallestContinent = PMG.Continents.OrderBy(x => x.Count).First();
            while(smallestContinent.Count < PMG.GenerationSettings.MinContinentSize)
            {
                float shortestDistance = float.MaxValue;
                GraphPolygon shortestDistancePolygon = null;
                foreach(GraphPolygon continentPoly in smallestContinent)
                {
                    foreach(GraphPolygon waterNeighbour in continentPoly.WaterNeighbours)
                    {
                        if(!smallestContinent.Contains(waterNeighbour))
                        {
                            float distance = PolygonMapFunctions.GetPolygonDistance(continentPoly, waterNeighbour);
                            if (distance < shortestDistance)
                            {
                                shortestDistance = distance;
                                shortestDistancePolygon = waterNeighbour;
                            }
                        }
                    }
                }

                foreach (GraphPolygon continentPoly in smallestContinent)
                {
                    continentPoly.Continent = shortestDistancePolygon.Continent;
                    shortestDistancePolygon.Continent.Add(continentPoly);
                }
                smallestContinent.Clear();
                PMG.Continents.Remove(smallestContinent);

                smallestContinent = PMG.Continents.OrderBy(x => x.Count).First();
            }
            
        }