예제 #1
0
    public Tile[,] CreateTerrainTilesData(float tileLength)
    {
        Tile[,] tileData = new Tile[width, height];

        Queue <Tile> borderTiles = new Queue <Tile>();
        List <Tile>  waterTiles  = new List <Tile>();
        List <Tile>  landTiles   = new List <Tile>();
        Queue <Tile> lakeTiles   = new Queue <Tile>();
        Queue <Tile> beachTiles  = new Queue <Tile>();
        Queue <Tile> coastTiles  = new Queue <Tile>();
        List <Tile>  locations   = new List <Tile>();

        List <Tile>[] regions = new List <Tile> [9];

        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                // Calculate actual center position in scene
                Vector2 center = new Vector2((-(width - 1) * 0.5f + i) * tileLength, (-(height - 1) * 0.5f + j) * tileLength);

                // Create a tile class
                Tile newTile = new Tile(i, j, center, tileLength);

                // Set property values of each tile
                // 1) Assign borders
                if (i == 0 || i == width - 1 || j == 0 || j == height - 1)
                {
                    newTile.border = true;
                    borderTiles.Enqueue(newTile);
                }

                // 2) Assign water and land
                newTile.water = !inside(newTile.Position);
                newTile.land  = !newTile.water;
                if (!newTile.water)
                {
                    newTile.DistanceToWater = int.MaxValue;
                    landTiles.Add(newTile);
                }
                else
                {
                    waterTiles.Add(newTile);
                }

                // Store in 2d array
                tileData[i, j] = newTile;
            }
        }

        // Store neighbor/adjacent tiles
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                tileData[i, j].Neighbors = GetNeighborTiles(tileData[i, j], tileData);
            }
        }

        AssignOceanTiles(borderTiles);
        AssignLakeTiles(waterTiles, lakeTiles);
        AssignBeachAndCoast(landTiles, beachTiles, locations);

        // Elevations
        AssignElevations(beachTiles);
        RedistributeElevations(locations);

        // Moistures
        AssignMoisture(lakeTiles, locations);
        RedistributeMoisture(locations);

        AssignBiome(landTiles);

        // ================================

        // Assign distance to water
        landTiles.ForEach(lt =>
        {
            if (lt.coast)
            {
                lt.DistanceToWater = 1;
                coastTiles.Enqueue(lt);
            }
        });

        while (coastTiles.Count > 0)
        {
            Tile t = coastTiles.Dequeue();

            foreach (Tile n in t.Neighbors)
            {
                if (!n.land)
                {
                    continue;
                }
                int newD = t.DistanceToWater + 1;
                if (newD < n.DistanceToWater)
                {
                    n.DistanceToWater = newD;
                    coastTiles.Enqueue(n);
                }
            }
        }

        // Assign region
        foreach (Tile lt in landTiles)
        {
            AssignRegion(lt);
            if (regions[(int)lt.RegionNum] == null)
            {
                regions[(int)lt.RegionNum] = new List <Tile>();
            }
            regions[(int)lt.RegionNum].Add(lt);
        }

        // Find a spawn region for player and theater
        // The region with the most land tiles excluding the middle region
        Region spawnRegion = Region.Northwest;

        for (int i = 0; i < regions.Length; i++)
        {
            if ((Region)i == Region.Middle)
            {
                continue;
            }
            int landTilesCount = regions[i].Count;
            //Debug.Log("Region " + ((Region)i).ToString() + " has " + landTilesCount + " land tiles");
            if (landTilesCount > regions[(int)spawnRegion].Count)
            {
                spawnRegion = (Region)i;
            }
        }

        Debug.Log("Spawn region is " + spawnRegion.ToString());

        // Determine spawn center of the theater
        // It needs to be at the farthest distance from water
        Tile potentialSpawnTile = null;

        foreach (Tile rt in regions[(int)spawnRegion])
        {
            if (potentialSpawnTile == null || rt.DistanceToWater > potentialSpawnTile.DistanceToWater)
            {
                potentialSpawnTile = rt;
                if (rt.DistanceToWater == 7)
                {
                    break;
                }
            }
        }
        potentialSpawnTile.isSpawnCenter = true;
        for (int i = -4; i <= 4; i++)
        {
            for (int j = -4; j <= 4; j++)
            {
                Vector2Int pos = new Vector2Int(potentialSpawnTile.Position.x + i, potentialSpawnTile.Position.y + j);
                tileData[pos.x, pos.y].hasBuilding = true;
            }
        }

        Debug.Log("Potential spawn tile is " + potentialSpawnTile.Position
                  + " with " + potentialSpawnTile.DistanceToWater + " units of distance to nearest water.");


        // Spawn items
        List <Tile> watermelonTileList = new List <Tile>();
        List <Tile> starbucksTileList  = new List <Tile>();
        List <Tile> sofaTileList       = new List <Tile>();

        for (int i = 0; i < regions.Length; i++)
        {
            if ((Region)i == spawnRegion)
            {
                continue;
            }

            SpawnItemEquipment(regions[i], ItemEquipment.Sofa, 0.2f, sofaTileList);
            SpawnItemEquipment(regions[i], ItemEquipment.Hammer, 0.3f);
            SpawnItemEquipment(regions[i], ItemEquipment.Starbucks, 0.4f, starbucksTileList);
            SpawnItemEquipment(regions[i], ItemEquipment.Watermelon, 0.6f, watermelonTileList);

            if (i == regions.Length - 1)
            {
                if (watermelonTileList.Count == 0)
                {
                    SpawnItemEquipment(regions[i], ItemEquipment.Watermelon, 1f, watermelonTileList);
                }
                if (starbucksTileList.Count == 0)
                {
                    SpawnItemEquipment(regions[i], ItemEquipment.Starbucks, 1f, starbucksTileList);
                }
                if (sofaTileList.Count == 0)
                {
                    SpawnItemEquipment(regions[i], ItemEquipment.Sofa, 1f, sofaTileList);
                }
            }
        }

        // Spawn enemies
        foreach (Tile watermelonTile in watermelonTileList)
        {
            SpawnEnemiesAroundItem(watermelonTile, 0.2f);
        }
        foreach (Tile starbucksTile in starbucksTileList)
        {
            SpawnEnemiesAroundItem(starbucksTile, 0.3f);
        }
        foreach (Tile sofaTile in sofaTileList)
        {
            SpawnEnemiesAroundItem(sofaTile, 0.3f);
        }

        // Trees
        foreach (Tile t in locations)
        {
            if (t.hasBuilding || t.hasItemEquipment)
            {
                continue;
            }
            List <Vector2> trees = new PoissonDiscSampling(poissonRadius, new Vector2(tileLength, tileLength), GetRejectionSamples(t.Biome)).SamplingPoints;

            List <Tile> lakeNeighbors = new List <Tile>();
            t.Neighbors.ForEach(nb =>
            {
                if (nb.lake)
                {
                    lakeNeighbors.Add(nb);
                }
            });

            if (lakeNeighbors.Count > 0)
            {
                foreach (Tile lake in lakeNeighbors)
                {
                    for (int i = 0; i < trees.Count; i++)
                    {
                        Vector2 newTreeCenter = t.Center + trees[i];
                        if (lake.IsWithinTile(newTreeCenter))
                        {
                            trees.RemoveAt(i);
                        }
                    }
                }
            }

            t.Trees = trees;
        }

        // Rocks
        foreach (Tile t in locations)
        {
            if (t.hasBuilding || t.hasItemEquipment)
            {
                continue;
            }
            if (t.Biome != Biome.DESERT && t.Biome != Biome.TEMPERATE_DESERT)
            {
                continue;
            }

            t.Rocks = new List <Vector2>();

            // First rock
            if (RandomSelect_Percentage(0.1f))
            {
                t.Rocks.Add(new Vector2(UnityEngine.Random.Range(-t.Length / 2f, t.Length / 2f), UnityEngine.Random.Range(-t.Length / 2f, t.Length / 2f)));
            }

            // Second rock
            if (RandomSelect_Percentage(0.05f))
            {
                t.Rocks.Add(new Vector2(UnityEngine.Random.Range(-t.Length / 2f, t.Length / 2f), UnityEngine.Random.Range(-t.Length / 2f, t.Length / 2f)));
            }
        }

        return(tileData);
    }