Ejemplo n.º 1
0
        /// <summary>
        /// creates a biome for a given type of terrain
        /// </summary>
        private void createBiome(Terrain.TerrainTypes terrain)
        {
            // calculate biome half length proportional to the map size
            int biomeLenghtValue = (int)(Mathf.Max(WIDTH, HEIGHT) / 7);
            int biomeHalfLength  = random.Next(biomeLenghtValue - 2, biomeLenghtValue + 2);

            // random anchor spot for biome
            // index 0 for x and 1 and y coordinate
            int[] anchor = new int[2];
            anchor[0] = random.Next(0, WIDTH);
            anchor[1] = random.Next(0, HEIGHT);

            int counter = 0;

            while (biomeAnchorTooClose(anchor, biomeLenghtValue) && counter < 100)
            {
                anchor[0] = random.Next(0, WIDTH);
                anchor[1] = random.Next(0, HEIGHT);
                counter++;
            }

            // adding anchor to screen
            MapTile    anchorTile         = ScriptableObject.CreateInstance <MapTile>();
            Vector3Int anchorVector       = new Vector3Int(-anchor[0] + WIDTH / 2, -anchor[1] + HEIGHT / 2, 0);
            Vector3    anchorMappedVector = map.CellToWorld(anchorVector);

            anchorTile.Canvas         = parent;
            anchorTile.ScreenPosition = anchorMappedVector;

            biomeAnchors[anchor] = terrain;
            // occupiedBiomSpots[anchor] = terrain;

            anchorTile.Terrain = new Terrain(terrain);

            growBoime(anchor, biomeHalfLength, terrain);

            // create beach biom if the biome type is Ocean
            if (terrain.Equals(Terrain.TerrainTypes.Ocean))
            {
                addBeachBiome(anchor, biomeHalfLength);
            }
            else if (terrain.Equals(Terrain.TerrainTypes.DesertHill))
            {
                addDessertBiome(anchor, biomeHalfLength);
            }
            else if (terrain.Equals(Terrain.TerrainTypes.Grass))
            {
                addMountainBiome(anchor, biomeHalfLength);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// grows a biome
        /// </summary>
        private void growBoime(int[] anchor, int biomHalfLength, Terrain.TerrainTypes terrain)
        {
            // constants that will be used further down the line
            float k = Mathf.Sqrt(Mathf.Pow(biomHalfLength, 2) * 2);
            float a = (float)2.0f / Mathf.Log10(Mathf.Pow(k, 2) - 2.0f);

            // growing biom
            for (int i = 0; i < biomHalfLength * 3; i++)
            {
                for (int j = 0; j < biomHalfLength * 3; j++)
                {
                    // current position array where index 0 is X and index 1 is Y coordinate
                    int[] curPos = new int[2];
                    curPos[0] = anchor[0] - biomHalfLength + i;
                    curPos[1] = anchor[1] - biomHalfLength + j;

                    // check if X and Y values are within the map
                    if (curPos[0] < WIDTH && curPos[0] >= 0 && curPos[1] < HEIGHT && curPos[1] >= 0)
                    {
                        MapTile tile = ScriptableObject.CreateInstance <MapTile>();
                        // A vector used for hex position
                        Vector3Int vector = new Vector3Int(-curPos[0] + WIDTH / 2, -curPos[1] + HEIGHT / 2, 0);
                        // Find the real position (the position on the screen)
                        Vector3 mappedVector = map.CellToWorld(vector);

                        tile.Canvas         = parent;
                        tile.ScreenPosition = mappedVector;

                        // check if terrain is vacant
                        if (getTileTerrain(curPos).Equals(Terrain.TerrainTypes.NotSet))
                        {
                            // Debug.Log("Cur: X: " + curX + ", Y: " + curY);

                            // weighted random terrain allocation depending on distance from anchor
                            int value = random.Next(0, 100);

                            // weighting is done in such a that:
                            // P = (k^2 - d^2)^a,
                            //    where:
                            //       P = probability of the biome tile being set
                            //       k = a constant (calculated earlier before the nested for loops)
                            //       d = absolute distance between the anchor and any potential biome tile
                            //       a = a constant (calculated earlier before the nested for loops)
                            //
                            // the formula satisfies the two equations below:
                            //    100 = (k^2 - 2)^a, this ensures that the biome is atleast 3x3
                            //    0 = (k^2 - d^2)^a, where d is a distance for an arbitrary square just outside the biome half length
                            //
                            // so if biome half length is 7 then k = 11.3 and a = 0.484
                            float  dist = Mathf.Sqrt(Mathf.Pow(anchor[0] - curPos[0], 2) + Mathf.Pow(anchor[1] - curPos[1], 2));
                            double prob = Mathf.Pow(Mathf.Pow(k, 2) - Mathf.Pow(dist, 2), a);
                            if (value < prob)
                            {
                                occupiedBiomSpots[curPos] = terrain;
                                tile.Terrain = new Terrain(terrain);
                                SetTileTo(vector, tile);

                                // add mountains if the biome is just grass
                                if (terrain.Equals(Terrain.TerrainTypes.Grass))
                                {
                                    StructureFactory mountainFactory = new MountainFactory();
                                    if (mountainFactory.CanBuildOnto(tile, out _))
                                    {
                                        mountainFactory.BuildOnto(tile);
                                    }
                                }

                                // Refresh the tile whenever its sprite changes.
                                tile.SpriteChange += () => map.RefreshTile(vector);
                            }
                        }
                    }
                }
            }
        }