/// <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; }