//function for changing the string motion after it's collided with cannon ball (the string shouldn't intersect will cannon ball)
    //the paramters are the cannon ball and the balloon whose string is collided with, and also the position of the two end of the line segment of the string
    void movingAfterCannonBallCollision(CannonBall ball, Balloon balloon, Vector3 startPoint, Vector3 endPoint)
    {
        //find the 2 Point objects of the balloon string according to the startPoint and endPoint
        //Balloon.Point point1 = null;
        Balloon.Point point2    = null;
        ArrayList     strPoints = balloon.getStringPoints();

        for (int i = 0; i < strPoints.Count; i++)
        {
            /*
             * if( ((Balloon.Point) strPoints[i]).getPosition().Equals(startPoint))
             * {
             *  point1 = (Balloon.Point) strPoints[i];
             * }*/
            if (((Balloon.Point)strPoints[i]).getPosition().Equals(endPoint))
            {
                point2 = (Balloon.Point)strPoints[i];
            }
        }


        Vector2 unitNormal = CollisionCalculation.getNormal(startPoint.x, startPoint.y, point2.getPosition().x, point2.getPosition().y); //calculate the unit normal of the line
        float   epsilon    = 0.1f;                                                                                                       //the coefficient of restitution (0~1, when it's 1 we have perfect bouncing)
        float   mass       = 1f;                                                                                                         //mass of the string

        float VnCollided = unitNormal.x * ball.getVelocity().x + unitNormal.y * ball.getVelocity().y;                                    //Vn-: the normal component of collided velocity = dot product of normal and velocity

        float   j       = -(1 + epsilon) * mass * VnCollided;                                                                            //the impulse scalar j = -(1+epsilon) * m * Vn-
        Vector2 impulse = -j * unitNormal;                                                                                               //the force will apply to the line, not the cannon ball, so we use negative of the impulse

        point2.setAcceleration((impulse / mass));                                                                                        //update the acceleration based on the impulse
    }
    //function for changing the balloon point motion after it's collided with line (the balloon Point shouldn't intersect will terrain)
    //the paramters are the balloon and the points of a line which the balloon is collided with, and also the position of the two end of the line segment
    void movingAfterLineCollision(Balloon balloon, Vector3 collidedPoint, Vector3 lineStart, Vector3 lineEnd)
    {
        //find the 2 Point objects of the balloon string according to the startPoint and endPoint
        //Balloon.Point point1 = null;
        Balloon.Point cPoint     = null;
        ArrayList     strPoints  = balloon.getStringPoints();
        ArrayList     bodyPoints = balloon.getBodyPoints();

        //iterate to find the contact point
        for (int i = 0; i < strPoints.Count; i++)
        {
            if (((Balloon.Point)strPoints[i]).getPosition().Equals(collidedPoint))
            {
                cPoint = (Balloon.Point)strPoints[i];
            }
        }
        for (int i = 0; i < bodyPoints.Count; i++)
        {
            if (((Balloon.Point)bodyPoints[i]).getPosition().Equals(collidedPoint))
            {
                cPoint = (Balloon.Point)bodyPoints[i];
            }
        }


        Vector2 unitNormal = CollisionCalculation.getNormal(lineStart.x, lineStart.y, lineEnd.x, lineEnd.y);            //calculate the unit normal of the line segment
        float   epsilon    = 1f;                                                                                        //the coefficient of restitution (0~1, when it's 1 we have perfect bouncing)
        float   mass       = 0.1f;                                                                                      //mass of the string

        float VnCollided = unitNormal.x * cPoint.getMovingDirection().x + unitNormal.y * cPoint.getMovingDirection().y; //Vn-: the normal component of collided velocity = dot product of normal and velocity
        float multiplier = 30f;

        float   j       = -(1 + epsilon) * mass * -VnCollided * multiplier; //the impulse scalar j = -(1+epsilon) * m * Vn-
        Vector2 impulse = -j * unitNormal;                                  //the force will apply to the line, not the cannon ball, so we use negative of the impulse

        foreach (Balloon.Point p in bodyPoints)
        {
            p.setAcceleration((impulse / mass));  //update the acceleration based on the impulse
        }
        foreach (Balloon.Point p in strPoints)
        {
            p.setAcceleration((impulse / mass));  //update the acceleration based on the impulse
        }

        //cPoint.setAcceleration((impulse / mass));  //update the acceleration based on the impulse
    }
    //function for the bouncing solution of collison, taking a ball and a line represented by two points
    //as parameters
    void bouncingAfterTerrainCollision(CannonBall ball, float x1, float y1, float x2, float y2)
    {
        //calculate bouncing velocity using the formula V+ = V- + dotProduct(j,n)/m,
        //where V- is the velocity when colliding, V+ is the velocity after colliding,
        //dotProduct(j,n) = J which is the impulse, and j = -(1+epsilon) * m * Vn- where
        //Vn- = dotProduct(V-,n).

        Vector2 unitNormal = CollisionCalculation.getNormal(x1, y1, x2, y2);                          //calculate the unit normal of the line
        float   epsilon    = 0.55f;                                                                   //the coefficient of restitution (0~1, when it's 1 we have perfect bouncing)
        float   mass       = 1f;                                                                      //mass of the ball

        float VnCollided = unitNormal.x * ball.getVelocity().x + unitNormal.y * ball.getVelocity().y; //Vn-: the normal component of collided velocity = dot product of normal and velocity

        float   j       = -(1 + epsilon) * mass * VnCollided;                                         //the impulse scalar j = -(1+epsilon) * m * Vn-
        Vector2 impulse = j * unitNormal;                                                             //J

        ball.addVelocity(impulse / mass);                                                             //update the velocity based on the impulse (V+ = V- + impulse/mass)
    }
    //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);
                }
            }
        }
    }