예제 #1
0
    public static bool SetOutgoingRiver(
        Hex source,
        Hex target,
        HexDirections direction,
        ref RiverDigraph riverDigraph
        )
    {
        if (
            riverDigraph.HasOutgoingRiverInDirection(
                source,
                direction
                )
            )
        {
            return(false);
        }

        if (
            !IsValidRiverDestination(
                source,
                target
                )
            )
        {
            return(false);
        }

        riverDigraph.RemoveOutgoingRivers(
            source
            );

        if (
            riverDigraph.HasIncomingRiverInDirection(
                source,
                direction
                )
            )
        {
            riverDigraph.RemoveIncomingRivers(
                source
                );
        }

        riverDigraph.RemoveIncomingRivers(target);


        riverDigraph.AddVerticesAndEdge(
            new RiverEdge(
                source,
                target,
                direction
                )
            );

        return(true);

//		SetRoad((int)direction, false);
    }
예제 #2
0
    public HexMapRivers(
        HexMap hexMap,
        List <ClimateData> climate,
        int waterLevel,
        int elevationMax
        )
    {
        _hexMap                = hexMap;
        _riverLists            = new List <RiverList>();
        _riverOriginCandidates = new List <Hex>();
        _riverDigraph          = new RiverDigraph();
        _adjacencyGraph        = hexMap.AdjacencyGraph;

        for (int i = 0; i < _hexMap.SizeSquared; i++)
        {
            Hex hex = _hexMap.GetHex(i);

            if (hex.IsUnderwater)
            {
                continue;
            }

            ClimateData data = climate[i];

            float weight =
                data.moisture * (hex.elevation - waterLevel) /
                (elevationMax - waterLevel);

            if (weight > 0.75)
            {
                _riverOriginCandidates.Add(hex);
                _riverOriginCandidates.Add(hex);
            }

            if (weight > 0.5f)
            {
                _riverOriginCandidates.Add(hex);
            }

            if (weight > 0.25f)
            {
                _riverOriginCandidates.Add(hex);
            }
        }
    }
예제 #3
0
    public void RefreshTerrainTypes(
        ClimateParameters parameters,
        RiverDigraph riverDigraph
        )
    {
        int temperatureJitterChannel = Random.Range(0, 4);

        int rockDesertElevation =
            parameters.elevationMax -
            (parameters.elevationMax - parameters.waterLevel) / 2;

        Holdridge holdridge = new Holdridge();

        foreach (Hex hex in _hexMap.Hexes)
        {
            float temperature = ClimateArray[hex.Index].temperature;
            float moisture    = ClimateArray[hex.Index].moisture;
            if (!hex.IsUnderwater)
            {
                hex.HoldrigeZone = holdridge.GetHoldridgeZone(
                    temperature,
                    moisture
                    );

                continue;

                int temperatureBand = 0;

                for (
                    ;
                    temperatureBand < temperatureBands.Length;
                    temperatureBand++
                    )
                {
                    if (temperature < temperatureBands[temperatureBand])
                    {
                        break;
                    }
                }

                int moistureBand = 0;

                for (; moistureBand < moistureBands.Length; moistureBand++)
                {
                    if (moisture < moistureBands[moistureBand])
                    {
                        break;
                    }
                }

                Biome hexBiome = biomes[temperatureBand * 4 + moistureBand];

                if (hexBiome.terrain == Terrains.Desert)
                {
                    if (hex.elevation >= rockDesertElevation)
                    {
                        hexBiome.terrain = Terrains.Stone;
                    }
                }
                else if (hex.elevation == parameters.elevationMax)
                {
                    hexBiome.terrain = Terrains.Snow;
                }

                if (hexBiome.terrain == Terrains.Snow)
                {
                    hexBiome.plant = 0;
                }

                if (hexBiome.plant < 3 && riverDigraph.HasRiver(hex))
                {
                    hexBiome.plant += 1;
                }

                //hex.Biome = hexBiome;
                //hex.ClimateData = ClimateArray[hex.Index];
            }
            else
            {
                LZone lZone;

                if (hex.elevation == parameters.waterLevel - 1)
                {
                    int        cliffs = 0;
                    int        slopes = 0;
                    List <Hex> neighbors;

                    if (_hexMap.TryGetNeighbors(hex, out neighbors))
                    {
                        foreach (Hex neighbor in neighbors)
                        {
                            int delta =
                                neighbor.elevation - hex.WaterLevel;

                            if (delta == 0)
                            {
                                slopes += 1;
                            }
                            else if (delta > 0)
                            {
                                cliffs += 1;
                            }
                        }
                    }

                    // More than half neighbors at same level. Inlet or
                    // lake, therefore terrain is grass.
                    if (cliffs + slopes > 3)
                    {
                        lZone = LZone.Steppe;
                    }

                    // More than half cliffs, terrain is stone.
                    else if (cliffs > 0)
                    {
                        lZone = LZone.DesertScb;
                    }

                    // More than half slopes, terrain is beach.
                    else if (slopes > 0)
                    {
                        lZone = LZone.DesertH;
                    }

                    // Shallow non-coast, terrain is grass.
                    else
                    {
                        lZone = LZone.Steppe;
                    }
                }
                else if (hex.elevation >= parameters.waterLevel)
                {
                    lZone = LZone.Steppe;
                }
                else if (hex.elevation < 0)
                {
                    lZone = LZone.DesertH;
                }
                else
                {
                    lZone = LZone.WTundra;
                }

                // Coldest temperature band produces mud instead of grass.
                if (
                    lZone == LZone.Steppe &&
                    temperature < temperatureBands[0]
                    )
                {
                    lZone = LZone.WTundra;
                }

                //hex.Biome = new Biome(terrain, 0);
            }
        }
    }
예제 #4
0
    public void Triangulate(
        HexMap hexMap,
        float hexOuterRadius,
        HexAdjacencyGraph adjacencyGraph,
        RiverDigraph riverGraph,
        RoadUndirectedGraph roadGraph,
        ElevationDigraph elevationGraph
        )
    {
        _terrainLayer.Clear();
        _riversLayer.Clear();
        _roadsLayer.Clear();
        _openWaterLayer.Clear();
        _waterShoreLayer.Clear();
        _estuariesLayer.Clear();
        _features.Clear();

        for (int i = 0; i < Hexes.Length; i++)
        {
            Hex current = Hexes[i];

            if (current)
            {
                Dictionary <HexDirections, Hex> neighbors =
                    adjacencyGraph.GetNeighborByDirection(current);

                Dictionary <HexDirections, ElevationEdgeTypes> edgeTypes =
                    elevationGraph.GetNeighborEdgeTypes(current);

                Dictionary <HexDirections, bool> roadEdges =
                    roadGraph.GetNeighborRoads(current);

                List <HexDirections> borderDirections =
                    adjacencyGraph.GetBorderDirectionsList(current);

                HexRiverData riverData = riverGraph.GetRiverData(current);

                TriangulateHex(
                    current,
                    neighbors,
                    borderDirections,
                    hexOuterRadius,
                    riverData,
                    roadEdges,
                    edgeTypes,
                    hexMap.WrapSize,
                    _terrainLayer,
                    _riversLayer,
                    _roadsLayer,
                    _openWaterLayer,
                    _waterShoreLayer,
                    _estuariesLayer,
                    _features
                    );
            }
        }

        _terrainLayer.Draw();
        _riversLayer.Draw();
        _roadsLayer.Draw();
        _openWaterLayer.Draw();
        _waterShoreLayer.Draw();
        _estuariesLayer.Draw();
        _features.Apply();
    }
예제 #5
0
        public Hex Step(
            HexAdjacencyGraph adjacencyGraph,
            ref RiverDigraph riverDigraph,
            float extraLakeProbability,
            float hexOuterRadius,
            int waterLevel
            )
        {
            if (RiverHead.IsUnderwater)
            {
                return(null);
            }

            int minNeighborElevation  = int.MaxValue;
            int minNeighborWaterLevel = int.MaxValue;

            List <HexDirections> flowDirections = new List <HexDirections>();
            HexDirections        direction      = HexDirections.Northeast;

            for (
                HexDirections directionCandidate = HexDirections.Northeast;
                directionCandidate <= HexDirections.Northwest;
                directionCandidate++
                )
            {
                Hex neighborInDirection =
                    adjacencyGraph.TryGetNeighborInDirection(
                        RiverHead,
                        directionCandidate
                        );

                if (!neighborInDirection || River.Contains(neighborInDirection))
                {
                    continue;
                }

                if (neighborInDirection.elevation < minNeighborElevation)
                {
                    minNeighborElevation  = neighborInDirection.elevation;
                    minNeighborWaterLevel = neighborInDirection.WaterLevel;
                }

                // If the direction points to the river origin, or to a
                // neighbor which already has an incoming river, continue.
                if (
                    neighborInDirection == RiverHead ||
                    riverDigraph.HasIncomingRiver(neighborInDirection)
                    )
                {
                    continue;
                }

                int delta =
                    neighborInDirection.elevation - RiverHead.elevation;

                // If the elevation in the given direction is positive,
                // continue.
                if (delta > 0)
                {
                    continue;
                }

                // If the direction points away from the river origin and
                // any neighbors which already have an incoming river, and
                // the elevation in the given direction is negative or
                // zero, and the neighbor has an outgoing river, branch
                // river in this direction.
                if (
                    riverDigraph.HasOutgoingRiver(neighborInDirection)
                    )
                {
                    SetOutgoingRiver(
                        RiverHead,
                        neighborInDirection,
                        directionCandidate,
                        ref riverDigraph
                        );

                    River.Add(neighborInDirection);
                    return(neighborInDirection);
                }

                // If the direction points away from the river origin and
                // any neighbors which already have an incoming river, and
                // the elevation in the given direction is not positive,
                // and the neighbor does not have an outgoing river in the
                // given direction...

                // If the direction is a decline, make the probability for
                // the branch 4 / 5.
                if (delta < 0)
                {
                    flowDirections.Add(directionCandidate);
                    flowDirections.Add(directionCandidate);
                    flowDirections.Add(directionCandidate);
                }

                // If the rivers local length is 1, and the direction does
                // not result in a slight river bend, but rather a straight
                // river or a corner river, make the probability of the
                // branch 2 / 5
                if (
                    River.Count == 1 ||
                    (directionCandidate != direction.NextClockwise2() &&
                     directionCandidate != direction.PreviousClockwise2())
                    )
                {
                    flowDirections.Add(directionCandidate);
                }

                flowDirections.Add(directionCandidate);
            }

            // If there are no candidates for branching the river...
            if (flowDirections.Count == 0)
            {
                // If the river contains only the river origin...
                if (River.Count == 1)
                {
                    // Do nothing and return null
                    return(null);
                }

                // If the hex is surrounded by hexes at a higher elevation,
                // set the water level of the hex to the minium elevation
                // of all neighbors.
                if (minNeighborElevation >= RiverHead.elevation)
                {
                    RiverHead.WaterLevel = RiverHead.elevation;

                    // If the hex is of equal elevation to a neighbor with
                    // a minimum elevation, lower the current hexes
                    // elevation to one below the minimum elevation of all
                    // of its neighbors so that it becomes a small lake
                    // that the river feeds into, and then break out of the
                    // while statement terminating the river in a lake
                    // rather than into the ocean.
                    if (minNeighborElevation == RiverHead.elevation)
                    {
                        RiverHead.SetElevation(
                            minNeighborElevation - 1,
                            hexOuterRadius,
                            _hexMap.WrapSize
                            );
                    }
                }

                return(null);
            }

            direction = flowDirections[
                Random.Range(0, flowDirections.Count)
                        ];

            Hex neighborInRandomDirection =
                adjacencyGraph.TryGetNeighborInDirection(
                    RiverHead,
                    direction
                    );

            SetOutgoingRiver(
                RiverHead,
                neighborInRandomDirection,
                direction,
                ref riverDigraph
                );

            // If the hex is lower than the minimum elevation of its
            // neighbors assign a lake based on a specified probability.
            if (
                minNeighborElevation >= RiverHead.elevation &&
                Random.value < extraLakeProbability
                )
            {
                RiverHead.WaterLevel = RiverHead.elevation;

                RiverHead.SetElevation(
                    minNeighborElevation - 1,
                    hexOuterRadius,
                    _hexMap.WrapSize
                    );
            }

            River.Add(neighborInRandomDirection);
            return(neighborInRandomDirection);
        }