// S. Ramachandran, January 1994 // Revised by Scott Haug, February 1994 // These procedures and code fragments perform calculations of the new // puck velocity after a collision between the puck and the paddle. // puck and paddle data structures (examples only): PGtuple (Position) { PGreal x,y ; FIELDS (Position, member (x); member (y);); }; typedef struct { Position center; struct { double vi,vj; // components of velocity along X and Y axes } velocity; } circle; circle *puck, *paddle; // This function computes the velocity of the puck after a collision // with a paddle. // Assumptions: The paddle is assumed to be stationary and of infinite mass. // Since the field is assumed frictionless and the puck moves with uniform // velocity only the components of the puck's velocity change while the // magnitude of the velocity remains constant. void ChangeVelocity(Circle *puck,Circle *paddle) // Refer to the diagram (class handout) showing collision between the puck // and the paddle. The formula for calculating value of the angle that // the puck makes with the X and Y axes after the collision holds true // only for the case shown in the diagram. The paddle center is taken to // be the origin of the coordinate axis. // The function checks the position of the puck relative to the paddle // and transforms the puck position and velocity to the position shown // in the diagram. Two multiplying constants " xmultiplier" and // "ymultiplier" are used for transformation (which is linear). // After calculating the new angle as shown in the diagram the new // velocity components are calculated and the inverse transformation // is applied to get the actual values. // The inverse transformation consists simply of multiplying the // components with the corresponding multiplier. { float xcomp, ycomp ; // components of the velocity along X and y axes float xdist, ydist ; // x and y distance of the puck and paddle float val ; // magnitude of puck velocity float alpha ; // angle of the velocity vector float theta ; // angle created by the distance between paddle and puck float result ; // resultant vector of the deflecting puck int xmultiplier=1,ymultiplier=1; // transformation constants // Calculate the multipliers needed to transform the puck // to the position shown in the diagram // If puck is to the left of the paddle, move it to the right of the paddle. if (puck->center.x < paddle->center.x) xmultiplier = -1; // If puck is above the paddle, move it below the paddle. if (puck->center.y < paddle->center.y) ymultiplier = -1; //determine the x and y distances xdist = fabs(puck->center.x - paddle->center.x); ydist = fabs(puck->center.y - paddle->center.y); // transform the puck velocity xcomp = puck->velocity.vi*xmultiplier; ycomp = puck->velocity.vj*ymultiplier; val = sqrt(xcomp*xcomp + ycomp*ycomp); // get velocity and distance angles alpha = atan(ycomp/xcomp); theta = atan(ydist/xdist); //determine resultant angle of deflecting puck result = pi - 2*alpha - theta; // compute the actual velocity components by multiplying // with the corresponding multipliers. puck->velocity.vi = xmultiplier*fabs(val*cos(result)); puck->velocity.vj = ymultiplier*fabs(val*sin(result)); } float GetDistBetCenters(Circle *puck,Circle* paddle) { double t; t = pow((paddle->center.x - puck->center.x),2); t += pow((paddle->center.y - puck->center.y),2); return fabs(sqrt(t)); } // Use this code in the function which checks for collisions // between puck and paddle. // If the distance between the centers of two circles is less than the // sum of their radii then they intersect. // If the puck and paddle intersect then call ChangeVelocity() // to calculate the new velocity of the puck. if ( GetDistBetCenters(puck,p1) <= puck->radius + p1->radius ) { ChangeVelocity(puck,p1) ; return 1 ; } if ( GetDistBetCenters(puck,p2) <= puck->radius + p2->radius ) { ChangeVelocity(puck,p2) ; return 1 ; }