javascript - Circle/rectangle collision response -
so built time ago little breakout clone, , wanted upgrade little bit, collisions. when first made had basic "collision" detection between ball , brick, in fact considered ball rectangle. created issue edge collisions, thought change it. thing is, found answers problem: example image ball_deflection.jpeg , last comment of thread : circle/rect collision reaction not find how compute final velocity vector.
so far have :
- found closest point on rectangle,
- created normal , tangent vectors,
and need somehow "divide velocity vector normal component , tangent component; negate normal component , add normal , tangent components new velocity vector" i'm sorry if seems terribly easy not mind around ... code :
function collision(rect, circle){ var nearestx = max(rect.x, min(circle.pos.x, rect.x + rect.w)); var nearesty = max(rect.y, min(circle.pos.y, rect.y + rect.w)); var dist = createvector(circle.pos.x - nearestx, circle.pos.y - nearesty); var dnormal = createvector(- dist.y, dist.x); //change current circle vel according collision response }
thanks !
edit: found this didn't know if applicable @ points of rectangle or corners.
best explained couple of diagrams:
have angle of incidence = angle of reflection. call value θ.
have θ = normal angle - incoming angle.
atan2 function computing angle of vector positive x-axis.
then code below follows:
function collision(rect, circle){ var nearestx = max(rect.x, min(circle.pos.x, rect.x + rect.w)); var nearesty = max(rect.y, min(circle.pos.y, rect.y + rect.h)); var dist = createvector(circle.pos.x - nearestx, circle.pos.y - nearesty); var dnormal = createvector(- dist.y, dist.x); var normal_angle = atan2(dnormal.y, dnormal.x); var incoming_angle = atan2(circle.vel.y, circle.vel.x); var theta = normal_angle - incoming_angle; circle.vel = circle.vel.rotate(2*theta); }
another way of doing velocity along tangent , subtracting twice value circle velocity.
then code becomes
function collision(rect, circle){ var nearestx = max(rect.x, min(circle.pos.x, rect.x + rect.w)); var nearesty = max(rect.y, min(circle.pos.y, rect.y + rect.h)); var dist = createvector(circle.pos.x - nearestx, circle.pos.y - nearesty); var tangent_vel = dist.normalize().dot(circle.vel); circle.vel = circle.vel.sub(tangent_vel.mult(2)); }
both of code snippets above same thing in same time (probably). pick whichever 1 best understand.
also, @arbuthnott pointed out, there's copy-paste error in nearesty
should use rect.h
instead of rect.w
.
edit: forgot positional resolution. process of moving 2 physics objects apart they're no longer intersecting. in case, since block static, need move ball.
function collision(rect, circle){ var nearestx = max(rect.x, min(circle.pos.x, rect.x + rect.w)); var nearesty = max(rect.y, min(circle.pos.y, rect.y + rect.h)); var dist = createvector(circle.pos.x - nearestx, circle.pos.y - nearesty); if (circle.vel.dot(dist) < 0) { //if circle moving toward rect //update circle.vel using 1 of above methods } var penetrationdepth = circle.r - dist.mag(); var penetrationvector = dist.normalise().mult(penetrationdepth); circle.pos = circle.pos.sub(penetrationvector); }
Comments
Post a Comment