//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 the friction on the horizontal ground void applyFrictionOfGround(CannonBall ball) { //use a friction coefficient to decelerate the ball float frictionCoeff = 0.95f; ball.addVelocity(new Vector2(-ball.getVelocity().x *(1 - frictionCoeff), 0)); }
//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 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()); } }