Esempio n. 1
0
    private void _connectTraversableTiles(Godot.Collections.Array tiles)
    {
        foreach (Vector2 tile in tiles)
        {
            // Add all neighbors
            for (int indexX = -1; indexX < 2; indexX++)
            {
                for (int indexY = -1; indexY < 2; indexY++)
                {
                    Vector2 targetTile = new Vector2(tile.x + indexX, tile.y + indexY);
                    int     toId       = getPointID((int)targetTile.x, (int)targetTile.y);
                    int     fromId     = getPointID((int)tile.x, (int)tile.y);

                    if (tile == targetTile || !_aStar.HasPoint(toId))
                    {
                        // No need to add tile as it is the same
                        continue;
                    }

                    // Caculate if diagonal point can be used
                    // (this is to avoid to given a diagonal path to agent, but agent cannot pass as vertical/horizontal has obstacles)

                    // Upper left/right diagonal (-1,1), (1,1)
                    // which need (-1,0) (horizontal), (0,1) (veritcal), (1,0) (horizontal)

                    // Bottom left/right diagonal (-1,-1), (1,-1)
                    // which need (-1,0) (horizontal), (0,-1) (veritcal), (1,0) (horizontal)

                    // this is to avoid stuck on corner
                    if (indexX != 0 && indexY != 0)
                    {
                        int horizaontalId = getPointID((int)tile.x + indexX, (int)tile.y);
                        int verticalId    = getPointID((int)tile.x, (int)tile.y + indexY);

                        // Upper diaonal connection depend on if there is obstacle for vertical/horizontal neighbors
                        // If there are obstacles (i.e. point not exist, then not connect it)
                        if (!_aStar.HasPoint(horizaontalId) || !_aStar.HasPoint(verticalId))
                        {
                            continue;
                        }
                    }

                    if (!_aStar.ArePointsConnected(fromId, toId))
                    {
                        // Debug code
                        if (debug)
                        {
                            Line2D    line2d = new Line2D();
                            Vector2[] points = { (Vector2)_tilestoWorld[fromId], (Vector2)_tilestoWorld[toId] };
                            line2d.Points = points;
                            _tileMap.AddChild(line2d);
                        }
                        _aStar.ConnectPoints(fromId, toId, true);
                    }
                }
            }
        }
    }
Esempio n. 2
0
    // Called every time stabilizes (mode changes to RigidBody2D.MODE_STATIC).
    //
    // Once all rooms have stabilized it calculates a playable dungeon `_path` using the MST
    // algorithm. Based on the calculated `_path`, it populates `_data` with room and corridor tile
    // positions.
    //
    // It emits the "rooms_placed" signal when it finishes so we can begin the tileset placement.
    private void _on_Room_sleeping_state_changed()
    {
        GD.Print("_on_Room_sleeping_state_changed");

        _sleepingRooms++;
        if (_sleepingRooms < MaxRooms)
        {
            return;
        }

        var mainRooms          = new List <Room>();
        var mainRoomsPositions = new List <Vector2>();

        foreach (Room room in Rooms.GetChildren())
        {
            if (IsMainRoom(room))
            {
                mainRooms.Add(room);
                mainRoomsPositions.Add(room.Position);
            }
        }

        _path = Utils.MST(mainRoomsPositions);

        foreach (int point1Id in _path.GetPoints())
        {
            foreach (int point2Id in _path.GetPoints())
            {
                if (point1Id != point2Id &&
                    !_path.ArePointsConnected(point1Id, point2Id) &&
                    _rng.Randf() < ReconnectionFactor)
                {
                    _path.ConnectPoints(point1Id, point2Id);
                }
            }
        }

        foreach (Room room in mainRooms)
        {
            AddRoom(room);
        }
        AddCorridors();

        SetProcess(false);
        EmitSignal(nameof(RoomsPlaced));
    }