private bool TestMapCollision(Rectangle kollitionsRect, Edge riktning, KollitionsStatusTiled KollitionsStatus, out int KollitsionResponse)
        {
            KollitsionResponse = 0;
            Edge side = riktning.OppositeEdge();
            int  perpindicularPosition = side.IsVertical() ? kollitionsRect.Center.X : kollitionsRect.Center.Y;
            int  leadingPosition       = kollitionsRect.GetSide(riktning);
            bool shouldTestSlopes      = side.IsVertical();

            PopulateCollidingTiles(kollitionsRect, riktning);

            for (int i = 0; i < KolliderandeTiles.Count; i++)
            {
                if (KolliderandeTiles[i] == null)
                {
                    continue;
                }

                // disregard horizontal collisions with tiles on the same row as a slope if the last tile we were grounded on was a slope.
                // the y collision response will push us up on the slope.
                if (riktning.IsHorizontal() && KollitionsStatus.SitaGrundadeTile != null &&
                    KollitionsStatus.SitaGrundadeTile.IsSlope() && IsSlopeCollisionRow(KolliderandeTiles[i].Y))
                {
                    continue;
                }

                if (TestTileCollision(KolliderandeTiles[i], side, perpindicularPosition, leadingPosition,
                                      shouldTestSlopes, out KollitsionResponse))
                {
                    // store off our last ground tile if we collided below
                    if (riktning == Edge.Bottom)
                    {
                        KollitionsStatus.SitaGrundadeTile             = KolliderandeTiles[i];
                        KollitionsStatus.GrundadPåEnkelriktadPlatform = KollitionsStatus.SitaGrundadeTile.IsOneWayPlatform();
                    }

                    return(true);
                }

                // special case for sloped ground tiles
                if (KollitionsStatus.SitaGrundadeTile != null && riktning == Edge.Bottom)
                {
                    // if grounded on a slope and intersecting a slope or if grounded on a wall and intersecting a tall slope we go sticky.
                    // tall slope here means one where the the slopeTopLeft/Right is 0, i.e. it connects to a wall
                    var isHighSlopeNearest = KolliderandeTiles[i].IsSlope() &&
                                             KolliderandeTiles[i].GetNearestEdge(perpindicularPosition) ==
                                             KolliderandeTiles[i].GetHighestSlopeEdge();
                    if ((KollitionsStatus.SitaGrundadeTile.IsSlope() && KolliderandeTiles[i].IsSlope()) || (!KollitionsStatus.SitaGrundadeTile.IsSlope() && isHighSlopeNearest))
                    {
                        // store off our last ground tile if we collided below
                        KollitionsStatus.SitaGrundadeTile = KolliderandeTiles[i];
                        return(true);
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// moves the Entity taking into account the tiled map
        /// </summary>
        /// <param name="rörelse">Motion.</param>
        /// <param name="boxCollider">Box collider.</param>
        public void Move(Vector2 rörelse, BoxCollider boxCollider, KollitionsStatusTiled KollitionsStatus)
        {
            if (Karta == null)
            {
                return;
            }

            // test for collisions then move the Entity
            TestCollisions(ref rörelse, boxCollider.Bounds, KollitionsStatus);

            boxCollider.UnregisterColliderWithPhysicsSystem();
            boxCollider.Entity.Transform.Position += rörelse;
            boxCollider.RegisterColliderWithPhysicsSystem();
        }
        public void TestCollisions(ref Vector2 rörelse, Rectangle boxColliderGränser, KollitionsStatusTiled KollitionsStatus)
        {
            BoxColliderGränser = boxColliderGränser;

            // save off our current grounded state which we will use for wasGroundedLastFrame and becameGroundedThisFrame
            KollitionsStatus.VarGrundadFöraFramen = KollitionsStatus.Under;

            // reset our collisions state
            KollitionsStatus.Återställ(ref rörelse);

            // reset rounded motion for us while dealing with subpixel movement so fetch the rounded values to use for our actual detection
            int motionX = (int)rörelse.X;
            int motionY = (int)rörelse.Y;

            // first, check movement in the horizontal dir
            if (motionX != 0)
            {
                Edge      direction   = motionX > 0 ? Edge.Right : Edge.Left;
                Rectangle sweptBounds = CollisionRectForSide(direction, motionX);

                int collisionResponse;
                if (TestMapCollision(sweptBounds, direction, KollitionsStatus, out collisionResponse))
                {
                    // react to collision. get the distance between our leading edge and what we collided with
                    rörelse.X = collisionResponse - boxColliderGränser.GetSide(direction);
                    KollitionsStatus.Vänster = direction == Edge.Left;
                    KollitionsStatus.Höger   = direction == Edge.Right;
                    KollitionsStatus.RörelsePåminareX.Reset();
                }
                else
                {
                    KollitionsStatus.Vänster = false;
                    KollitionsStatus.Höger   = false;
                }
            }

            // next, check movement in the vertical dir
            {
                Edge      riktning     = motionY >= 0 ? Edge.Bottom : Edge.Top;
                Rectangle sweptGränser = CollisionRectForSide(riktning, motionY);
                sweptGränser.X += (int)rörelse.X;

                int KollitsionResponse;
                if (TestMapCollision(sweptGränser, riktning, KollitionsStatus, out KollitsionResponse))
                {
                    // react to collision. get the distance between our leading edge and what we collided with
                    rörelse.Y = KollitsionResponse - boxColliderGränser.GetSide(riktning);
                    KollitionsStatus.Ovanför = riktning == Edge.Top;
                    KollitionsStatus.Under   = riktning == Edge.Bottom;
                    KollitionsStatus.RörelsePåminareY.Reset();

                    if (KollitionsStatus.Under && KollitionsStatus.SitaGrundadeTile?.IsSlope() == true)
                    {
                        KollitionsStatus.SlopeVinkel = MathHelper.ToDegrees((float)Math.Atan(KollitionsStatus.SitaGrundadeTile.GetSlope()));
                    }
                }
                else
                {
                    KollitionsStatus.Ovanför          = false;
                    KollitionsStatus.Under            = false;
                    KollitionsStatus.SitaGrundadeTile = null;
                }


                // when moving down we also check for collisions in the opposite direction. this needs to be done so that ledge bumps work when
                // a jump is made but misses by the colliderVerticalInset
                if (riktning == Edge.Bottom)
                {
                    riktning        = riktning.OppositeEdge();
                    sweptGränser    = CollisionRectForSide(riktning, 0);
                    sweptGränser.X += (int)rörelse.X;
                    sweptGränser.Y += (int)rörelse.Y;

                    if (TestMapCollision(sweptGränser, riktning, KollitionsStatus, out KollitsionResponse))
                    {
                        // react to collision. get the distance between our leading edge and what we collided with
                        rörelse.Y = KollitsionResponse - boxColliderGränser.GetSide(riktning);

                        // if we collide here this is an overlap of a slope above us. this small bump down will prevent hitches when hitting
                        // our head on a slope that connects to a solid tile. It puts us below the slope when the normal response would put us
                        // above it
                        rörelse.Y += 2;
                        KollitionsStatus.Ovanför = true;
                    }
                }
            }

            // set our becameGrounded state based on the previous and current collision state
            if (!KollitionsStatus.VarGrundadFöraFramen && KollitionsStatus.Under)
            {
                KollitionsStatus.BlevGrundadDennaFrame = true;
            }
        }