Projectile bouncing off curved surface - Pygame, Python 3 -
i working on (top-down) game requires code bounce projectile off of circular surface.
the way work when projectile hits surface
a hypothetical line drawn center of circle
which used normal calculate angle of reflection of new trajectory.
physics (such gravity) unnecessary. there more or less simple way of doing that?
reflect line segment off circle.
this reflexed line segment off circle. length of reflected line segment , incoming line segment circle intercept equal length of original line segment. if want reflected ray stop calculations when reflected vector has been worked out. assumes incoming line segment starts outside circle. if line starts inside line fails. can check if line starts inside circle getting distance circle center line start if less circle radius line starts inside circle.
this in pseudo code don't php. sqrt() function sqrt of number.
the incoming ray line segment. line.x1, line.y1 start , x2,y2 end
line x1,y1,x2,y2
the circle x,y position , r radius
circle x,y,r
first need line segment circle intercept if any. find closest point on line circle center , see if distance point circle center less circle radius.if line segment might intercept. if distance greater there no intercept.
convert line segment vector
vx = line.x2 - line.x1; vy = line.y2 - line.y1;
get length of line segment squared
len2 = (vx * vx + vy * vy);
get normalised distance start of line point closest circle center
unitdist = ((circle.x - x1) * vx + (circle.y - y1) * vy) / len2;
then using normalised distance point closest circle in absolute position.
x = x1 + vx * unitdist; y = y1 + vy * unitdist;
now distance point circle center
dist = sqrt((x - circle.x)*(x - circle.x)+ (y - circle.y)*(y - circle.y));
if distance less circle radius there possibility of intercept. if not there no intercept exit there no reflection.
if( dist > circle.r) exit;
now know line intercept circle, need check if line segment intercepts, find intercept point towards line start , see if point on line segment or not.
thus closest point on line circle center length `dist' worked out out there intercept point length circle.r , distance closest point unknown, know triangle 3 lengths make right triangle missing side
lentointercept = sqrt(circle.r * circle.r - dist * dist);
this gives distance closest point on line circle center, along line toward start intercept point. convenience convert distance unit scaled distance (normalised) dividing length of line segment
lentointercept = lentointercept / sqrt(len2)
subtract normalised length normalised distance start of incoming line closest point on line circle center.
unitdist = unitdist - lentointercept;
if new unitdist intercept point >= 0 , <= 1 know line segment has intercepted circle, otherwise the line segment has not intercepted circle , can exit.
if(unitdist < 0 or unitdist > 1) exit; // no intercept
now can calculate absolute position of intercept point adding vector multiplied normalised distance start of incoming line intercept point
x = line.x1 + unitdist * vx; y = line.y1 + unitdist * vy;
now can work out reflection.
get vector circle center intercept point
cx = x - circle.x; cy = y - circle.y;
we need tangent make calculations easier tangent rotating clockwise 90 deg
tx = -cy; ty = cx;
normalise tangent vector. know same length circle radius because rotated line circle center intercept point can normalise tangent vector using circle radius
tx = tx / circle.r; ty = ty / circle.r;
we need normalise incoming line vector divide length
vx = vx / sqrt(len2); vy = vy / sqrt(len2);
now dot product of tangent , line seg. distance incoming vector end tangent line, squared
dot = vx * tx + vy * ty;
double because want reflection on other side of tangent line.
dot = dot * 2;
now lengthen normalised tangent vector dot amount
tx = tx * dot; ty = ty * dot;
and subtract incoming line vector give vector of outgoing line
reflectedx = tx - vx; reflectedy = ty - vy;
normalise vector getting length
lengr = sqrt(reflectedx * reflectedx + reflectedy * reflectedy);
and dividing reflected line length
reflectedx = reflectedx / lengr; reflectedy = reflectedy / lengr;
now calculate reflected part of line distance form circle intercept point end of incoming line. have normalised distance along line intercept point remaining distance
remaindist = 1-unitdist;
multiply normalised distance incoming line length
remaindist = remaindist * sqrt(len2);
now multiply reflected normalised vector length
reflectedx = reflectedx * remaindist; reflectedy = reflectedy * remaindist;
a lastly create new reflected line segment line intercept point point plus reflected vector
reflectedline.x1 = x; reflectedline.y1 = y; reflectedline.x2 = x + reflectedx; reflectedline.y2 = y + reflectedy;
Comments
Post a Comment