コード例 #1
0
    // Create area segments borders
    private void CreateAreaBlockerLines()
    {
        foreach (var edge in VoronoiDiagram.Edges)
        {
            if (!edge.Visible())
            {
                continue;
            }

            int         leftAreaSegmentID  = _siteAreaSegmentMap[edge.LeftSite.Coord];
            int         rightAreaSegmentID = _siteAreaSegmentMap[edge.RightSite.Coord];
            AreaSegment leftAreaSegment    = AreaSegmentGraph.GetNodeData(leftAreaSegmentID);
            AreaSegment rightAreaSegment   = AreaSegmentGraph.GetNodeData(rightAreaSegmentID);

            var leftNeighborhood = AreaSegmentGraph.GetNeighbours(leftAreaSegmentID);

            if (leftAreaSegmentID == rightAreaSegmentID ||
                leftAreaSegment.Type == AreaSegment.EAreaSegmentType.Border ||
                rightAreaSegment.Type == AreaSegment.EAreaSegmentType.Border ||
                !leftNeighborhood.Contains(rightAreaSegmentID) ||
                AreaSegmentGraph.GetEdgeValue(leftAreaSegmentID, rightAreaSegmentID) != (int)AreaSegment.EAreaSegmentEdgeType.NonNavigable)
            {
                continue;
            }

            var p0      = edge.ClippedEnds[LR.LEFT].ToUnityVector2();
            var p1      = edge.ClippedEnds[LR.RIGHT].ToUnityVector2();
            var segment = new[] { p0, p1 };
            AreaBlockerLines.Add(segment);
        }
    }
コード例 #2
0
    public void SpawnAreaObject()
    {
        GameObject areaObj = currentAreaObj;

        NetworkServer.Spawn(areaObj);
        for (int i = 0; i < currentArea.corridors.Count; i++)
        {
            AreaCorridor corridor = currentArea.corridors[i];
            for (int j = 0; j < corridor.segments.Count; j++)
            {
                AreaSegment seg             = corridor.segments[j];
                Vector3     segmentLocation = new Vector3(seg.x * segmentWidth, -1 * seg.y * segmentHeight, 0);
                NetworkServer.Spawn(seg.netId.gameObject);
                RpcSetupAreaSegment(areaObj.GetComponent <NetworkIdentity>(), seg.netId, corridor.index, seg.index, segmentLocation);
                for (int k = 0; k < 4; k++)
                {
                    if (seg.walls[k] != null)
                    {
                        AreaSegmentInstallation installation = seg.installations[k];
                        if (installation != null)
                        {
                            NetworkServer.Spawn(installation.netId.gameObject);
                            RpcSetupAreaInstallation(seg.netId, installation.netId, corridor.index, seg.index, k);
                        }
                    }
                }
            }
        }
    }
コード例 #3
0
    // Sample area texture at given position
    public KeyValuePair <int, float> SampleTexture(Vector2 position)
    {
        Vector2     noisePosition = position + new Vector2(Random.Range(-_alphaNoise, _alphaNoise), Random.Range(-_alphaNoise, _alphaNoise));
        AreaSegment areaSegment   = GetClosestAreaSegment(noisePosition);
        int         splatID       = _splatIDMap[areaSegment.Type == AreaSegment.EAreaSegmentType.Border ? BorderSettings.Splat : BiomeSettings.Splat];
        float       splatValue    = 1;

        return(new KeyValuePair <int, float>(splatID, splatValue));
    }
コード例 #4
0
        public int AddNode(AreaSegment segment, AreaSegment correspondence)
        {
            int pat = Pattern.AddNode(segment);
            int rep = Replace.AddNode(correspondence);

            Correspondences.Add(pat, rep);

            return(pat);
        }
コード例 #5
0
    [ClientRpc] private void RpcSpawnInstallation(int corridorId, int segmentId, int dir, string type, string name, NetworkIdentity id)
    {
        AreaCorridor corridor = currentArea.corridors[corridorId];
        AreaSegment  segment  = corridor.segments[segmentId];

        segment.installations[dir]       = new AreaSegmentInstallation(dir, segment);
        segment.installations[dir].type  = type;
        segment.installations[dir].name  = name;
        segment.installations[dir].netId = id;
    }
コード例 #6
0
    // Sample area height at a given position
    public BiomeHeightParameters SampleHeight(Vector2 position)
    {
        AreaSegment areaSegment = GetClosestAreaSegment(position);

        if (areaSegment.Type == AreaSegment.EAreaSegmentType.Border)
        {
            position   += new Vector2(Random.Range(-_heightNoise, _heightNoise), Random.Range(-_heightNoise, _heightNoise));
            areaSegment = GetClosestAreaSegment(position);
        }
        return(areaSegment == null || areaSegment.Type == AreaSegment.EAreaSegmentType.Border ? BorderSettings.HeightParameters : BiomeSettings.HeightParameters);
    }
コード例 #7
0
    public AreaSegment getNeighbor(int directionId)
    {
        AreaSegment neighbor       = null;
        Coordinates neighborCoords = new Coordinates(corridor.x + index, corridor.y);

        neighborCoords = coordinates.getAdjacent(directionId);
        foreach (AreaCorridor cor in area.corridors)
        {
            if (cor.y == neighborCoords.y)
            {
                foreach (AreaSegment seg in cor.segments)
                {
                    if (seg.x == neighborCoords.x)
                    {
                        neighbor = seg;
                    }
                }
            }
        }
        return(neighbor);
    }
コード例 #8
0
    [ClientRpc] private void RpcSetupAreaSegment(NetworkIdentity areaNetId, NetworkIdentity segNetId, int corridorId, int segmentId, Vector3 segmentLocation)
    {
        GameObject  areaObj     = areaNetId.gameObject;
        GameObject  areaSegment = segNetId.gameObject;
        AreaSegment seg         = currentArea.corridors[corridorId].segments[segmentId];

        areaSegment.transform.SetParent(areaObj.transform);
        areaSegment.transform.localPosition = segmentLocation;
        for (int i = 0; i < 4; i++)
        {
            GameObject wallObj = areaSegment.transform.Find("Wall" + i.ToString()).gameObject;
            if (seg.walls[i] == null)
            {
                GameObject.Destroy(wallObj);
            }
            else
            {
                currentArea.tileset.setWallSprite(wallObj, seg.walls[i]);
            }
        }
    }
コード例 #9
0
    public AreaCorridor spawnCorridor(int x, int y, int len)
    {
        AreaCorridor cor = new AreaCorridor();

        cor.coordinates = new Coordinates(x, y);
        cor.area        = this;
        for (int i = 0; i < len; i++)
        {
            AreaSegment segment = new AreaSegment(cor);
            if (i != 0)
            {
                segment.walls[2] = null;
            }
            if (i != len - 1)
            {
                segment.walls[0] = null;
            }
            cor.segments.Add(segment);
        }
        cor.index = corridors.Count;
        corridors.Add(cor);
        return(cor);
    }
コード例 #10
0
 public AreaSegmentInstallation(int dir, AreaSegment seg)
 {
     directionId = dir;
     segment     = seg;
 }
コード例 #11
0
 public AreaSegmentWall(int dir, AreaSegment seg)
 {
     directionId = dir;
     segment     = seg;
 }
コード例 #12
0
    public static GameObject DrawAreaSegments(TerrainStructure terrainStructure, string name = "AreaSegments")
    {
        GameObject result = new GameObject(name);
        var        graph  = terrainStructure.AreaSegmentGraph;

        // Draw all lines
        GameObject edges = new GameObject("Edges");

        edges.transform.parent = result.transform;
        foreach (var edge in graph.GetAllEdges())
        {
            Vector2 start = terrainStructure.GetAreaSegmentCenter(edge.x);
            Vector2 end   = terrainStructure.GetAreaSegmentCenter(edge.y);
            Color   color;

            switch ((AreaSegment.EAreaSegmentEdgeType)graph.GetEdgeValue(edge.x, edge.y))
            {
            case AreaSegment.EAreaSegmentEdgeType.NonNavigable:
                color = Color.black;
                break;

            case AreaSegment.EAreaSegmentEdgeType.MainPath:
                color = Color.green;
                break;

            case AreaSegment.EAreaSegmentEdgeType.SidePath:
                color = Color.cyan;
                break;

            case AreaSegment.EAreaSegmentEdgeType.BossInnerPath:
                color = Color.red;
                break;

            case AreaSegment.EAreaSegmentEdgeType.SpecialInnerPath:
                color = Color.yellow;
                break;

            default:
                color = Color.gray;
                break;
            }

            GameObject line = DrawLine(new Vector3(start.x, 0, start.y), new Vector3(end.x, 0, end.y), 5, color);
            line.transform.parent = edges.transform;
        }

        // Draw all centers
        GameObject nodes = new GameObject("Nodes");

        nodes.transform.parent = result.transform;
        foreach (var id in graph.GetAllNodeIDs())
        {
            AreaSegment data   = graph.GetNodeData(id);
            Vector2     center = terrainStructure.GetAreaSegmentCenter(id);
            Color       color;
            switch (data.Type)
            {
            case AreaSegment.EAreaSegmentType.Empty:
                color = Color.white;
                break;

            case AreaSegment.EAreaSegmentType.Border:
                color = Color.black;
                break;

            case AreaSegment.EAreaSegmentType.Start:
                color = Color.blue;
                break;

            case AreaSegment.EAreaSegmentType.Boss:
                color = Color.red;
                break;

            case AreaSegment.EAreaSegmentType.Special:
                color = Color.yellow;
                break;

            case AreaSegment.EAreaSegmentType.MainPath:
                color = Color.green;
                break;

            case AreaSegment.EAreaSegmentType.SidePath:
                color = Color.cyan;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            GameObject node = DrawSphere(new Vector3(center.x, 0, center.y), 20, color);
            node.name             = "Node " + id + " - " + data.Type;
            node.transform.parent = nodes.transform;
        }

        return(result);
    }
コード例 #13
0
    public GameObject GenerateAreaObject()
    {
        Area       area    = currentArea;
        GameObject areaObj = GameObject.Instantiate <GameObject>(areaObject);

        if (area.isStarship)
        {
            areaObj.transform.Find("Sky").gameObject.GetComponent <SpriteRenderer>().sprite = spaceSkySprites[area.starship.currentSector.skySpriteIndex];
        }
        for (int i = 0; i < area.corridors.Count; i++)
        {
            AreaCorridor corridor = area.corridors[i];
            for (int j = 0; j < corridor.segments.Count; j++)
            {
                AreaSegment seg             = corridor.segments[j];
                Vector3     segmentLocation = new Vector3(seg.x * segmentWidth, -1 * seg.y * segmentHeight, 0);
                GameObject  areaSegment     = GameObject.Instantiate <GameObject>(segmentObject);
                seg.netId = areaSegment.GetComponent <NetworkIdentity>();
                areaSegment.transform.SetParent(areaObj.transform);
                areaSegment.transform.localPosition = segmentLocation;
                for (int k = 0; k < 4; k++)
                {
                    GameObject installationObj;
                    GameObject wallObj = areaSegment.transform.Find("Wall" + k.ToString()).gameObject;
                    if (seg.walls[k] == null)
                    {
                        GameObject.Destroy(wallObj);
                    }
                    else
                    {
                        area.tileset.setWallSprite(wallObj, seg.walls[k]);
                        AreaSegmentInstallation installation = seg.installations[k];
                        if (installation != null)
                        {
                            installationObj    = GameObject.Instantiate(installationPrefabs[k]);
                            installation.netId = installationObj.GetComponent <NetworkIdentity>();
                            installationObj.transform.SetParent(wallObj.transform);
                            installationObj.transform.localPosition = new Vector3(0, 0, -1);
                            switch (installation.type)
                            {
                            case "door":
                                installationObj.AddComponent <DoorInstallation>();
                                installationObj.GetComponent <DoorInstallation>().attachedWall     = wallObj;
                                installationObj.GetComponent <DoorInstallation>().installationName = installation.name;
                                installationObj.GetComponent <SpriteRenderer>().sprite             = area.tileset.doorSprites[k];
                                installationObj.GetComponent <DoorInstallation>().directionId      = k;
                                break;

                            case "interactive":
                                installationObj.AddComponent <InteractiveInstallation>();
                                installationObj.GetComponent <InteractiveInstallation>().attachedWall         = wallObj;
                                installationObj.GetComponent <InteractiveInstallation>().installationName     = installation.name;
                                installationObj.GetComponent <InteractiveInstallation>().interfaceOverlayName = installation.overlayName;
                                installationObj.GetComponent <SpriteRenderer>().sprite = area.tileset.getInstallationSprite(installation.name, k);
                                break;
                            }
                        }
                    }
                }
            }
        }
        return(areaObj);
    }
コード例 #14
0
    // Create border blocker polygon
    private void CreateBorderBlockerLines(float borderInlandOffset)
    {
        var segments = new List <KeyValuePair <Edge, Vector2> >();

        foreach (var edge in VoronoiDiagram.Edges)
        {
            //Check if this edge is visible before continuing
            if (!edge.Visible())
            {
                continue;
            }

            int         leftAreaSegmentID  = _siteAreaSegmentMap[edge.RightSite.Coord];
            int         rightAreaSegmentID = _siteAreaSegmentMap[edge.LeftSite.Coord];
            AreaSegment leftAreaSegment    = AreaSegmentGraph.GetNodeData(leftAreaSegmentID);
            AreaSegment rightAreaSegment   = AreaSegmentGraph.GetNodeData(rightAreaSegmentID);

            // Either one or the other must be a border type
            if (leftAreaSegment.Type != rightAreaSegment.Type &&
                (leftAreaSegment.Type == AreaSegment.EAreaSegmentType.Border || rightAreaSegment.Type == AreaSegment.EAreaSegmentType.Border))
            {
                // Add border edge with the biome center to scale inwards later
                segments.Add(new KeyValuePair <Edge, Vector2>(edge,
                                                              leftAreaSegment.Type == AreaSegment.EAreaSegmentType.Border ? edge.LeftSite.Coord.ToUnityVector2() : edge.RightSite.Coord.ToUnityVector2()));
            }
        }

        // Group connected segments
        var edgeGroups = new List <List <KeyValuePair <Edge, Vector2> > >();

        while (segments.Count > 0)
        {
            var edges     = new List <KeyValuePair <Edge, Vector2> >();
            var startEdge = segments[0];
            segments.Remove(startEdge);
            Vertex headPoint = startEdge.Key.RightVertex;
            Vertex tailPoint = startEdge.Key.LeftVertex;
            edges.Add(startEdge);

            // Find a polygon
            var polygonClosed = false;
            while (!polygonClosed && segments.Count > 0)
            {
                for (int i = 0; i < segments.Count; i++)
                {
                    var    currentElement = segments[i];
                    Vertex leftPoint      = currentElement.Key.LeftVertex;
                    Vertex rightPoint     = currentElement.Key.RightVertex;
                    if (leftPoint == headPoint)
                    {
                        edges.Add(currentElement);
                        segments.Remove(currentElement);
                        headPoint = rightPoint;
                    }
                    else if (rightPoint == headPoint)
                    {
                        edges.Add(currentElement);
                        segments.Remove(currentElement);
                        headPoint = leftPoint;
                    }

                    // Polygon has been closed
                    if (headPoint == tailPoint)
                    {
                        polygonClosed = true;
                        break;
                    }
                }
            }
            edgeGroups.Add(edges);
        }

        // Iterate over each polygon found previously
        foreach (var edges in edgeGroups)
        {
            var polygon     = new List <Vector2>();
            var borderLines = edges.Select(pair => pair.Key).ToList().EdgesToSortedLines();
            foreach (var line in borderLines)
            {
                // Offset borders towards biome center
                var left   = line[0];
                var right  = line[1];
                var center = Vector2.zero;
                edges.ForEach(e =>
                {
                    var l = e.Key.ClippedEnds[LR.LEFT].ToUnityVector2();
                    var r = e.Key.ClippedEnds[LR.RIGHT].ToUnityVector2();
                    if ((l == left || l == right) && (r == left || r == right))
                    {
                        center = e.Value;
                    }
                });

                left  += (center - left).normalized * borderInlandOffset;
                right += (center - right).normalized * borderInlandOffset;

                // Offsetting can give duplicated points
                if (!polygon.Contains(left))
                {
                    polygon.Add(left);
                }
                if (!polygon.Contains(right))
                {
                    polygon.Add(right);
                }
            }

            // Create border blocker lines
            BorderBlockerLines.AddRange(polygon.ToArray().PolygonToLines());
        }
    }
コード例 #15
0
    // Create a graph containing all connected empty areas
    private void CreateBaseGraph(int lloydIterations)
    {
        // Create uniform random point distribution and Voronoi Diagram
        var centers = new List <Vector2f>();

        for (int i = 0; i < _voronoiSamples; i++)
        {
            var x = Random.Range(0f, MapSize);
            var y = Random.Range(0f, MapSize);
            centers.Add(new Vector2f(x, y));
        }
        VoronoiDiagram = new Voronoi(centers, new Rectf(0, 0, MapSize, MapSize));

        // Apply Lloyd Relaxation
        VoronoiDiagram.LloydRelaxation(lloydIterations);

        // Assign area segments to initial areas
        foreach (var site in VoronoiDiagram.SiteCoords())
        {
            bool isOnBorder = false;
            var  segments   = VoronoiDiagram.VoronoiBoundaryForSite(site);

            foreach (var segment in segments)
            {
                if (!(segment.p0.x <= VoronoiDiagram.PlotBounds.left) &&
                    !(segment.p0.x >= VoronoiDiagram.PlotBounds.right) &&
                    !(segment.p0.y <= VoronoiDiagram.PlotBounds.top) &&
                    !(segment.p0.y >= VoronoiDiagram.PlotBounds.bottom) &&
                    !(segment.p1.x <= VoronoiDiagram.PlotBounds.left) &&
                    !(segment.p1.x >= VoronoiDiagram.PlotBounds.right) &&
                    !(segment.p1.y <= VoronoiDiagram.PlotBounds.top) &&
                    !(segment.p1.y >= VoronoiDiagram.PlotBounds.bottom))
                {
                    continue;
                }

                isOnBorder = true;
                break;
            }

            // Assign areaSegment to site and corresponding area
            var areaSegment = new AreaSegment(isOnBorder ? AreaSegment.EAreaSegmentType.Border : AreaSegment.EAreaSegmentType.Empty);

            var nodeID = AreaSegmentGraph.AddNode(areaSegment);
            _siteAreaSegmentMap.Add(site, nodeID);
            _areaSegmentCenterMap.Add(nodeID, site.ToUnityVector2());
        }

        // Create navigation graph - for each area segment that is not a border, add reachable neighbors
        foreach (var id in _siteAreaSegmentMap)
        {
            var areaSegment = AreaSegmentGraph.GetNodeData(id.Value);
            if (areaSegment.Type == AreaSegment.EAreaSegmentType.Border)
            {
                continue;
            }

            Vector2 center = _areaSegmentCenterMap[id.Value];
            foreach (var neighbor in VoronoiDiagram.NeighborSitesForSite(new Vector2f(center.x, center.y)))
            {
                var neighborSegment = AreaSegmentGraph.GetNodeData(_siteAreaSegmentMap[neighbor]);
                if (neighborSegment.Type != AreaSegment.EAreaSegmentType.Border)
                {
                    AreaSegmentGraph.AddEdge(_siteAreaSegmentMap[neighbor], id.Value, (int)AreaSegment.EAreaSegmentEdgeType.NonNavigable);
                }
            }
        }
    }