Beispiel #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="side"></param>
        /// <returns></returns>
        private static Vector2 GetSideNormalCollision(EnemiesCollisionSide side)
        {
            switch (side)
            {
            case EnemiesCollisionSide.Top: return(new Vector2(0, -1));

            case EnemiesCollisionSide.Bottom: return(Vector2.UnitY);

            case EnemiesCollisionSide.Left: return(Vector2.UnitX);

            case EnemiesCollisionSide.Right: return(new Vector2(-1, 0));

            default: return(Vector2.Zero);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Check where and which direction should the enemies collide to
        /// </summary>
        /// <param name="timeStep"></param>
        /// <param name="screenWidth"></param>
        /// <param name="screenHeight"></param>
        /// <param name="firstObjectVelocity"></param>
        /// <param name="secondObjectVelocity"></param>
        /// <param name="firstObjectRectangle"></param>
        /// <param name="secondObjectRectangle"></param>
        /// <returns></returns>
        public static EnemiesCollisionInfor CheckCollisions(int timeStep, int screenWidth, int screenHeight,
                                                            Vector2 firstObjectVelocity, Vector2 secondObjectVelocity,
                                                            Rectangle firstObjectRectangle, Rectangle secondObjectRectangle)
        {
            Rectangle initialFirstObject;
            Rectangle initialSecondObject;
            Rectangle finalfirstObject;
            Rectangle finalSecondObject;
            Rectangle collisionRectangle;

            //checking if they are overlap
            bool detectedCollision = firstObjectRectangle.Intersects(secondObjectRectangle);

            if (detectedCollision)
            {
                // getting the same size of the rectangle
                finalfirstObject.Width   = firstObjectRectangle.Width;
                finalfirstObject.Height  = firstObjectRectangle.Height;
                finalSecondObject.Width  = secondObjectRectangle.Width;
                finalSecondObject.Height = secondObjectRectangle.Height;

                // Getting the information right at the moment they overlap
                float firstXSpeed = (firstObjectVelocity.X * timeStep);
                float firstYSpeed = (firstObjectVelocity.Y * timeStep);
                initialFirstObject.X      = (int)(firstObjectRectangle.X - firstXSpeed);
                initialFirstObject.Y      = (int)(firstObjectRectangle.Y - firstYSpeed);
                initialFirstObject.Width  = firstObjectRectangle.Width;
                initialFirstObject.Height = firstObjectRectangle.Height;

                float secondXSpeed = (secondObjectRectangle.X * timeStep);
                float secondYSpeed = (secondObjectRectangle.Y * timeStep);
                initialSecondObject.X      = (int)(secondObjectRectangle.X - secondXSpeed);
                initialSecondObject.Y      = (int)(secondObjectRectangle.Y - secondYSpeed);
                initialSecondObject.Width  = secondObjectRectangle.Width;
                initialSecondObject.Height = secondObjectRectangle.Height;

                // Constantly, the time step is 60 frames per second, time will increament by the power of 2
                int timeIncrement   = timeStep / 2;
                int collisionDeltaT = timeStep;      // rate of change of time
                int DeltaT          = timeIncrement; // rate of change of time at a certain moment

                while (timeIncrement > 0)
                {
                    // Move the objects
                    firstXSpeed  = firstObjectVelocity.X * DeltaT;
                    firstYSpeed  = firstObjectVelocity.Y * DeltaT;
                    secondXSpeed = secondObjectVelocity.X * DeltaT;
                    secondYSpeed = secondObjectVelocity.Y * DeltaT;

                    // Updating current Location for the objects
                    finalfirstObject.X  = (int)(initialFirstObject.X + firstXSpeed);
                    finalfirstObject.Y  = (int)(initialFirstObject.Y + firstYSpeed);
                    finalSecondObject.X = (int)(initialSecondObject.X + secondXSpeed);
                    finalSecondObject.Y = (int)(initialSecondObject.Y + secondYSpeed);

                    // decreasing the time increament
                    timeIncrement /= 2;

                    // check if they bound again or not
                    detectedCollision = finalfirstObject.Intersects(finalSecondObject);

                    if (detectedCollision)
                    {   // if the collision happens again
                        collisionDeltaT = DeltaT;
                        DeltaT         -= timeIncrement;

                        Rectangle.Intersect(ref finalfirstObject, ref finalSecondObject, out collisionRectangle);
                    }
                    else
                    {
                        DeltaT += timeIncrement;
                    }
                }

                // Start the Collision
                int collisionStartTime = collisionDeltaT;
                firstXSpeed  = firstObjectVelocity.X * collisionStartTime;
                firstYSpeed  = firstObjectVelocity.Y * collisionStartTime;
                secondXSpeed = secondObjectVelocity.X * collisionStartTime;
                secondYSpeed = secondObjectVelocity.Y * collisionStartTime;

                finalfirstObject.X  = (int)(initialFirstObject.X + firstXSpeed);
                finalfirstObject.Y  = (int)(initialFirstObject.Y + firstYSpeed);
                finalSecondObject.X = (int)(initialSecondObject.X + secondXSpeed);
                finalSecondObject.Y = (int)(initialSecondObject.Y + secondYSpeed);

                // Check the side of the collision
                Rectangle            collisionIntersection = Rectangle.Intersect(finalfirstObject, finalSecondObject);
                EnemiesCollisionSide possibleSide          = checkCollisionSide(finalSecondObject, collisionIntersection,
                                                                                firstObjectVelocity, secondObjectVelocity);

                // Let the object move over the time Step
                int preCollisionTime  = collisionStartTime - 1;
                int postCollisionTime = timeStep - preCollisionTime;

                EnemiesCollisionInfor enemiesBounce = getBounceObjects(firstObjectVelocity, initialFirstObject,
                                                                       secondObjectVelocity, initialSecondObject,
                                                                       preCollisionTime, postCollisionTime, possibleSide);
                enemiesBounce.firstOutBounds  = IsOutOfBounds(firstObjectRectangle, screenWidth, screenHeight);
                enemiesBounce.SecondOutBounds = IsOutOfBounds(secondObjectRectangle, screenWidth, screenHeight);

                return(enemiesBounce);
            }
            else
            {
                // no collision happens -> no enemiesCollisionInfor
                return(null);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Get the new velocity for each object after collision
        /// </summary>
        /// <param name="firstVelocity"></param>
        /// <param name="secondVelocity"></param>
        /// <param name="side"></param>
        /// <param name="newFirstVelocity"></param>
        /// <param name="newSecondVelocity"></param>
        private static void getNewVelocities(Vector2 firstVelocity, Vector2 secondVelocity, EnemiesCollisionSide side,
                                             out Vector2 newFirstVelocity, out Vector2 newSecondVelocity)
        {
            switch (side)
            {
            case EnemiesCollisionSide.Top:
                if (firstVelocity.Y > 0 && secondVelocity.Y > 0)
                {
                    // first object caught up to second object, change the first y velocity
                    newFirstVelocity  = new Vector2(firstVelocity.X, -1 * firstVelocity.Y);
                    newSecondVelocity = secondVelocity;
                }
                else if (firstVelocity.Y < 0 && secondVelocity.Y < 0)
                {
                    // second object caught up to first object, change the second y velocity
                    newFirstVelocity  = firstVelocity;
                    newSecondVelocity = new Vector2(secondVelocity.X, -1 * secondVelocity.Y);
                }
                else
                {
                    // normal collision, change both velocities of two objects
                    newFirstVelocity  = new Vector2(firstVelocity.X, -1 * firstVelocity.Y);
                    newSecondVelocity = new Vector2(secondVelocity.X, -1 * secondVelocity.Y);
                }
                break;

            case EnemiesCollisionSide.Bottom:
                if (firstVelocity.Y > 0 && secondVelocity.Y > 0)
                {
                    // second object caught up to first object, change the second y velocity
                    newFirstVelocity  = firstVelocity;
                    newSecondVelocity = new Vector2(secondVelocity.X, -1 * secondVelocity.Y);
                }
                else if (firstVelocity.Y < 0 && secondVelocity.Y < 0)
                {
                    // first object caught up to second object, change the first y velocity
                    newFirstVelocity  = new Vector2(firstVelocity.X, -1 * firstVelocity.Y);
                    newSecondVelocity = secondVelocity;
                }
                else
                {
                    // normal collision, change both velocities of two objects
                    newFirstVelocity  = new Vector2(firstVelocity.X, -1 * firstVelocity.Y);
                    newSecondVelocity = new Vector2(secondVelocity.X, -1 * secondVelocity.Y);
                }

                break;

            case EnemiesCollisionSide.Left:
                if (firstVelocity.X > 0 && secondVelocity.X > 0)
                {
                    // first object caught up to second object, change the first x velocity
                    newFirstVelocity  = new Vector2(firstVelocity.X * -1, firstVelocity.Y);
                    newSecondVelocity = secondVelocity;
                }
                else if (firstVelocity.X < 0 && secondVelocity.X < 0)
                {
                    // second object caught up to first object, change the second x velocity
                    newFirstVelocity  = firstVelocity;
                    newSecondVelocity = new Vector2(secondVelocity.X * -1, secondVelocity.Y);
                }
                else
                {
                    // normal collision, change both velocities of two objects
                    newFirstVelocity  = new Vector2(firstVelocity.X * -1, firstVelocity.Y);
                    newSecondVelocity = new Vector2(secondVelocity.X * -1, secondVelocity.Y);
                }
                break;

            case EnemiesCollisionSide.Right:
                if (firstVelocity.X > 0 && secondVelocity.X > 0)
                {
                    // second object caught up to first object, change the second x velocity
                    newFirstVelocity  = firstVelocity;
                    newSecondVelocity = new Vector2(secondVelocity.X * -1, secondVelocity.Y);
                }
                else if (firstVelocity.X < 0 && secondVelocity.X < 0)
                {
                    // first object caught up to second object, change the first x velocity
                    newFirstVelocity  = new Vector2(firstVelocity.X * -1, firstVelocity.Y);
                    newSecondVelocity = secondVelocity;
                }
                else
                {
                    // normal collision, change both velocities of two objects
                    newFirstVelocity  = new Vector2(firstVelocity.X * -1, firstVelocity.Y);
                    newSecondVelocity = new Vector2(secondVelocity.X * -1, secondVelocity.Y);
                }
                break;

            default:
                newFirstVelocity  = firstVelocity;
                newSecondVelocity = secondVelocity;
                break;
            }
        }
Beispiel #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="firstObjectVelocity"></param>
        /// <param name="firstObjectRectangle"></param>
        /// <param name="secondObjectVelocity"></param>
        /// <param name="secondObjectRectangle"></param>
        /// <param name="preCollisionTime"></param>
        /// <param name="postCollisionTime"></param>
        /// <param name="side"></param>
        /// <returns></returns>
        private static EnemiesCollisionInfor getBounceObjects(Vector2 firstObjectVelocity, Rectangle firstObjectRectangle,
                                                              Vector2 secondObjectVelocity, Rectangle secondObjectRectangle,
                                                              int preCollisionTime, int postCollisionTime, EnemiesCollisionSide side)
        {
            // make a temp variables for the initial speeds
            float firstSpeed  = firstObjectVelocity.Length();
            float secondSpeed = secondObjectVelocity.Length();

            // get the properties in order to move the object forward
            Rectangle newFirstRectangle  = moveObjects(firstObjectVelocity, firstObjectRectangle, preCollisionTime);
            Rectangle newSecondRectangle = moveObjects(secondObjectVelocity, secondObjectRectangle, preCollisionTime);

            // Change the velocity
            Vector2 newFirstVelocity;
            Vector2 newSecondVelocity;

            getNewVelocities(firstObjectVelocity, secondObjectVelocity, side, out newFirstVelocity, out newSecondVelocity);

            // move the object forward
            moveObjects(newFirstVelocity, newFirstRectangle, postCollisionTime);
            moveObjects(newSecondVelocity, newSecondRectangle, postCollisionTime);

            // If the objects are still colliding
            MoveCollidingObjects(newFirstVelocity, newFirstRectangle, newSecondVelocity, newSecondRectangle,
                                 out newFirstRectangle, out newSecondRectangle);
            return(new EnemiesCollisionInfor(newFirstVelocity, newFirstRectangle, false, newSecondVelocity, newSecondRectangle, false));
        }
        /// <summary>
        /// Returns the collision resolution info object associated with a detected collision or null if no collision
        /// is detected
        ///
        /// Ref: David M. Bourg, Physics for Game Developers, pages 207 and 209
        /// </summary>
        /// <param name="timeStep">the time step, in milliseconds</param>
        /// <param name="windowWidth">the width of the game window</param>
        /// <param name="windowHeight">the height of the game window</param>
        /// <param name="firstVelocity">the velocity of the first object</param>
        /// <param name="firstDrawRectangle">the draw rectangle of the first object</param>
        /// <param name="secondVelocity">the velocity of the second object</param>
        /// <param name="secondDrawRectangle">the draw rectangle of the second object</param>
        /// <returns>the collision resolution info object for a detected collision or null if no collision is detected</returns>
        public static EnemiesCollisionInfor CheckCollision(int timeStep, int windowWidth, int windowHeight,
                                                           Vector2 firstVelocity, Rectangle firstDrawRectangle,
                                                           Vector2 secondVelocity, Rectangle secondDrawRectangle)
        {
            Rectangle initialFirstAabr;
            Rectangle initialSecondAabr;
            Rectangle currentFirstAabr;
            Rectangle currentSecondAabr;
            Rectangle collisionRectangle;

            // overlap test
            bool collisionDetected = firstDrawRectangle.Intersects(secondDrawRectangle);

            if (collisionDetected)
            {
                // initialize non-changing properties
                currentFirstAabr.Width   = firstDrawRectangle.Width;
                currentFirstAabr.Height  = firstDrawRectangle.Height;
                currentSecondAabr.Width  = secondDrawRectangle.Width;
                currentSecondAabr.Height = secondDrawRectangle.Height;

                // back up both objects to their locations before the time step
                float firstDx = (firstVelocity.X * timeStep);
                float firstDy = (firstVelocity.Y * timeStep);
                initialFirstAabr.X      = (int)(firstDrawRectangle.X - firstDx);
                initialFirstAabr.Y      = (int)(firstDrawRectangle.Y - firstDy);
                initialFirstAabr.Width  = firstDrawRectangle.Width;
                initialFirstAabr.Height = firstDrawRectangle.Height;

                float secondDx = (secondVelocity.X * timeStep);
                float secondDy = (secondVelocity.Y * timeStep);
                initialSecondAabr.X      = (int)(secondDrawRectangle.X - secondDx);
                initialSecondAabr.Y      = (int)(secondDrawRectangle.Y - secondDy);
                initialSecondAabr.Width  = secondDrawRectangle.Width;
                initialSecondAabr.Height = secondDrawRectangle.Height;

                // at fixed time step of 60 fps, time increment can only be 8, 4, 2, or 1
                int timeIncrement = timeStep / 2;
                int collisionDt   = timeStep;  // we know we have a collision or we wouldn't be here
                int dt            = timeIncrement;
                while (timeIncrement > 0)
                {
                    // move both objects forward by dt from their initial positions
                    firstDx  = firstVelocity.X * dt;
                    firstDy  = firstVelocity.Y * dt;
                    secondDx = secondVelocity.X * dt;
                    secondDy = secondVelocity.Y * dt;

                    // update axis-aligned bounding rectangles
                    currentFirstAabr.X  = (int)(initialFirstAabr.X + firstDx);
                    currentFirstAabr.Y  = (int)(initialFirstAabr.Y + firstDy);
                    currentSecondAabr.X = (int)(initialSecondAabr.X + secondDx);
                    currentSecondAabr.Y = (int)(initialSecondAabr.Y + secondDy);

                    // cut time increment in half as we search for the time of collision
                    timeIncrement /= 2;

                    collisionDetected = currentFirstAabr.Intersects(currentSecondAabr);
                    if (collisionDetected)
                    {
                        // collision detected, so save collision dt and reduce dt to make it earlier
                        collisionDt = dt;
                        dt         -= timeIncrement;

                        // save the collision rectangle in case we don't find any other collisions
                        Rectangle.Intersect(ref currentFirstAabr, ref currentSecondAabr, out collisionRectangle);
                    }
                    else
                    {
                        // no collision detected, so increase dt to make it later
                        dt += timeIncrement;
                    }
                }

                // get rectangle locations at start of collision
                int collisionStartTime = collisionDt;
                firstDx  = firstVelocity.X * collisionStartTime;
                firstDy  = firstVelocity.Y * collisionStartTime;
                secondDx = secondVelocity.X * collisionStartTime;
                secondDy = secondVelocity.Y * collisionStartTime;

                currentFirstAabr.X  = (int)(initialFirstAabr.X + firstDx);
                currentFirstAabr.Y  = (int)(initialFirstAabr.Y + firstDy);
                currentSecondAabr.X = (int)(initialSecondAabr.X + secondDx);
                currentSecondAabr.Y = (int)(initialSecondAabr.Y + secondDy);

                // use square collision normals
                Rectangle            intersection  = Rectangle.Intersect(currentFirstAabr, currentSecondAabr);
                EnemiesCollisionSide collisionSide = GetCollisionSide(currentSecondAabr,
                                                                      intersection, firstVelocity, secondVelocity);

                // move objects through complete time step
                int preCollisionDuration       = collisionStartTime - 1;
                int postCollisionDuration      = timeStep - collisionStartTime + 1;
                EnemiesCollisionInfor colInfor = BounceObjects(firstVelocity, initialFirstAabr,
                                                               secondVelocity, initialSecondAabr, preCollisionDuration, postCollisionDuration,
                                                               collisionSide);

                // check out of bounds and return
                colInfor.firstOutBounds  = OutOfBounds(firstDrawRectangle, windowWidth, windowHeight);
                colInfor.SecondOutBounds = OutOfBounds(secondDrawRectangle, windowWidth, windowHeight);
                return(colInfor);
            }
            else
            {
                // no collision
                return(null);
            }
        }
        /// <summary>
        /// Gets the new velocity vectors for the collider (first object) and
        /// collidee (second object) in a collision. Need to be careful if
        /// the collider caught up to the collidee when both were going in
        /// the same direction
        /// </summary>
        /// <param name="firstVelocity">velocity of the first object</param>
        /// <param name="secondVelocity">velocity of the second object</param>
        /// <param name="collisionSide">the collision side</param>
        /// <param name="newFirstVelocity">the new first object velocity</param>
        /// <param name="newSecondVelocity">the new second object velocity</param>
        private static void GetNewVelocities(Vector2 firstVelocity, Vector2 secondVelocity,
                                             EnemiesCollisionSide collisionSide, out Vector2 newFirstVelocity, out Vector2 newSecondVelocity)
        {
            switch (collisionSide)
            {
            case EnemiesCollisionSide.Top:
                if (firstVelocity.Y > 0 && secondVelocity.Y > 0)
                {
                    // first object caught up to second object, only change first y velocity
                    newFirstVelocity  = new Vector2(firstVelocity.X, -1 * firstVelocity.Y);
                    newSecondVelocity = secondVelocity;
                }
                else if (firstVelocity.Y < 0 && secondVelocity.Y < 0)
                {
                    // second object caught up to first object, only change second y velocity
                    newFirstVelocity  = firstVelocity;
                    newSecondVelocity = new Vector2(secondVelocity.X, -1 * secondVelocity.Y);
                }
                else
                {
                    // normal top collision, change both y velocities
                    newFirstVelocity  = new Vector2(firstVelocity.X, -1 * firstVelocity.Y);
                    newSecondVelocity = new Vector2(secondVelocity.X, -1 * secondVelocity.Y);
                }
                break;

            case EnemiesCollisionSide.Bottom:
                if (firstVelocity.Y > 0 && secondVelocity.Y > 0)
                {
                    // second object caught up to first object, only change second y velocity
                    newFirstVelocity  = firstVelocity;
                    newSecondVelocity = new Vector2(secondVelocity.X, -1 * secondVelocity.Y);
                }
                else if (firstVelocity.Y < 0 && secondVelocity.Y < 0)
                {
                    // first object caught up to second object, only change first y velocity
                    newFirstVelocity  = new Vector2(firstVelocity.X, -1 * firstVelocity.Y);
                    newSecondVelocity = secondVelocity;
                }
                else
                {
                    // normal bottom collision, change both y velocities
                    newFirstVelocity  = new Vector2(firstVelocity.X, -1 * firstVelocity.Y);
                    newSecondVelocity = new Vector2(secondVelocity.X, -1 * secondVelocity.Y);
                }
                break;

            case EnemiesCollisionSide.Left:
                if (firstVelocity.X > 0 && secondVelocity.X > 0)
                {
                    // first object caught up to second object, only change first x velocity
                    newFirstVelocity  = new Vector2(-1 * firstVelocity.X, firstVelocity.Y);
                    newSecondVelocity = secondVelocity;
                }
                else if (firstVelocity.X < 0 && secondVelocity.X < 0)
                {
                    // second object caught up to first object, only change second x velocity
                    newFirstVelocity  = firstVelocity;
                    newSecondVelocity = new Vector2(-1 * secondVelocity.X, secondVelocity.Y);
                }
                else
                {
                    // normal left collision, change both x velocities
                    newFirstVelocity  = new Vector2(-1 * firstVelocity.X, firstVelocity.Y);
                    newSecondVelocity = new Vector2(-1 * secondVelocity.X, secondVelocity.Y);
                }
                break;

            case EnemiesCollisionSide.Right:
                if (firstVelocity.X > 0 && secondVelocity.X > 0)
                {
                    // second object caught up to first object, only change second x velocity
                    newFirstVelocity  = firstVelocity;
                    newSecondVelocity = new Vector2(-1 * secondVelocity.X, secondVelocity.Y);
                }
                else if (firstVelocity.X < 0 && secondVelocity.X < 0)
                {
                    // first object caught up to second object, only change first x velocity
                    newFirstVelocity  = new Vector2(-1 * firstVelocity.X, firstVelocity.Y);
                    newSecondVelocity = secondVelocity;
                }
                else
                {
                    // normal right collision, change both x velocities
                    newFirstVelocity  = new Vector2(-1 * firstVelocity.X, firstVelocity.Y);
                    newSecondVelocity = new Vector2(-1 * secondVelocity.X, secondVelocity.Y);
                }
                break;

            default:
                // should never get here
                newFirstVelocity  = firstVelocity;
                newSecondVelocity = secondVelocity;
                break;
            }
        }
        /// <summary>
        /// Bounces the two objects off each other. This method makes sure the speed
        /// of each object after the bounce is set to the given speed values
        /// </summary>
        /// <param name="firstVelocity">the velocity of the first object</param>
        /// <param name="firstDrawRectangle">the draw rectangle of the first object</param>
        /// <param name="secondVelocity">the velocity of the second object</param>
        /// <param name="secondDrawRectangle">the draw rectangle of the second object</param>
        /// <param name="preCollisionDuration">the duration before the collision</param>
        /// <param name="postCollisionDuration">the duration after the collision</param>
        /// <param name="collisionSide">the collision side</param>
        /// <returns>the collision resolution info object</returns>
        private static EnemiesCollisionInfor BounceObjects(Vector2 firstVelocity, Rectangle firstDrawRectangle,
                                                           Vector2 secondVelocity, Rectangle secondDrawRectangle, int preCollisionDuration,
                                                           int postCollisionDuration, EnemiesCollisionSide collisionSide)
        {
            // save speeds for later
            float firstSpeed  = firstVelocity.Length();
            float secondSpeed = secondVelocity.Length();

            // move forward up to collision
            Rectangle newFirstDrawRectangle = MoveForward(firstVelocity, firstDrawRectangle,
                                                          preCollisionDuration);
            Rectangle newSecondDrawRectangle = MoveForward(secondVelocity, secondDrawRectangle,
                                                           preCollisionDuration);

            // change velocities as appropriate
            Vector2 newFirstVelocity;
            Vector2 newSecondVelocity;

            GetNewVelocities(firstVelocity, secondVelocity, collisionSide,
                             out newFirstVelocity, out newSecondVelocity);

            // move objects forward after collision
            MoveForward(newFirstVelocity, newFirstDrawRectangle,
                        postCollisionDuration);
            MoveForward(newSecondVelocity, newSecondDrawRectangle,
                        postCollisionDuration);


            // may still need to move objects apart if they're still colliding
            MoveCollidingObjectsApart(newFirstVelocity, newFirstDrawRectangle,
                                      newSecondVelocity, newSecondDrawRectangle,
                                      out newFirstDrawRectangle, out newSecondDrawRectangle);

            return(new EnemiesCollisionInfor(newFirstVelocity, newFirstDrawRectangle,
                                             false, newSecondVelocity, newSecondDrawRectangle, false));
        }