/// <summary> /// gets a list of all the tiles intersecting bounds. The returned list is ordered for collision detection based on the /// direction passed in so they can be processed in order. /// </summary> /// <returns>The colliding tiles.</returns> /// <param name="bounds">Bounds.</param> /// <param name="riktining">Direction.</param> private void PopulateCollidingTiles(Rectangle bounds, Edge riktining) { KolliderandeTiles.Clear(); var isHorizontal = riktining.IsHorizontal(); var primaryAxis = isHorizontal ? Axis.X : Axis.Y; var oppositeAxis = primaryAxis == Axis.X ? Axis.Y : Axis.X; var oppositeDirection = riktining.OppositeEdge(); var firstPrimary = TilePosition(bounds.GetSide(oppositeDirection), primaryAxis); var lastPrimary = TilePosition(bounds.GetSide(riktining), primaryAxis); var primaryIncr = riktining.IsMax() ? 1 : -1; var min = TilePosition(isHorizontal ? bounds.Top : bounds.Left, oppositeAxis); var mid = TilePosition(isHorizontal ? bounds.GetCenter().Y : bounds.GetCenter().X, oppositeAxis); var max = TilePosition(isHorizontal ? bounds.Bottom : bounds.Right, oppositeAxis); var isPositive = mid - min < max - mid; var secondaryIncr = isPositive ? 1 : -1; var firstSecondary = isPositive ? min : max; var lastSecondary = !isPositive ? min : max; for (var primary = firstPrimary; primary != lastPrimary + primaryIncr; primary += primaryIncr) { for (var secondary = firstSecondary; secondary != lastSecondary + secondaryIncr; secondary += secondaryIncr) { var col = isHorizontal ? primary : secondary; var row = !isHorizontal ? primary : secondary; KolliderandeTiles.Add(KollitionsLager.GetTile(col, row)); } } }
// Check every tile between the two intersections // If blocked by grass, sidewalk, or another intersection, not connected private static bool IsConnected(Node a, Node b, TmxLayer layer) { if (a.tilePosition.X == b.tilePosition.X) { // Vertically aligned var dir = Math.Sign(b.tilePosition.Y - a.tilePosition.Y); for (int y = a.tilePosition.Y + dir; y != b.tilePosition.Y; y += dir) { var t = layer.GetTile(a.tilePosition.X, y); t.TilesetTile.Properties.TryGetValue(Constants.TiledPropertyID, out var value); if (value != Constants.TiledIDRoad) { return(false); } } return(true); } else if (a.tilePosition.Y == b.tilePosition.Y) { // Horizontally aligned var dir = Math.Sign(b.tilePosition.X - a.tilePosition.X); for (int x = a.tilePosition.X + dir; x != b.tilePosition.X; x += dir) { var t = layer.GetTile(x, a.tilePosition.Y); t.TilesetTile.Properties.TryGetValue(Constants.TiledPropertyID, out var value); if (value != Constants.TiledIDRoad) { return(false); } } return(true); } return(false); }
/// <summary> /// creates a WeightedGridGraph from a TiledTileLayer. Present tile are walls and empty tiles are passable. /// </summary> /// <param name="tiledLayer">Tiled layer.</param> public AstarGridGraph(TmxLayer tiledLayer) { _width = tiledLayer.Width; _height = tiledLayer.Height; for (var y = 0; y < tiledLayer.Map.Height; y++) { for (var x = 0; x < tiledLayer.Map.Width; x++) { if (tiledLayer.GetTile(x, y) != null) { Walls.Add(new Point(x, y)); } } } }
public UnweightedGridGraph(TmxLayer tiledLayer) { _width = tiledLayer.Width; _height = tiledLayer.Height; _dirs = CARDINAL_DIRS; for (var y = 0; y < tiledLayer.Map.Height; y++) { for (var x = 0; x < tiledLayer.Map.Width; x++) { if (tiledLayer.GetTile(x, y) != null) { Walls.Add(new Point(x, y)); } } } }
/// <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); }