Пример #1
0
        public override void DisplayMap(WorldMapData mapData)
        {
            if (!enabled)
            {
                return;
            }

            _mapData   = mapData;
            _heightMap = _mapData.GetLayer <HeightMapLayerData>().heightMap;

            ClearChunks();

            //Chunks
            var chunksWide = Mathf.CeilToInt(mapData.width / (float)chunkWidth);
            var chunksHigh = Mathf.CeilToInt(mapData.height / (float)chunkHeight);

            for (var chunkY = 0; chunkY < chunksHigh; chunkY++)
            {
                for (var chunkX = 0; chunkX < chunksWide; chunkX++)
                {
                    //Create the mesh
                    var startX    = chunkX * chunkWidth;
                    var startY    = chunkY * chunkHeight;
                    var chunkView = GetChunk(new Vector2Int(chunkX, chunkY));
                    chunkView.transform.localPosition = new Vector3(0, 0, 0);
                    var mesh = HexMeshUtility.GenerateHexagonMesh(radius, border, startX, startY, chunkWidth, chunkHeight, mapData.width, mapData.height, _heightMap, GetColor, GetElevation);
                    chunkView.SetMesh(mesh);
                }
            }
        }
        public override void DisplayMap(WorldMapData mapData)
        {
            if (!enabled)
            {
                return;
            }

            var heightMap  = mapData.GetLayer <HeightMapLayerData>().heightMap;
            int chunksWide = Mathf.CeilToInt(mapData.width / (float)chunkWidth);
            int chunksHigh = Mathf.CeilToInt(mapData.height / (float)chunkHeight);

            if (Application.isEditor)
            {
                ClearChunks();
            }

            for (var y = 0; y < chunksHigh; y++)
            {
                for (var x = 0; x < chunksWide; x++)
                {
                    var chunk    = GetChunk(new Vector2Int(x, y));
                    var meshData = VoxelMeshUtility.CreateMeshData(heightMap, mapData.width, mapData.height, x, y, chunkWidth,
                                                                   chunkHeight, _terrainTable, edges, edgeThickness);
                    chunk.SetMesh(meshData.CreateMesh());
                }
            }
        }
        private void DisplayMap(WorldMapData mapData)
        {
            var mapViews = GetComponents <IWorldMapView>();

            foreach (var view in mapViews)
            {
                view.DisplayMap(mapData);
            }
        }
 public void GenerateMap()
 {
     if (randomizeSeed)
     {
         seed = Random.Range(int.MinValue, Int32.MaxValue);
     }
     _mapData = _generator.GenerateMap(seed);
     DisplayMap(_mapData);
 }
Пример #5
0
        public override void AddToWorld(WorldMapData mapData)
        {
            if (useRegions)
            {
                AddToWorldUsingRegions(mapData);
                return;
            }

            AddToWorldDefault(mapData);
        }
Пример #6
0
        private void AddToWorldDefault(WorldMapData mapData)
        {
            var points = PoissonDiskSampling.GenerateIntPoints(radius, new Vector2Int(mapData.width, mapData.height),
                                                               mapData.seed, maxSamplesPerPoint);
            var layer = new PoissonMapLayerData
            {
                points = points
            };

            mapData.layers.Add(layer);
        }
Пример #7
0
        private void AddToWorldUsingRegions(WorldMapData mapData)
        {
            var regionLayer = mapData.GetLayer <RegionMapLayerData>();
            var regionMap   = regionLayer.regionMap;

            //Only select points in valid regions
            var points = PoissonDiskSampling.GenerateIntPoints(radius, new Vector2Int(mapData.width, mapData.height),
                                                               mapData.seed, maxSamplesPerPoint,
                                                               (pt) =>
            {
                if (regionMap[pt.y * mapData.width + pt.x] <= 0)
                {
                    return(false);
                }

                if (edgeAvoidance == 0)
                {
                    return(true);
                }

                //Check any points in radius for overlap with bad region
                var searchStartX = Mathf.Max(0, pt.x - edgeAvoidance);
                var searchEndX   = Mathf.Min(pt.x + edgeAvoidance, mapData.width - 1);

                var searchStartY = Mathf.Max(0, pt.y - edgeAvoidance);
                var searchEndY   = Mathf.Min(pt.y + edgeAvoidance, mapData.height - 1);

                for (var x = searchStartX; x <= searchEndX; x++)
                {
                    for (var y = searchStartY; y <= searchEndY; y++)
                    {
                        //Index was stored with +1 so we could avoid initializing the grid to all -1 values
                        int regionIndex = regionMap[y * mapData.width + x];
                        if (regionIndex <= 0)
                        {
                            return(false);
                        }
                    }
                }

                return(true);
            });

            var layer = new PoissonMapLayerData
            {
                points = points
            };

            mapData.layers.Add(layer);
        }
Пример #8
0
        public WorldMapData GenerateMap(int seed)
        {
            var worldData = new WorldMapData
            {
                seed   = seed,
                width  = mapWidth,
                height = mapHeight
            };

            for (int i = 0; i < layerGenerators.Count; i++)
            {
                layerGenerators[i].AddToWorld(worldData);
            }

            return(worldData);
        }
        public override void DisplayMap(WorldMapData worldMapData)
        {
            if (!enabled)
            {
                return;
            }
            var heightMap = worldMapData.GetLayer <HeightMapLayerData>().heightMap;

            if (terrainTable == null)
            {
                var meshData = TerrainMeshUtility.GenerateMesh(heightMap, worldMapData.width, worldMapData.height, heightScale, levelOfDetail);
                _meshFilter.mesh = meshData.CreateMesh();
            }
            else
            {
                var meshData = TerrainMeshUtility.GenerateMesh(heightMap, worldMapData.width, worldMapData.height, levelOfDetail,
                                                               x =>
                {
                    var terrainType = terrainTable.GetTerrainType(x);
                    if (smooth)
                    {
                        var t = Mathf.InverseLerp(terrainType.Floor, terrainType.Threshold, x);
                        return(Mathf.Lerp(terrainType.MinElevation, terrainType.MaxElevation, t) * heightScale);
                    }
                    return(terrainTable.GetTerrainType(x).MinElevation *heightScale);
                },
                                                               x =>
                {
                    var terrainType = terrainTable.GetTerrainType(x);
                    if (!useColorGradient)
                    {
                        return(terrainType.ColorGradient.Evaluate(0));
                    }
                    var t = Mathf.InverseLerp(terrainType.Floor, terrainType.Threshold, x);
                    return(terrainType.ColorGradient.Evaluate(t));
                });
                _meshFilter.mesh = meshData.CreateMesh();
            }
        }
Пример #10
0
 public abstract void AddToWorld(WorldMapData mapData);
Пример #11
0
 public abstract void DisplayMap(WorldMapData mapData);
Пример #12
0
        public void DisplayMap(WorldMapData mapData)
        {
            if (!enabled || prefab == null)
            {
                return;
            }

            prefab.gameObject.SetActive(false);

            ClearLines();

            var positionOffset = new Vector3(mapData.width * -0.5f, 0, mapData.height * 0.5f) + offset;

            var regionLayer = mapData.GetLayer <RegionMapLayerData>();

            foreach (var region in regionLayer.regions)
            {
                //Each region could have more than one border line to draw
                //Border point list is unordered so we need to also figure out what the lines are

                //Convert border points to 3D space
                var points = new List <Vector3>(region.borderPoints.Select((pt) => new Vector3(pt.x, 0, -pt.y) + positionOffset));

                //Extract lines from list of points by getting closest points
                var lines       = new List <List <Vector3> >();
                var currentLine = new List <Vector3>();
                lines.Add(currentLine);
                var currentPt = points[0];
                points.RemoveAt(0);
                while (points.Count > 0)
                {
                    float minDistance = float.MaxValue;
                    int   minIndex    = -1;

                    for (int i = 0; i < points.Count; i++)
                    {
                        var distance = (currentPt - points[i]).sqrMagnitude;
                        if (distance < minDistance)
                        {
                            minDistance = distance;
                            minIndex    = i;
                        }
                    }


                    if (minDistance > 2)
                    {
                        //Start a new line if the closest points was more than a certain distance away
                        lines.Add(currentLine);
                        currentLine = new List <Vector3>();
                    }

                    currentPt = points[minIndex];
                    currentLine.Add(points[minIndex]);
                    points.RemoveAt(minIndex);
                }

                var regionColor = regionColors.Length > 0 ? regionColors[(region.id - 1) % regionColors.Length] : Color.white;

                foreach (var line in lines)
                {
                    //Don't draw anything with less than 2 points
                    if (line.Count < minLineLength)
                    {
                        continue;
                    }

                    var lineRenderer = Instantiate(prefab, transform);
                    lineRenderer.transform.localEulerAngles = new Vector3(90, 0, 0);
                    lineRenderer.startColor = regionColor;
                    lineRenderer.endColor   = regionColor;

                    //lineRenderer.positionCount = region.borderPoints.Count;
                    lineRenderer.positionCount = line.Count;
                    lineRenderer.SetPositions(line.ToArray());

                    var startPt = line[0];
                    var endPt   = line[line.Count - 1];
                    //If the end is close enough to the start then complete the loop
                    if ((startPt - endPt).sqrMagnitude <= 2)
                    {
                        lineRenderer.loop = true;
                    }

                    lineRenderer.gameObject.SetActive(true);
                    lineRenderers.Add(lineRenderer);
                }
            }
        }
        public override void AddToWorld(WorldMapData mapData)
        {
            var rng         = new System.Random(mapData.seed);
            var regionLayer = new RegionMapLayerData();

            var heightMapLayer = mapData.GetLayer <HeightMapLayerData>();

            if (heightMapLayer == null)
            {
                throw new Exception("Cannot generate region layer without a height map");
            }

            var heightMap = heightMapLayer.heightMap;

            //Generate stuff
            var regionMap = new int[mapData.width * mapData.height];

            int emptyTileCount = 0;

            //Initialize map such that negative values are 'water'
            for (int i = 0; i < regionMap.Length; i++)
            {
                if (heightMap[i] > waterLevel)
                {
                    emptyTileCount++;
                    regionMap[i] = 0;
                }
                else
                {
                    regionMap[i] = -1;
                }
            }

            List <RegionData> regions = new List <RegionData>();

            for (int i = 0; i < 100 && regions.Count < regionCount; i++)
            {
                //Pick a random point
                Vector2Int pt    = new Vector2Int(rng.Next(0, mapData.width), rng.Next(0, mapData.height));
                int        index = pt.y * mapData.width + pt.x;

                //If point is not empty try again
                if (regionMap[index] != 0)
                {
                    continue;
                }

                //Regions are assigned id starting from 1
                var region = new RegionData
                {
                    id      = regions.Count + 1,
                    spawnPt = pt
                };

                AddPointToRegion(region, regionMap, mapData.width, mapData.height, pt);
                emptyTileCount -= 1;

                regions.Add(region);
            }

            if (regions.Count != regionCount)
            {
                throw new Exception("Failed to create enough regions");
            }

            var neighbors = new List <Vector2Int>();

            int maxIterations = mapData.width * mapData.height;
            int count         = 0;
            int emptyCount    = 0;

            //Grow each region until there are no more empty tiles remaining
            while (emptyTileCount > 0 && emptyCount != regions.Count && count < maxIterations)
            {
                emptyCount = 0;
                foreach (var region in regions)
                {
                    if (region.borderPoints.Count == 0)
                    {
                        //Count the number of regions that can no longer grow
                        //Then we can early out if all regions are maxed out
                        emptyCount++;
                        continue;
                    }

                    if (TryExpandRegion(region, regionMap, mapData.width, mapData.height, rng, neighbors))
                    {
                        emptyTileCount--;
                    }
                }

                count++;
            }


            count = 0;
            while (emptyTileCount != 0 && count < maxIterations)
            {
                count++;

                //We may have islands so lets find one and expand the closest region into it
                int index = FindUnassignedRegion(regionMap);
                int y     = index / mapData.width;
                int x     = index - (y * mapData.width);
                var pt    = new Vector2Int(x, y);

                //Find the region with spawn point closest to pt
                var closestRegion = FindClosestRegion(regions, pt);
                AddPointToRegion(closestRegion, regionMap, mapData.width, mapData.height, pt);
                emptyTileCount--;

                //Expand region until it has no border points left
                while (closestRegion.borderPoints.Count > 0)
                {
                    if (TryExpandRegion(closestRegion, regionMap, mapData.width, mapData.height, rng, neighbors))
                    {
                        emptyTileCount--;
                    }
                }
            }

            if (emptyTileCount != 0)
            {
                Debug.LogError($"Failed to fill all tiles {emptyTileCount} (MaxIterations? {count >= maxIterations})");
            }

            //Validate
            for (int i = 0; i < regionMap.Length; i++)
            {
                if (regionMap[i] == 0)
                {
                    Debug.LogError("Found a zero. TODO: Handle Islands");
                    break;
                }
            }

            //Clear Border Points
            foreach (var region in regions)
            {
                region.borderPoints.Clear();
            }

            //Find actual border points
            for (int y = 0; y < mapData.height; y++)
            {
                for (int x = 0; x < mapData.width; x++)
                {
                    var index = y * mapData.width + x;

                    if (regionMap[index] <= 0)
                    {
                        continue;
                    }

                    var region = regions[regionMap[index] - 1];
                    var pt     = new Vector2Int(x, y);
                    if (IsBorder(regionMap, mapData.width, mapData.height, pt))
                    {
                        region.borderPoints.Add(pt);
                    }
                }
            }

            regionLayer.regionMap = regionMap;
            regionLayer.regions   = regions;

            mapData.layers.Add(regionLayer);
        }
Пример #14
0
        public async void DisplayMap(WorldMapData worldMapData)
        {
            if (!enabled)
            {
                return;
            }

            var heightMapLayer = worldMapData.GetLayer <HeightMapLayerData>();
            var regionMapLayer = worldMapData.GetLayer <RegionMapLayerData>();

            var width  = worldMapData.width;
            var height = worldMapData.height;

            var heightMap = heightMapLayer.heightMap;
            var regions   = regionMapLayer.regions;
            var regionMap = regionMapLayer.regionMap;

            var terrainMap = _terrainTable.GetTerrainMap(heightMap);
            var colorMap   = TerrainTable.GetColorMap(heightMap, terrainMap, gradiate);

            if (fillRegions && regionColors.Length > 0)
            {
                for (int i = 0; i < colorMap.Length; i++)
                {
                    var regionIndex = regionMap[i];
                    if (regionIndex <= 0)
                    {
                        continue;
                    }

                    var regionColor = regionColors[(regionIndex - 1) % regionColors.Length];
                    var alpha       = Mathf.Clamp01(regionColor.a * regionFillAlpha);
                    colorMap[i] = regionColor * alpha + (1 - alpha) * colorMap[i];
                }
            }

            if (drawBorders && regionColors.Length > 0)
            {
                foreach (var region in regions)
                {
                    foreach (var pt in region.borderPoints)
                    {
                        int index       = pt.y * width + pt.x;
                        var regionIndex = regionMap[index];
                        var regionColor = regionColors[regionIndex - 1];
                        var alpha       = regionColor.a * borderAlpha;
                        colorMap[index]   = regionColor * alpha + (1 - alpha) * colorMap[index];
                        colorMap[index].a = 1;
                    }
                }
            }

            if (drawSpawnPoints)
            {
                foreach (var region in regions)
                {
                    var pt    = region.spawnPt;
                    int index = pt.y * width + pt.x;
                    colorMap[index] = Color.black;
                }
            }

            if (drawPoissonPoints)
            {
                var poissonLayer = worldMapData.GetLayer <PoissonMapLayerData>();
                if (poissonLayer != null)
                {
                    foreach (var pt in poissonLayer.points)
                    {
                        int index = pt.y * width + pt.x;
                        colorMap[index] = Color.black;
                    }
                }
            }

            var texture = TextureUtility.GetColorMap(colorMap, width, height);

            texture.filterMode = filterMode;
            SetTexture(texture);

            if (scaleTexture)
            {
                await TextureScale.BilinearAsync(texture, Mathf.Min(2048, Mathf.RoundToInt(width *textureScale)), Mathf.Min(2048, Mathf.RoundToInt(height *textureScale)));
            }
        }
Пример #15
0
 public override void AddToWorld(WorldMapData worldMapData)
 {
     worldMapData.layers.Add(Generate(worldMapData.width, worldMapData.height, worldMapData.seed));
 }