//function to remove cannon balls if they are out of screen or remain stationary for a long time
 void removeUselessBall(CannonBall ball, ArrayList ballList)
 {
     if (ball.getPosition().x < leftBoundary || ball.getPosition().x > rightBoundary || ball.getPosition().y < bottonBoundary)
     {
         //when out of scree, remove the ball from the ball list and destroy it
         ballList.Remove(ball);
         Destroy(ball.GetGameObject());
     }
     else if (Mathf.Abs(ball.getVelocity().x) < 0.0001f)
     {
         //the ball's x-velocity is really small (caused by friction), remove the ball from the ball list and destroy it
         //note that it must been a long time for the ball staying on the ground to have such a small x-velocty
         ballList.Remove(ball);
         Destroy(ball.GetGameObject());
     }
 }
    //function to detect and handle collision bewtween cannon ball and collision lines (water, terrain and balloons)
    //taking one cannon ball and an array of points of the line (line with corners) as paramters, detect the collsion
    void handleCannonBallCollision(CannonBall ball, Vector3[] linePoints, ColliderType type)
    {
        GameObject ballObject = ball.GetGameObject();

        //check that if any line segment of the line is collided with the cannon ball
        for (int i = 0; i < linePoints.Length - 1; i++)
        {
            //if the line which the ball is colliding with is terrain
            if (type == ColliderType.TERRAIN)
            {
                // if the cannon ball is collided with the line
                if (CollisionCalculation.isCircleCollidesLine(linePoints[i].x, linePoints[i].y, linePoints[i + 1].x, linePoints[i + 1].y, ballObject.transform.position.x, ballObject.transform.position.y, ball.getRadius()))
                {
                    //if the ball is colliding with horizontal ground
                    if (linePoints[i].y - linePoints[i + 1].y == 0)
                    {
                        //apply an inverse acceleration to the gravity to cancel out the gravity
                        ball.updateVelocity(Time.deltaTime, new Vector2(0, -gravity));
                        //apply a friction to the ball when rolling on horizontal ground
                        applyFrictionOfGround(ball);
                    }
                    else  //when the ball is not colliding with the horizontal terrain, push it back by a small amount to avoid triggering continuous collision detection
                    {
                        //push the ball away from the terrain line in its normal vector direction by a small
                        //amount to avoid penetration
                        Vector2 unitNormal = CollisionCalculation.getNormal(linePoints[i].x, linePoints[i].y, linePoints[i + 1].x, linePoints[i + 1].y);
                        ball.translatePosition(Time.deltaTime, unitNormal * 1);
                    }

                    //handle the collision on terrain
                    bouncingAfterTerrainCollision(ball, linePoints[i].x, linePoints[i].y, linePoints[i + 1].x, linePoints[i + 1].y);
                }
            }
            else  //if the line which the ball is colliding with is water
            {
                // if the cannon ball is collided with the line
                if (CollisionCalculation.isCircleCollidesLine(linePoints[i].x, linePoints[i].y, linePoints[i + 1].x, linePoints[i + 1].y, ballObject.transform.position.x, ballObject.transform.position.y, ball.getRadius()))
                {
                    //handle the collision on water
                    disappearAfterWaterCollision(ball, cannonBallsList);
                }
            }
        }
    }
 //function for the disappearing solution of collison on water
 void disappearAfterWaterCollision(CannonBall ball, ArrayList ballList)
 {
     //when fall in water, remove the ball from the ball list and destroy it
     ballList.Remove(ball);
     Destroy(ball.GetGameObject());
 }
    //this function will handle the collision between cannon ball and any ballon body
    void handleBalloonCollision(CannonBall cb, ArrayList balloonList)
    {
        //vectors that store the position of points that construct the balloons
        Vector3[] bodyPositions;
        Vector3[] stringPositions;
        //get every ballon as line segment
        for (int k = 0; k < balloonsList.Count; k++)
        {
            bodyPositions   = ((Balloon)balloonsList[k]).getBodyLinePositions();
            stringPositions = ((Balloon)balloonsList[k]).getStringLinePositions();

            //iterate through the Points to check if the cannon ball collided any line segment of the balloon string
            for (int i = 0; i < stringPositions.Length - 1; i++)
            {
                // if the cannon ball is collided with the line segment of a balloon string
                if (CollisionCalculation.isCircleCollidesLine(stringPositions[i].x, stringPositions[i].y, stringPositions[i + 1].x, stringPositions[i + 1].y, cb.GetGameObject().transform.position.x, cb.GetGameObject().transform.position.y, cb.getRadius()))
                {
                    //handle the collision by moving the string to avoid intersecting with the cannon ball
                    movingAfterCannonBallCollision(cb, ((Balloon)balloonsList[k]), stringPositions[i], stringPositions[i + 1]);
                }
            }

            //iterate through the Points to check if the cannon ball collided any line segment of the balloon body
            for (int i = 0; i < bodyPositions.Length - 1; i++)
            {
                // if the cannon ball is collided with the line segment of a balloon body
                if (CollisionCalculation.isCircleCollidesLine(bodyPositions[i].x, bodyPositions[i].y, bodyPositions[i + 1].x, bodyPositions[i + 1].y, cb.GetGameObject().transform.position.x, cb.GetGameObject().transform.position.y, cb.getRadius()))
                {
                    //handle the collision by destroy the balloon which has been collided
                    destroyAfterCannonBallCollision(((Balloon)balloonsList[k]), balloonList);

                    break; //break since the balloon with current positions array is destroyed, so no further check has to be made
                }
            }
        }
    }