Example #1
0
    /// <summary>
    /// Calculates the length of the road for the given atom, taking its position and environment into account. This
    /// method is invoked by each <see cref="RoadAtom"/> during its production, in order to find out its length.
    /// </summary>
    /// <returns>The road length.</returns>
    /// <param name="currentAtom">Current atom.</param>
    /// <param name="gen">City generator.</param>
    public virtual float CalculateRoadLength(RoadAtom currentAtom, CityGenerator gen)
    {
        // Calculate how much the population density influences road length (the less population, the longer the road)
        float populationLengthFactor = 1f - gen.DensityAt(currentAtom.Node.position);

        // Calculate how much the slope of the road influences its length (the steeper, the shorter)
        float elevationLengthFactor = Mathf.Abs(gen.ElevationAt(currentAtom.Node.position) -
                                                gen.ElevationAt(currentAtom.Node.position + currentAtom.Forward));
        elevationLengthFactor = 1f - Mathf.Clamp01(gen.slopeExaggeration * elevationLengthFactor);

        // Multiply them to get the final length factor. Basically the elevation factor should only influence the
        // population factor when the road is very steep, in other cases it should be close to 1.
        float lengthFactor = populationLengthFactor * elevationLengthFactor;

        // Calculate the road length
        return gen.minimumRoadLength + lengthFactor * (gen.maximumRoadLength - gen.minimumRoadLength);
    }
Example #2
0
    public override List<RoadAtom> SpawnRoads(BranchAtom currentAtom, CityGenerator gen)
    {
        List<RoadAtom> production = new List<RoadAtom>();

        if (currentAtom.Creator != null) {
            // Get the orientation of the "parent" road (the one we're continuing in this production)
            MapNode toNode = currentAtom.Node;
            MapNode fromNode = currentAtom.Node.edges[0].FromNode;
            Vector3 parentDirection = (toNode.position - fromNode.position).normalized;

            // Get the elevation at the current point
            float currentElevation = gen.ElevationAt(currentAtom.Node.position);

            // Create three roads: left, right and straight with regard to the "parent" road's direction
            float[] angles = new float[] { -90f, 0f, 90f };
            foreach (float angle in angles) {
                // Rotate the direction vector to get the direction we'll probe in
                Vector3 roadDirection = Quaternion.Euler(0f, angle, 0f) * parentDirection;

                // Probe elevations around the given direction and get the direction of the road which is least steep
                roadDirection = LeastSteepDirection(currentAtom.Node.position, roadDirection, currentElevation, gen);

                // Create a new RoadAtom with the given road direction
                RoadAtom roadAtom = new RoadAtom(roadDirection, currentAtom.Node, Rule.Type.Rectangular);

                // Add it to the production
                production.Add(roadAtom);
            }
        } else {
            // This is the axiom, just spawn roads in all directions
            production.Add(new RoadAtom(Vector3.forward, currentAtom.Node, Rule.Type.Rectangular));
            production.Add(new RoadAtom(Vector3.back, currentAtom.Node, Rule.Type.Rectangular));
            production.Add(new RoadAtom(Vector3.left, currentAtom.Node, Rule.Type.Rectangular));
            production.Add(new RoadAtom(Vector3.right, currentAtom.Node, Rule.Type.Rectangular));
        }

        return production;
    }