Ejemplo n.º 1
0
        /// <summary>
        /// Tests to see if an object's intended x- and y-displacements are fully achievable in its
        /// current room and position. Causes a collision and modifies the displacement value if
        /// it would send the object into a collideable surface.
        /// </summary>
        /// <param name="obj">The object to be evaluated.</param>
        /// <param name="room">The room in which the object is located and trying to move.</param>
        /// <param name="time">The amount of time since the last frame.</param>
        public static void Update(PhysicsObject obj, Room room, GameTime time)
        {
            PhysicsObject ridingAtStart = obj.riding;
            float totalTime = (float)(time.ElapsedGameTime.TotalSeconds);
            //All ungrounded, gravity-affected objects will have the displacement caused by
            //gravity in this frame added to their y-displacement.
            if (obj.IsGravityAffected && !obj.IsOnGround)
                obj.DisplacementY = Math.Min(obj.DisplacementY + (GRAVITY / 2) * (totalTime * totalTime), MAX_FALLING_SPEED * totalTime);

            obj.DisplacementX = (float)((int)(obj.DisplacementX));
            obj.DisplacementY = (float)((int)(obj.DisplacementY));

            //If the object will get stuck trying to move the originally intended amount, a collision
            //has occurred. The appropriate velocity & acceleration variables as well as boolean flags
            //will be reset, by calling the appropriate collision function (HitCeiling(), Land(), or
            //HitWall()).
            //Then the intended displacement is decreased by one until the object finds a coordinate
            //at which it will no longer be stuck.
            if (obj.DisplacementY < 0)
            {
                if (obj.IsStuck(room, 0, (int)obj.DisplacementY))
                {
                    obj.HitCeiling();
                    obj.DisplacementY += 1;
                    while (obj.DisplacementY != 0 && obj.IsStuck(room, 0, (int)obj.DisplacementY))
                        obj.DisplacementY += 1;
                }
                if (obj.SticksToSurfaces && obj.DisplacementX == 0)
                {
                    if (obj.WillLoseSurface(room))
                    {
                        while (obj.WillLoseSurface(room))
                            obj.DisplacementY += 1;
                    }
                }
            }
            else if (obj.DisplacementY > 0)
            {
                if (obj.IsStuck(room, 0, (int)obj.DisplacementY))
                {
                    obj.Land();
                    obj.DisplacementY -= 1;
                    while (obj.DisplacementY != 0 && obj.IsStuck(room, 0, (int)obj.DisplacementY))
                        obj.DisplacementY -= 1;
                }
                if (obj.SticksToSurfaces && obj.DisplacementX == 0)
                {
                    if (obj.WillLoseSurface(room))
                    {
                        while (obj.WillLoseSurface(room))
                            obj.DisplacementY -= 1;
                    }
                }
            }

            if (obj.DisplacementX > 0)
            {
                if (obj.IsStuck(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                {
                    obj.CollideRight();
                    obj.DisplacementX -= 1;
                    while (obj.DisplacementX != 0 && obj.IsStuck(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                        obj.DisplacementX -= 1;
                }
                if (!obj.MovesOffEdges && obj.IsOnGround && obj.DisplacementY == 0)
                {
                    if (obj.WillMovePastEdge(room))
                    {
                        obj.VelocityX *= -1;
                        while (obj.WillMovePastEdge(room))
                            obj.DisplacementX -= 1;
                    }
                }
                if (obj.SticksToSurfaces && obj.DisplacementY == 0)
                {
                    if (obj.WillLoseSurface(room))
                    {
                        while (obj.WillLoseSurface(room))
                            obj.DisplacementX -= 1;
                    }
                }
            }
            else if (obj.DisplacementX < 0)
            {
                if (obj.IsStuck(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                {
                    obj.CollideLeft();
                    obj.DisplacementX += 1;
                    while (obj.DisplacementX != 0 && obj.IsStuck(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                        obj.DisplacementX += 1;
                }
                if (!obj.MovesOffEdges && obj.IsOnGround && obj.DisplacementY == 0)
                {
                    if (obj.WillMovePastEdge(room))
                    {
                        obj.VelocityX *= -1;
                        while (obj.WillMovePastEdge(room))
                            obj.DisplacementX += 1;
                    }
                }
                if (obj.SticksToSurfaces && obj.DisplacementY == 0)
                {
                    if (obj.WillLoseSurface(room))
                    {
                        while (obj.WillLoseSurface(room))
                            obj.DisplacementX += 1;
                    }
                }
            }
            else if (obj.DisplacementX == 0 && obj.DisplacementY == 0)
            {
                if (obj.IsStuck(room, 0, 0))
                {
                    if (obj.WallOnLeft && !obj.WallOnRight)
                        obj.DisplacementX += STUCK_OBJ_DISPLACEMENT;
                    else if (obj.WallOnRight && !obj.WallOnLeft)
                        obj.DisplacementX -= STUCK_OBJ_DISPLACEMENT;
                }
            }

            //Even if a displacement value goes unchanged in the above test, it's still possible that the object
            //will (not) have a wall beside or ground beneath them after moving their full displacements. This last
            //test checks to see if this is the case, and changes the appropriate boolean flags accordingly.
            //If the object is touching a floor in its new position, the appropriate collision-causing function
            //is called.
            //If an object was airborne at the beginning of the frame and is still airborne, its y-velocity
            //is increased by the acceleration due to gravity.
            //If it's determined that the object is now in the air, it will become airborne.

            if (!obj.WallOnLeft)
            {
                if (obj.CheckWallLeft(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                    obj.CollideLeft();
            }
            else
            {
                if (!obj.CheckWallLeft(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                    obj.WallOnLeft = false;
            }

            if (!obj.WallOnRight)
            {
                if (obj.CheckWallRight(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                    obj.CollideRight();
            }
            else
            {
                if (!obj.CheckWallRight(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                    obj.WallOnRight = false;
            }

            if (!obj.IsOnGround)
            {
                if (obj.CheckGround(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                    obj.Land();
                else if (obj.IsGravityAffected)
                    obj.VelocityY = Math.Min(obj.VelocityY + GRAVITY * totalTime, MAX_FALLING_SPEED);
            }
            else
            {
                if (!obj.CheckGround(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                    obj.LeaveGround();
            }

            if (!obj.CeilingAbove)
            {
                if (obj.CheckCeiling(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                    obj.HitCeiling();
            }
            else
            {
                if (!obj.CheckCeiling(room, (int)obj.DisplacementX, (int)obj.DisplacementY))
                    obj.LeaveCeiling();
            }

            if ((obj.riding != null) && (obj.riding == ridingAtStart))
            {
                obj.DisplacementX += ridingAtStart.DisplacementX;
                obj.DisplacementY += ridingAtStart.DisplacementY;
            }
        }