Esempio n. 1
0
            void GenWalls()
            {
                for (int y = 0; y < G.Mapping.RowSz; y++)
                {
                    for (int x = 0; x < G.Mapping.ColSz; x++)
                    {
                        //connect to next col
                        if (RollWall())
                        {
                            if (x != G.Mapping.ColSz - 1)
                            {
                                G.AddEdge(x, y, x + 1, y, 1, true);
                            }
                        }

                        //connect to row below
                        if (RollWall())
                        {
                            if (y < G.Mapping.RowSz - 1)
                            {
                                G.AddEdge(x, y, x, y + 1, 1, true);
                            }
                        }
                    }
                }
            }
Esempio n. 2
0
    private void AddRoom()
    {
        GridGraph <MapRoom, MapPath> Rooms = Map.Graph;

        // choose random node with open edges
        MapNode openNode = _openNodes[Random.Range(0, _openNodes.Count)];

        // choose random open edge direction
        List <GridDirection> emptyNeighbors   = GetEmptyNeighbors(openNode.Neighbors);
        GridDirection        newRoomDirection = emptyNeighbors[Random.Range(0, emptyNeighbors.Count)];

        // add new room
        XY nextCoord = Rooms.GetCoordForNeighbor(openNode, newRoomDirection);

        // add new node and edges to graph
        MapNode newNode = Rooms.AddNode(nextCoord, new MapRoom());

        Rooms.AddEdge(openNode, newNode, new MapPath());
        Rooms.AddEdge(newNode, openNode, new MapPath());

        // update open nodes
        foreach (KeyValuePair <GridDirection, MapNode> entry in newNode.Neighbors)
        {
            MapNode neighbor = entry.Value;

            if (neighbor.Neighbors.Count == 4 && _openNodes.Contains(neighbor))
            {
                _openNodes.Remove(neighbor);
            }
        }

        if (Map.Graph.GetNeighbors(newNode).Count != 4)
        {
            _openNodes.Add(newNode);
        }
    }
Esempio n. 3
0
    public void InitializeMapGraph()
    {
        sidewalkGraph = new GridGraph_Node();
        drivewayGraph = new GridGraph <DrivewayNode>();
        blockTable    = new Dictionary <Grid, Block>();

        //sidewalkGraph 노드를 전부 생성한다.
        //block별로 입구 노드를 만들어준뒤, block과 연결해준다.
        //block을 생성한 후 blockTable에 넣는다.
        for (int x = -MAX_X_GRID; x <= MAX_X_GRID; x++)
        {
            for (int y = -MAX_Y_GRID; y <= MAX_Y_GRID; y++)
            {
                Grid blockGrid = new Grid(x, y);
                blockTable.Add(blockGrid, new Block(blockGrid, Area.Default));

                for (int i = 0; i < 4; i++)
                {
                    float offset_x = (float)(i % 2);
                    float offset_y = (float)((i >> 1) % 2);

                    Grid    grid = new Grid(x, y, offset_x, offset_y);
                    Vector2 pos  = GetSidewalkNodePos(x, y, offset_x, offset_y);
                    sidewalkGraph.AddVertex(new SidewalkNode(grid, pos), grid);
                }


                //set enterenceGrid
                float randomOffsetX = Random.Range(0f, 1f);
                float randomOffsetY = Random.Range(0f, 1f);

                bool horizontalOffset = Random.Range(0, 2) == 0 ? true : false; //horizontal or vertical
                if (horizontalOffset)
                {
                    randomOffsetY = Mathf.Round(randomOffsetY);
                }
                else
                {
                    randomOffsetX = Mathf.Round(randomOffsetX);
                }

                Grid enterenceGrid = new Grid(x, y, randomOffsetX, randomOffsetY);
                sidewalkGraph.AddVertex(new SidewalkNode(enterenceGrid, GetSidewalkNodePos(enterenceGrid)), enterenceGrid);
            }
        }

        //blockGraph의 ConnectedBlock을 설정한다.
        for (int i = 0; i < CONNECTED_BLOCK_NUM; i++)
        {
            int x = Random.Range(-MAX_X_GRID, MAX_Y_GRID + 1);
            int y = Random.Range(-MAX_Y_GRID, MAX_Y_GRID + 1);

            int setx  = Random.Range(0, 2);
            int sety  = 1 - setx;
            int value = Random.Range(0, 2) * 2 - 1;
            int offx  = value * setx;
            int offy  = value * sety;


            Block pair1, pair2;

            //pair1과 pair2에 Block을 연결해준다.
            //불가능한 Grid가 설정되었을 때에는 재시도한다.
            if (!(blockTable.TryGetValue(new Grid(x, y), out pair1) &&
                  (blockTable.TryGetValue(new Grid(x + offx, y + offy), out pair2))))
            {
                i--;
                continue;
            }

            //이미 연결되어 있을 때에는 재시도한다.
            foreach (Grid grid in pair1.LocalConnectedBlockPos)
            {
                if (grid == pair2.BlockGrid)
                {
                    i--;
                    continue;
                }
            }

            pair1.AddConnectedBlock(pair2.BlockGrid);
            pair2.AddConnectedBlock(pair1.BlockGrid);
        }

        //sidewalkGraph 노드를 연결한다.
        for (int x = -MAX_X_GRID; x <= MAX_X_GRID; x++)
        {
            for (int y = -MAX_Y_GRID; y <= MAX_Y_GRID; y++)
            {
                for (int i = 0; i < 4; i++)
                {
                    float offset_x = (float)(i % 2);
                    float offset_y = (float)((i >> 1) % 2);

                    Grid homeGrid = new Grid(x, y, offset_x, offset_y);
                    Grid grid1    = new Grid(x, y, 1.0f - offset_x, offset_y);
                    Grid grid2    = new Grid(x, y, offset_x, 1 - offset_y);

                    sidewalkGraph.AddEdge(homeGrid, grid1, walking_weight_coefficient);
                    sidewalkGraph.AddEdge(homeGrid, grid2, walking_weight_coefficient);
                }

                //연결된 블록끼리 연결해준다.
                //연결된 블록 사이에 있는 노드는 삭제한다.
                Block block = blockTable_TryGetValue(new Grid(x, y));

                foreach (Grid grid in block.LocalConnectedBlockPos)
                {
                    Grid  connectedBlockGrid = new Grid(x + grid.block_x, y + grid.block_y);
                    Block connectedBlock     = blockTable_TryGetValue(connectedBlockGrid);

                    Grid nodeGrid1;
                    Grid nodeGrid2;
                    Grid cnodeGrid1;
                    Grid cnodeGrid2;

                    //grid에 따라 nodeGrid1과 nodeGrid2를 결정해준다.
                    //상
                    if (grid == Grid.up)
                    {
                        nodeGrid1  = new Grid(0, 1);
                        nodeGrid2  = new Grid(1, 1);
                        cnodeGrid1 = new Grid(0, 0);
                        cnodeGrid2 = new Grid(1, 0);
                    }
                    //하
                    else if (grid == Grid.down)
                    {
                        nodeGrid1  = new Grid(0, 0);
                        nodeGrid2  = new Grid(0, 1);
                        cnodeGrid1 = new Grid(1, 0);
                        cnodeGrid2 = new Grid(1, 1);
                    }
                    //좌
                    else if (grid == Grid.left)
                    {
                        nodeGrid1  = new Grid(0, 0);
                        nodeGrid2  = new Grid(1, 0);
                        cnodeGrid1 = new Grid(0, 1);
                        cnodeGrid2 = new Grid(1, 1);
                    }
                    //우
                    else if (grid == Grid.right)
                    {
                        nodeGrid1  = new Grid(1, 0);
                        nodeGrid2  = new Grid(1, 1);
                        cnodeGrid1 = new Grid(0, 0);
                        cnodeGrid2 = new Grid(0, 1);
                    }
                    else
                    {
                        throw new System.Exception();
                    }

                    sidewalkGraph.RemoveEdge(nodeGrid1, nodeGrid2);
                    sidewalkGraph.RemoveEdge(nodeGrid2, nodeGrid1);

                    sidewalkGraph.AddEdge(nodeGrid1, cnodeGrid1, walking_weight_coefficient);
                    sidewalkGraph.AddEdge(nodeGrid2, cnodeGrid2, walking_weight_coefficient);
                }
            }
        }

        //dirvewayGraph 노드를 전부 생성한다.
        for (int x = -MAX_X_GRID + 1; x <= MAX_X_GRID; x++)
        {
            for (int y = -MAX_Y_GRID + 1; y <= MAX_Y_GRID; y++)
            {
                Grid    grid = new Grid(x, y);
                Vector2 pos  = new Vector2((BLOCK_HEIGHT + SIDEWALK_WIDTH * 2 + DRIVEWAY_WIDTH) * x - DRIVEWAY_WIDTH * 0.5f,
                                           (BLOCK_WIDTH + SIDEWALK_WIDTH * 2 + DRIVEWAY_WIDTH) * y - DRIVEWAY_WIDTH * 0.5f);
                drivewayGraph.AddVertex(new DrivewayNode(DrivewayNodeType.Default, grid, pos), grid);
            }
        }

        //drivewayGraph 노드를 전부 연결한다.
        for (int x = -MAX_X_GRID + 1; x <= MAX_X_GRID; x++)
        {
            for (int y = -MAX_Y_GRID + 1; y <= MAX_Y_GRID; y++)
            {
                Grid grid = new Grid(x, y);
                foreach (Grid udlr in Grid.UDLR)
                {
                    //first나 end가 존재하지 않는다면 연결하지 않는다.
                    drivewayGraph.AddEdge(grid, grid + udlr, bus_weight_coefficient, true);
                }
            }
        }

        //연결된 Block 사이에 연결된 drivewaynode를 끊어준다.
        for (int x = -MAX_X_GRID + 1; x <= MAX_X_GRID; x++)
        {
            for (int y = -MAX_Y_GRID + 1; y <= MAX_Y_GRID; y++)
            {
                Grid        blockGrid         = new Grid(x, y);
                Block       block             = blockTable_TryGetValue(blockGrid);
                List <Grid> connectedBlockPos = block.LocalConnectedBlockPos;

                foreach (Grid grid in connectedBlockPos)
                {
                    if (grid == Grid.left)
                    {
                        drivewayGraph.RemoveEdge(blockGrid, blockGrid + Grid.up, true);
                        drivewayGraph.RemoveEdge(blockGrid + Grid.up, blockGrid, true);
                    }
                    if (grid == Grid.down)
                    {
                        drivewayGraph.RemoveEdge(blockGrid, blockGrid + Grid.right, true);
                        drivewayGraph.RemoveEdge(blockGrid + Grid.right, blockGrid, true);
                    }
                }
            }
        }
        drivewayGraph.DestoryIsolatedVertex();

        //TrafficLight 위치를 설정한다.
        {
            bool[,] isConnected = new bool[2 * MAX_X_GRID + 1, 2 * MAX_Y_GRID + 1];


            int  x    = Random.Range(-MAX_X_GRID, MAX_X_GRID + 1);
            int  y    = Random.Range(-MAX_Y_GRID, MAX_Y_GRID + 1);
            Grid udlr = Grid.GetRandomUDLR();

            Stack <Grid> gridStack = new Stack <Grid>();
            isConnected[x + MAX_X_GRID, y + MAX_Y_GRID] = true;
            gridStack.Push(new Grid(x, y));
            foreach (Grid connectedBlockPos in blockTable_TryGetValue(new Grid(x, y)).LocalConnectedBlockPos)
            {
                isConnected[x + connectedBlockPos.block_x + MAX_X_GRID, y + connectedBlockPos.block_y + MAX_Y_GRID] = true;
            }


            //DFS
            while (gridStack.Count != 0)
            {
                Grid nowGrid = gridStack.Pop();

                //blockGrid가 Connected일 경우
                if (isConnected[nowGrid.block_x + MAX_X_GRID, nowGrid.block_y + MAX_Y_GRID])
                {
                    for (int i = 0; i < 4; i++)
                    {
                        //90도 회전변환 한다.
                        udlr = new Grid(-udlr.block_y, udlr.block_x);
                        Grid grid = nowGrid + udlr;

                        if (Mathf.Abs(grid.block_x) > MAX_X_GRID || Mathf.Abs(grid.block_y) < MAX_Y_GRID)
                        {
                            continue;
                        }


                        //주변에 unconnected가 있을 경우 연결하고, 연결한 블록에 대해 재귀한다.
                        if (isConnected[grid.block_x + MAX_X_GRID, grid.block_y + MAX_Y_GRID] == false)
                        {
                            blockTable_TryGetValue(nowGrid).AddTrafficLight(grid);
                            blockTable_TryGetValue(grid).AddTrafficLight(nowGrid);
                            isConnected[grid.block_x + MAX_X_GRID, grid.block_y + MAX_Y_GRID] = true;
                            gridStack.Push(grid);
                            foreach (Grid connectedBlockPos in blockTable_TryGetValue(grid).LocalConnectedBlockPos)
                            {
                                isConnected[x + connectedBlockPos.block_x + MAX_X_GRID, y + connectedBlockPos.block_y + MAX_Y_GRID] = true;
                            }
                        }
                    }
                }
            }
        }

        //TrafficLight를 생성한다.
        for (int x = -MAX_X_GRID; x <= MAX_X_GRID; x++)
        {
            for (int y = -MAX_Y_GRID; y <= MAX_Y_GRID; y++)
            {
                Grid blockGrid = new Grid(x, y);
                foreach (Grid trafficPos in blockTable_TryGetValue(blockGrid).LocalTrafficLightPos)
                {
                    if (trafficPos == Grid.up)
                    {
                        float   ratio     = Random.Range((1 - RANGE_TRAFFICLIGHT_MAY_EXIST) * 0.5f, (1 + RANGE_TRAFFICLIGHT_MAY_EXIST) * 0.5f);
                        Vector2 sNodePos1 = GetSidewalkNodePos(x, y, ratio, 1);
                        Vector2 sNodePos2 = GetSidewalkNodePos(x, y + 1, ratio, 0);
                        Vector2 dNodePos  = (sNodePos1 + sNodePos2) * 0.5f;


                        TrafficLightTimer trafficLightTimer = new TrafficLightTimer();
                        SidewalkNode      sidewalkNode1     = new SidewalkNode(SidewalkNodeType.TrafficLight,
                                                                               new Grid(x, y, ratio, 1),
                                                                               sNodePos1);
                        SidewalkNode sidewalkNode2 = new SidewalkNode(SidewalkNodeType.TrafficLight,
                                                                      new Grid(x, y + 1, ratio, 0),
                                                                      sNodePos2);
                        DrivewayNode drivewayNode = new DrivewayNode(DrivewayNodeType.TrafficLight,
                                                                     new Grid(x, y + 1, ratio, 0),
                                                                     dNodePos);
                    }
                }
            }
        }
    }