Exemple #1
0
        /// <summary>
        /// Convert the tilemap into a better data structure
        /// </summary>
        private void analyzeRooms()
        {
            var rooms = new List <Map.Room>();

            // pass 1 - find all rooms
            for (int r = 0; r < structure.Height; r++)
            {
                for (int c = 0; c < structure.Width; c++)
                {
                    var tile = structure.GetTile(c, r);
                    if (tile == null)
                    {
                        continue;
                    }

                    Map.TileOri ori(TmxLayerTile t)
                    {
                        return(analyzeWallTile((Map.TileKind)(t.Gid - worldTileset.FirstGid), tileDirection(t)));
                    }

                    var tileOri = ori(tile);
                    if (tileOri == Map.TileOri.UpLeft)
                    {
                        var topEdge   = r;
                        var leftEdge  = c;
                        var scanFirst = default(Point);
                        var scanOpen  = 0;
                        var openings  = new List <Map.Door>();

                        // line-scan setup
                        void updateScan(TmxLayerTile t, Point p, Direction dir)
                        {
                            if (t != null)
                            {
                                if (scanOpen > 0)
                                {
                                    openings.Add(new Map.Door(scanFirst, p, dir));
                                    scanFirst = default;
                                    scanOpen  = 0;
                                }
                            }
                            else
                            {
                                if (scanOpen == 0)
                                {
                                    // start the count
                                    scanFirst = p;
                                }

                                scanOpen++;
                            }
                        }

                        // scan for an UpRight
                        var ulTile    = tile;
                        var urTile    = default(TmxLayerTile);
                        var rightEdge = -1;
                        for (int sx = leftEdge; sx < structure.Width; sx++)
                        {
                            // pass left-to-right along top
                            var scTile = structure.GetTile(sx, topEdge);
                            updateScan(scTile, new Point(sx, topEdge), Direction.Up);
                            if (scTile == null)
                            {
                                continue;
                            }
                            if (ori(scTile) == Map.TileOri.UpRight)
                            {
                                urTile    = scTile;
                                rightEdge = sx;
                                break;
                            }
                        }

                        if (urTile == null)
                        {
                            break;
                        }
                        var drTile   = default(TmxLayerTile);
                        var downEdge = -1;
                        for (int sy = topEdge; sy < structure.Height; sy++)
                        {
                            // pass top-to-bottom along right
                            var scTile = structure.GetTile(rightEdge, sy);
                            updateScan(scTile, new Point(rightEdge, sy), Direction.Right);
                            if (scTile == null)
                            {
                                continue;
                            }
                            if (ori(scTile) == Map.TileOri.DownRight)
                            {
                                drTile   = scTile;
                                downEdge = sy;
                                break;
                            }
                        }

                        if (drTile == null)
                        {
                            break;
                        }
                        var dlTile = default(TmxLayerTile);
                        for (int sx = rightEdge; sx >= 0; sx--)
                        {
                            // pass right-to left along down
                            var scTile = structure.GetTile(sx, downEdge);
                            updateScan(scTile, new Point(sx, downEdge), Direction.Down);
                            if (scTile == null)
                            {
                                continue;
                            }
                            if (ori(scTile) == Map.TileOri.DownLeft)
                            {
                                dlTile = scTile;
                                break;
                            }
                        }

                        if (dlTile == null)
                        {
                            break;
                        }

                        // finally, check the left side
                        for (int sy = downEdge; sy >= 0; sy--)
                        {
                            // pass down-to-top along left
                            var scTile = structure.GetTile(leftEdge, sy);
                            updateScan(scTile, new Point(leftEdge, sy), Direction.Left);
                            if (scTile == null)
                            {
                                continue;
                            }
                            if (ori(scTile) == Map.TileOri.UpLeft)
                            {
                                // we found her again
                                break;
                            }
                        }

                        // all 4 corners have been found, create a room
                        var room = new Map.Room(new Point(leftEdge, topEdge), new Point(rightEdge, downEdge));
                        room.doors = openings;
                        foreach (var door in openings)
                        {
                            // set local room of all doors
                            door.roomLocal = room;
                        }

                        rooms.Add(room);
                        Global.log.trace($"room ul:{room.ul}, dr{room.dr}, doors:{room.doors.Count})");
                    }
                }
            }

            // pass 2 - determine room links
            foreach (var room in rooms)
            {
                foreach (var door in room.doors)
                {
                    // average the door pos
                    var inPos = door.doorCenter;
                    var(dx, dy) = DirectionStepper.stepIn(door.dir);

                    // now scan in direction
                    var distScanned = 0;
                    // set initial pos
                    var ix = inPos.X;
                    var iy = inPos.Y;
                    // set scan pos
                    var sx = ix;
                    var sy = iy;
                    while (distScanned < ROOM_LINK_DIST)
                    {
                        // update scan vars
                        distScanned = Math.Abs(ix - sx) + Math.Abs(iy - sy);
                        sx         += dx;
                        sy         += dy;

                        // check if we're inside another room
                        var sPt = new Point(sx, sy);
                        // TODO: optimize this checking
                        // check if we're in any other room
                        var otherRoom = default(Map.Room);
                        foreach (var testRoom in rooms)
                        {
                            if (testRoom.inRoom(sPt))
                            {
                                otherRoom = testRoom;
                                break;
                            }
                        }

                        if (otherRoom != null)
                        {
                            // set up the connection
                            door.roomOther = otherRoom;
                            room.links.Add(otherRoom);
                            Global.log.trace(
                                $"room link [dist: {distScanned}] from Room[@{room.center}] to Room[@{otherRoom.center}]");
                            break;
                        }
                    }
                }
            }

            // set up room graph
            mapRepr.roomGraph = new RoomGraph(rooms);
        }
 public RoomLink(Map.Room r1, Map.Room r2)
 {
     this.r1 = r1;
     this.r2 = r2;
 }