/// <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));
                }
            }
        }
Esempio n. 2
0
        // 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);
        }
Esempio n. 3
0
        /// <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));
                    }
                }
            }
        }
Esempio n. 4
0
        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));
                    }
                }
            }
        }
Esempio n. 5
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);
        }