示例#1
0
    public override List<Atom> Produce(CityGenerator generator)
    {
        List<Atom> production = new List<Atom>();

        // Create a new map node
        Rule rule = generator.RuleAtCoordinates(Node.position);
        MapNode spawn = new MapNode(Node.position + forward * rule.CalculateRoadLength(this, generator));
        spawn.ruleType = ruleType;

        // Fetch the spawned node's neighbours
        List<MapNode> neighbours = generator.GetNeighbours(spawn, generator.neighboursSearchRadius);

        // Check if the node is close to one of its neighbours so that they can be merged into one node
        bool merged = false;
        Vector2 spawnPosition = spawn.PositionAsVector2;
        foreach (MapNode neighbour in neighbours) {
            // Convert coords to 2D, we don't want elevation messing around with our merging algorithm
            Vector2 neighbourPosition = neighbour.PositionAsVector2;

            // Check for proximity
            if (Vector2.Distance(spawnPosition, neighbourPosition) <= generator.nodeMergingMaximumDistance) {
                // The neighbour merges
                spawn = neighbour;

                // Stop iterating
                merged = true;
                break;
            }
        }

        // Create a map edge between the current map node and the spawn
        MapEdge spawnedEdge = new MapEdge(Node, spawn);

        if (!merged) {
            // Perform the intersection of the spawned node's edge against the neighbours' edges
            bool intersected = Intersect(spawn, spawnedEdge, neighbours);

            // Raycast to check for water
            RaycastHit hit;
            if (Physics.Raycast(spawn.position + Vector3.up * 1000f, Vector3.down, out hit)) {
                if (hit.collider.gameObject.tag == "Water") {
                    // Spawned over water, remove the edge from the starting node
                    Node.edges.Remove(spawnedEdge);

                    // Skip this node
                    return production;
                }

                // Set the Y coordinate of the spawned node to match the height where the raycast hit
                spawn.position.y = hit.point.y + 0.1f;
            }

            // Add the newly created map node to the environment
            generator.AddMapNode(spawn);

            // Continue producing only if there were no intersections
            if (!intersected) {
                // Summon a branch atom
                Atom branch = new BranchAtom(this);
                branch.Node = spawn;

                // Add the branch atom to the list of results and we're done
                production.Add(branch);
            }
        }

        return production;
    }