Пример #1
0
 public bool isSame(MapEdge e)
 {
     if (e.from != this.from || e.to != this.to)
     {
         return(false);
     }
     return(true);
 }
Пример #2
0
    private void GenerateEdges(List <Vector2> points)
    {
        List <LineSegment> minimumSpanningTree;
        List <LineSegment> delaunayTriangulation;
        List <LineSegment> finalEdges = new List <LineSegment>();

        // Create the Voronoi diagram using the AS3 Delaunay library
        List <uint> colors = new List <uint> ();

        for (int i = 0; i < points.Count; i++)
        {
            colors.Add(0);
        }
        Delaunay.Voronoi voronoi = new Delaunay.Voronoi(points, colors, new Rect(0, 0, _mapWidth, _mapHeight));
        minimumSpanningTree   = voronoi.SpanningTree(KruskalType.MINIMUM);
        delaunayTriangulation = voronoi.DelaunayTriangulation();

        // First add any line segment in the minimum spanning tree to the list _edges
        for (int i = delaunayTriangulation.Count - 1; i >= 0; i--)
        {
            for (int j = 0; j < minimumSpanningTree.Count; j++)
            {
                if (LineSegmentEquals(minimumSpanningTree[j], delaunayTriangulation[i]))
                {
                    finalEdges.Add(delaunayTriangulation[i]);

                    delaunayTriangulation.RemoveAt(i);

                    break;
                }
            }
        }

        // Add a random amount of line segments in the delaunay triangulation but NOT in the minimum spanning tree to the list _edges
        for (int i = 0, count = delaunayTriangulation.Count; i < count; i++)
        {
            float rand = UnityEngine.Random.value;
            if (rand <= 0.35)
            {
                finalEdges.Add(delaunayTriangulation[i]);
            }
        }

        // Create the edges on the map
        // Also update neighbours properties on the nodes
        for (int i = 0, count = finalEdges.Count; i < count; i++)
        {
            LineSegment line = finalEdges[i];

            Vector3 p0 = new Vector3(line.p0.Value.x, line.p0.Value.y, 0);
            Vector3 p1 = new Vector3(line.p1.Value.x, line.p1.Value.y, 0);

            MapEdge mapEdge = CreateMapEdge(p0, p1);
            mapEdge.Initialize(p0, p1);
        }
    }
Пример #3
0
    public void AddEdge(string from, string to)
    {
        Node       fromNode;
        Node       toNode;
        GameObject fromGameObject = null;
        GameObject toGameObject   = null;

        for (int i = 0; i < this.gameObject.transform.childCount; i++)
        {
            GameObject gameObject = this.gameObject.transform.GetChild(i).gameObject;
            Node       node       = gameObject.GetComponent(typeof(Node)) as Node;
            if (node != null && node.id == from)
            {
                fromNode       = node;
                fromGameObject = gameObject;
            }
            else if (node != null && node.id == to)
            {
                toNode       = node;
                toGameObject = gameObject;
            }
        }
        GameObject mapEdge          = Instantiate(mapEdgePrefab, new Vector3(), Quaternion.identity);
        MapEdge    mapEdgeComponent = mapEdge.GetComponent(typeof(MapEdge)) as MapEdge;

        if (fromGameObject != null && toGameObject != null)
        {
            List <GameObject> connectedEdges = null;
            List <GameObject> connectedNodes = null;

            if (edgeObjectMap.TryGetValue(from, out connectedEdges))
            {
            }
            else
            {
                connectedEdges = new List <GameObject>();
            }

            if (edgeNodeMap.TryGetValue(from, out connectedNodes))
            {
            }
            else
            {
                connectedNodes = new List <GameObject>();
            }

            connectedEdges.Add(mapEdge);
            connectedNodes.Add(toGameObject);

            edgeObjectMap[from] = connectedEdges;
            edgeNodeMap[from]   = connectedNodes;

            mapEdgeComponent.draw(fromGameObject.transform.position, toGameObject.transform.position);
        }
    }
Пример #4
0
    public void AddEdge(MapEdge _mapEdge)
    {
        bool tIsUnique = true;

        for (int i = 0; i < edges.Count; i++)
        {
            MapEdge tOtherEdge = edges[i];
            if (_mapEdge.CompareTo(tOtherEdge) == 0)
            {
                tIsUnique = false;
            }
        }
        if (tIsUnique)
        {
            edges.Add(_mapEdge);
        }
    }
Пример #5
0
    private MapEdge CreateMapEdge(Vector3 p0, Vector3 p1)
    {
        GameObject graphEdgeGO = GameObject.Instantiate(_graphEdgePrefab) as GameObject;

        graphEdgeGO.transform.SetParent(transform);
        MapEdge mapEdge = graphEdgeGO.GetComponent <MapEdge>();

        string node1Id = GetNodeIdFromVector3(p0);
        string node2Id = GetNodeIdFromVector3(p1);

        _mapNodes[node1Id].AddNeighbour(node2Id);
        _mapNodes[node2Id].AddNeighbour(node1Id);

        _mapNodes[node1Id].AddEdge(mapEdge);
        _mapNodes[node2Id].AddEdge(mapEdge);

        _mapEdges.Add(mapEdge);

        return(mapEdge);
    }
Пример #6
0
    public static bool EdgeExists(MapNode prev, MapNode curr)
    {
        MapEdge testEdge = new MapEdge(prev, curr);

        foreach (MapEdge me in edges)
        {
            //Since these are added in tier order, you only need to check up until you reach the current tier
            //me.from is the MapEdge's first node
            if (me.from.tier > GameState.currentTier)
            {
                return(false);
            }
            if (me.isSame(testEdge))
            {
                return(true);
            }
        }
        //If we are on the last node, and somehow an edge doesnt exist...
        //should be unreachable
        return(false);
    }
Пример #7
0
    public void LoadMap(MapBlob blob)
    {
        _blob = blob;

        // Temp
        foreach (KeyValuePair <string, MapNodeData> kvp in blob.MapNodes)
        {
            MapNode mapNode = CreateMapNode(kvp.Key);
            mapNode.InitializeFromData(kvp.Value, MapNodeTappedCallback);
        }

        for (int i = 0, count = blob.MapEdges.Count; i < count; i++)
        {
            MapEdge mapEdge = CreateMapEdge(blob.MapEdges[i].P0, blob.MapEdges[i].P1);
            mapEdge.Initialize(blob.MapEdges[i]);
        }

        _currentNode = _mapNodes[blob.CurrentNode];

        _currentNode.ToggleEdgeVisibility(true);
    }
Пример #8
0
    public void ActivateNode(string node)
    {
        if (edgeObjectMap.ContainsKey(node))
        {
            List <GameObject> edges = edgeObjectMap[node];
            foreach (GameObject edge in edges)
            {
                MapEdge mapEdgeComponent = edge.GetComponent(typeof(MapEdge)) as MapEdge;
                mapEdgeComponent.activate();
            }
        }

        if (edgeNodeMap.ContainsKey(node))
        {
            List <GameObject> nodes = edgeNodeMap[node];
            foreach (GameObject nodeObject in nodes)
            {
                Node nodeComponent = nodeObject.GetComponent(typeof(Node)) as Node;
                nodeComponent.Reveal();
            }
        }
    }
Пример #9
0
        public static void DrawRandomBorder <T>(T border, DataGrid <T> grid, Vector2Int borderThickness, int z, MapEdge edges, bool overwrite = false)
        {
            if (edges.HasFlag(MapEdge.North))
            {
                int thickness = Random.Int(borderThickness);
                for (int x = grid.Bounds.xMin; x <= grid.Bounds.xMax; x++)
                {
                    for (int y = grid.Bounds.yMax - thickness; y <= grid.Bounds.yMax; y++)
                    {
                        grid.Add(new Vector3Int(x, y, z), border, overwrite);
                    }
                    thickness = ChangeThickness(thickness, borderThickness);
                }
            }

            if (edges.HasFlag(MapEdge.South))
            {
                int thickness = Random.Int(borderThickness);
                for (int x = grid.Bounds.xMin; x <= grid.Bounds.xMax; x++)
                {
                    for (int y = grid.Bounds.yMin + thickness; y >= grid.Bounds.yMin; y--)
                    {
                        grid.Add(new Vector3Int(x, y, 0), border, overwrite);
                    }
                    thickness = ChangeThickness(thickness, borderThickness);
                }
            }

            if (edges.HasFlag(MapEdge.East))
            {
                int thickness = Random.Int(borderThickness);
                for (int y = grid.Bounds.yMin; y <= grid.Bounds.yMax; y++)
                {
                    for (int x = grid.Bounds.xMax - thickness; x <= grid.Bounds.xMax; x++)
                    {
                        grid.Add(new Vector3Int(x, y, 0), border, overwrite);
                    }
                    thickness = ChangeThickness(thickness, borderThickness);
                }
            }

            if (edges.HasFlag(MapEdge.West))
            {
                int thickness = Random.Int(borderThickness);
                for (int y = grid.Bounds.yMin; y <= grid.Bounds.yMax; y++)
                {
                    for (int x = grid.Bounds.xMin + thickness; x >= grid.Bounds.xMin; x--)
                    {
                        grid.Add(new Vector3Int(x, y, 0), border, overwrite);
                    }
                    thickness = ChangeThickness(thickness, borderThickness);
                }
            }
        }
Пример #10
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;
    }
Пример #11
0
    private bool Intersect(MapNode spawn, MapEdge spawnedEdge, List<MapNode> neighbours)
    {
        // We'll need a set of all intersections we found for the given edge - in the general case there might be
        // several intersections so we must find the one closest to the starting node (this.Node)
        HashSet<MapNode> intersectionNodes = null;

        // Iterate through all neighbours
        foreach (MapNode neighbour in neighbours) {
            foreach (MapEdge neighboursEdge in neighbour.edges) {
                if (spawnedEdge.FromNode != neighboursEdge.FromNode &&
                    spawnedEdge.FromNode != neighboursEdge.ToNode &&
                    spawnedEdge.ToNode != neighboursEdge.FromNode &&
                    spawnedEdge.ToNode != neighboursEdge.ToNode) {

                    // Try to find an intersection
                    MapNode intersection = spawnedEdge.Intersection(neighboursEdge);
                    if (intersection != null) {
                        // Found - add the edge which generated the intersection to its edge list. Technically this is
                        // invalid behavior (since the intersection lies somewhere *on* that edge), but it's only
                        // temporarily there until we reconnect the nodes and edges properly in the next part of the
                        // algorithm.
                        intersection.edges.Add(neighboursEdge);

                        // Add it to the set
                        if (intersectionNodes == null) intersectionNodes = new HashSet<MapNode>();
                        intersectionNodes.Add(intersection);
                    }
                }
            }
        }

        if (intersectionNodes != null) {
            // Go through all intersections and find the one closest to this.Node
            MapNode chosenIntersection = null;
            float minimumDistance = float.MaxValue;
            foreach (MapNode intersection in intersectionNodes) {
                float distance = Node.Distance(intersection);
                if (distance < minimumDistance) {
                    chosenIntersection = intersection;
                    minimumDistance = distance;
                }
            }

            // Move the spawn's position to be the same as chosen intersection's
            spawn.position = chosenIntersection.position;

            // Get the edge that generated this intersection
            MapEdge neighboursEdge = chosenIntersection.edges[0];

            // Fix the "invalid behavior" mentioned above
            chosenIntersection.edges.Clear();

            // Split the edge in two at the intersection
            MapNode neighboursFromNode = neighboursEdge.FromNode;
            MapNode neighboursToNode = neighboursEdge.ToNode;

            neighboursFromNode.edges.Remove(neighboursEdge);
            new MapEdge(neighboursFromNode, spawn);

            neighboursToNode.edges.Remove(neighboursEdge);
            new MapEdge(spawn, neighboursToNode);

            // Done
            intersectionNodes.Clear();
            return true;
        }

        return false;
    }
Пример #12
0
 public void AddEdge(MapEdge edge)
 {
     _edges.Add(edge);
 }
Пример #13
0
 public void DelEdge(MapEdge _mapEdge)
 {
     edges.Remove(_mapEdge);
 }
Пример #14
0
    /// <summary>
    /// Finds the intersection between two map edges. If there is an intersection, a new MapNode instance is created and
    /// returned at the intersection's coordinates. The original edges and their nodes are left unchanged. If there's no
    /// intersection, <c>null</c> is returned.
    /// </summary>
    /// <param name='other'>
    /// The edge to intersect with.
    /// </param>
    /// <returns>
    /// A newly spawned MapNode if there was an intersection, or <c>null</c> otherwise.
    /// </returns>
    public MapNode Intersection(MapEdge other)
    {
        // Implementation of the intersection algorithm found at:
        // http://britneyspeerpink.wordpress.com/2011/08/06/line-intersection/

        Vector2 p = this.FromNode.PositionAsVector2;
        Vector2 r = this.ToNode.PositionAsVector2 - p;
        Vector2 q = other.FromNode.PositionAsVector2;
        Vector2 s = other.ToNode.PositionAsVector2 - q;

        Func<Vector2, Vector2, float> CrossMag = (v1, v2) => {
            return v1.x * v2.y - v1.y * v2.x;
        };

        float w = CrossMag(r, s);

        if (Mathf.Approximately(w, 0f)) return null;
        else if (Mathf.Approximately(CrossMag(q - p, r), 0f)) return null;
        else {
            float t = CrossMag(q - p, s) / w;
            Vector2 intersectionP = p + (t * r);

            // Check if the intersection lies within both line segments' bounds
            Func<Vector2, Vector2, Vector2, bool> BoundsCheck = (intersection, p1, p2) => {
                return Mathf.Min(p1.x, p2.x) <= intersection.x &&
                    Mathf.Max(p1.x, p2.x) >=  intersection.x &&
                    Mathf.Min(p1.y, p2.y) <= intersection.y &&
                    Mathf.Max(p1.y, p2.y) >= intersection.y;
            };

            if (BoundsCheck(intersectionP, this.FromNode.PositionAsVector2, this.ToNode.PositionAsVector2) &&
                BoundsCheck(intersectionP, other.FromNode.PositionAsVector2, other.ToNode.PositionAsVector2)) {
                // Intersection found
                float y = (FromNode.position + t * (ToNode.position - FromNode.position)).y;
                return new MapNode(new Vector3(intersectionP.x, y, intersectionP.y));
            }
        }

        return null;
    }
Пример #15
0
    void Draw()
    {
        texture = new Texture2D(mapWidth, mapHeight);
        cells   = new List <MapCell>();
        Debug.Log(map_points.Count);
        for (int i = 0; i < map_points.Count; i++)
        {
            Vector2 site = map_points[i];
            MapCell cell = new MapCell
            {
                Position   = site,
                edges      = new List <MapEdge>(),
                neighbours = voronoi.NeighborSitesForSite(site),
                ID         = i,
            };
            //cell.isBorder = IsBorder(voronoi.VoronoiBoundaryForSite(site));
            cell.isBorder = HullContainsSite(site);



            foreach (LineSegment segment in voronoi.VoronoiBoundaryForSite(site))
            {
                cell.edges.Add(new MapEdge(segment.P0, segment.P1));
            }


            // Paint edges
            for (int j = 0; j < cell.edges.Count; j++)
            {
                MapEdge        edge   = cell.edges[j];
                List <Vector2> points = new List <Vector2>
                {
                    edge.p0,
                    edge.p1
                };
                Vector2 p0 = points[0];
                Vector2 p1 = points[1];

                int distance = (int)Mathf.Abs(Vector2.Distance(p0, p1));
                for (int k = 0; k <= distance; k++)
                {
                    Vector2 temp = p1 - p0;
                    temp.Normalize();
                    Vector2 pos = k * temp + p0;

                    int x;
                    int y;

                    if ((int)pos.x >= mapWidth)
                    {
                        x = ((int)pos.x) - 1;
                    }
                    else
                    {
                        x = (int)pos.x;
                    }

                    if ((int)pos.y >= mapHeight)
                    {
                        y = ((int)pos.y) - 1;
                    }
                    else
                    {
                        y = (int)pos.y;
                    }

                    texture.SetPixel(x, y, borderColour);
                }
            }

            //Fill Center
            //Temporary fill to have land and water

            int tempx = (int)site.x; int tempy = (int)site.y;
            if (cell.isBorder)
            {
                cell.biome = Biomes.GetBiome("Ocean");
                texture.FloodFillBorder(tempx, tempy, cell.biome.biomeColour, borderColour);
                continue;
            }


            float[,] noiseLayer = Noise.GenerateNoiseMap(mapWidth, mapHeight, seed, NOISE_SCALE, OCTAVES, PERSISTANCE, LACUNARITY, new Vector2(0, 0));

            if (noiseLayer[tempx, tempy] > waterThreshold)
            {
                cell.biome = Biomes.GetBiome("Grasslands");
                texture.FloodFillBorder(tempx, tempy, cell.biome.biomeColour, borderColour);
            }

            else
            {
                cell.biome = Biomes.GetBiome("Ocean");
                texture.FloodFillBorder(tempx, tempy, cell.biome.biomeColour, borderColour);
            }
        }
        texture.Apply();
        plane.GetComponent <MeshRenderer>().sharedMaterial.mainTexture = texture;
    }