Let’s Bounce! or Physics of Collisions Part 1 Games Fundamentals © by Jarek Francik Kingston University, London
What’s on the Agenda? Collisions: Elastic vs. Inelastic Essential Physics: Momentum, Impulse, Kinematic Energy, Conservation Rules Perfectly Inelastic Collision Elastic Collisions –Collision with a Stationary Object –Collision between Bills Coefficient of Restitution Implementation Remarks
Elastic vs. Inelastic Collisions Physicists classify collisions as: –perfectly inelastic: –perfectly elastic:
Elastic vs. Inelastic Collisions Real collisions are neither perfectly elastic nor inelastic: they are somewhere in-between Marbles, bills and many other hard objects may be quite well simulated as perfectly elastic collisions
Elastic Collisions Equal mass marbles exchange their velocities: v‘ A = v B v’ B = v A
Elastic Collisions Maths behind the marbles of different mass is a bit more complex
Elastic Collisions But hitting a stationary obstacle, again, is very simple: v’ = -v
Essential Physics
Momentum, Impulse, Energy Momentum m – mass v – velocity Impulse Kinematic Energy
2 nd Newton’s Law Two equivalent formulas: F = am F = p / t = J / t J = Ft this is how it is widely known today this is what Isaac Newton originally wrote
Conservation of Momentum F1 = -F2(3rd Newton’s law) p 1 / t = p 2 / t p 1 = p 2
Conservation of Energy In an Isolated System ENERGY is constant but may be converted, for example into heat Only perfectly elastic collisions conserve the Kinematic Energy. In all real collisions part of Kinematic Energy is lost as colliding objects become hot.
Physics of Perfectly Inelastic Collision
Perfectly Inelastic Collision before the collision: applying momentum conservation: after the collision:
Physics of Perfectly Elastic Collision
Perfectly Elastic Collision
applying momentum conservation: after the collision: before the collision:
Elastic collision Two unknown velocities Momentum equation is not enough, we need something more! Definition: Elastic colision is a colision in which the kinematic energy is conserved
Elastic collision
Elastic collision of equal masses source:
Elastic Collisions collision with a stationary object: marbles bouncing from the walls bills bouncing from each other : billiard (or snooker) game
Collision with a Stationary Object
x’ v y’ v v’ Collision with a Stationary Object xvxv yvyv v vv’
Collision with a Stationary Object x’ v y’ v v’ xvxv yvyv v NOTICE: CHANGE OF SYMBOLS
Collision with a Stationary Object v’ v’ || v’ vv v || v xvxv x’ v yvyv y’ v n c n: normal vector c: collision vector
n c Collision with a Stationary Object v’ v’ || v’ vv v || v xvxv x’ v yvyv y’ v n: normal vector c: collision vector
Collision with a Stationary Object v’ v’ || v’ vv v xvxv x’ v yvyv y’ v n v || c
Collision with a Stationary Object
double xv = ball.GetXVelocity(); double yv = ball.GetYVelocity(); double xn = sin(DEG2RAD(obj.GetRotation())); double yn = cos(DEG2RAD(obj.GetRotation())); double xc = -yn; double yc = xn; double vdotn = xv * xn + yv * yn; double vdotc = xv * xc + yv * yc; ball.SetVelocity(xc * vdotc - xn * vdotn, yc * vdotc - yn * vdotn);
Physics of the Billiard/Snooker Game
Billiard Game t v c n vv v ||
Billiard Game // distance vector (t) and radius double xt = ball2.GetPrecX() - ball1.GetPrecX(); double yt = ball2.GetPrecY() - ball1.GetPrecY(); double R = ball1.GetWidth(); // normal and collision vectors double xn = xt / 2 / R; double yn = yt / 2 / R; double xc = -yn; double yc = xn; // velocity vectors double xv1 = ball1.GetXVelocity(); double yv1 = -ball1.GetYVelocity(); double xv2 = ball2.GetXVelocity(); double yv2 = -ball2.GetYVelocity(); // dot products double v1dotn = xv1 * xn + yv1 * yn; double v1dotc = xv1 * xc + yv1 * yc; double v2dotn = xv2 * xn + yv2 * yn; double v2dotc = xv2 * xc + yv2 * yc; ball1.SetVelocity(xn * v2dotn + xc * v1dotc, -(yn * v2dotn + yc * v1dotc)); ball2.SetVelocity(xn * v1dotn + xc * v2dotc, -(yn * v1dotn + yc * v2dotc));
Billiard Game Life Demo
Coefficient of Restitution
General Case Newton’s Law of Restitution e – coefficient of restitution Notice that we use relative velocity and relative normal velocity:
Implementation Remarks 1.Ball Sinking 2. Bouncing & Sinking: a simple solution for balls and boxes
Ball Sinking in the Floor In the real world: beforehit!after
Ball Sinking in the Floor In the simulated world: beforehit!after
Ball Sinking in the Floor or even a worse scenario: beforehit!after WRONG Bounce condition may be wrongly detected! SOLUTION: only bounce when moving DOWN
Ball Sinking in the Floor General solution: only apply the bounce if v n > 0 v n
Ball Sinking in Another Ball
In the real world: beforehit!after
Ball Sinking in Another Ball In the simulated world: beforehit!after
Ball Sinking in Another Ball In the nasty case: #1#2#3 In frame #3 the balls still overlap. This may lead to repeated application of the ‘bounce’ effect. The balls may end up ‘glued’!
Ball Sinking in Another Ball In the nasty case: no collision yet frame #1
Ball Sinking in Another Ball In the nasty case: collision detected frame #2
Ball Sinking in Another Ball In the nasty case: collision detected bouncing applied frame #2
Ball Sinking in Another Ball In the nasty case: collision detected (again!) frame #3
Ball Sinking in Another Ball In the nasty case: collision detected (again!) bouncing applied frame #3 WRONG
Ball Sinking in Another Ball Solution: Take: -t: position vector (of the other ball) -v: velocity vector if (v ∙ t < 0) don’t bounce! frame #3 t v
Ball Sinking in Another Ball Solution: frame #3 Take: -t: position vector (of the other ball) -v: velocity vector if (v ∙ t < 0) don’t bounce! // distance vector (t) and radius double xt = ball2.GetPrecX() - ball1.GetPrecX(); double yt = ball2.GetPrecY() - ball1.GetPrecY(); double R = ball1.GetWidth(); // normal and collision vectors double xn = xt / 2 / R; double yn = yt / 2 / R; double xc = -yn; double yc = xn; // velocity vectors double xv1 = ball1.GetXVelocity(); double yv1 = -ball1.GetYVelocity(); double xv2 = ball2.GetXVelocity(); double yv2 = -ball2.GetYVelocity(); // dot products double v1dotn = xv1 * xn + yv1 * yn; double v1dotc = xv1 * xc + yv1 * yc; double v2dotn = xv2 * xn + yv2 * yn; double v2dotc = xv2 * xc + yv2 * yc; ball1.SetVelocity(xn * v2dotn + xc * v1dotc, -(yn * v2dotn + yc * v1dotc)); ball2.SetVelocity(xn * v1dotn + xc * v2dotc, -(yn * v1dotn + yc * v2dotc)); t v
Ball Sinking in Another Ball Solution: frame #3 Take: -t: position vector (of the other ball) -v: velocity vector if (v ∙ t < 0) don’t bounce! // distance vector (t) and radius double xt = ball2.GetPrecX() - ball1.GetPrecX(); double yt = ball2.GetPrecY() - ball1.GetPrecY(); double R = ball1.GetWidth(); // normal and collision vectors double xn = xt / 2 / R; double yn = yt / 2 / R; double xc = -yn; double yc = xn; // velocity vectors double xv1 = ball1.GetXVelocity(); double yv1 = -ball1.GetYVelocity(); double xv2 = ball2.GetXVelocity(); double yv2 = -ball2.GetYVelocity(); // check velocity dot position double vx = xv1 - xv2; double vy = yv1 - yv2; if (vx * xt + vy * yt < 0) return; // dot products double v1dotn = xv1 * xn + yv1 * yn; double v1dotc = xv1 * xc + yv1 * yc; double v2dotn = xv2 * xn + yv2 * yn; double v2dotc = xv2 * xc + yv2 * yc; ball1.SetVelocity(xn * v2dotn + xc * v1dotc, -(yn * v2dotn + yc * v1dotc)); ball2.SetVelocity(xn * v1dotn + xc * v2dotc, -(yn * v1dotn + yc * v2dotc)); t v
Bouncing from boxes and walls is quite common in games – simple and advanced a scene from the Marble, a workshop task for today... Bouncing & Sinking: a simple solution for balls & boxes
GFC offers an effective hit test function for rectangular sprites against circular shapes, for which position and radius are known: rect.HitTest(pos, radius); Bouncing & Sinking: a simple solution for balls & boxes
Problem: when the ball is overlapping the box it is too late to determine which side it entered (why?) Bouncing & Sinking: a simple solution for balls & boxes
Solution: track the previous frame position. Bouncing & Sinking: a simple solution for balls & boxes
Example: the ball is hitting the left hand edge of the box if: –there is a hit in frame #n –it was to the left of the box in frame #n-1 Bouncing & Sinking: a simple solution for balls & boxes
Solution Draft: 1.Store in a safe place the position of the ball before the update. This should be the position after the previous frame, before the current one – (x 0, y 0 ) 2.Just after update, check the HitTest. If there is no collision there is no bounce. 3.Now, when we know there is a hit: Assume there was no hit with (x 0, y 0 )* Check on which side of the box the ball was (in the prev frame) Apply the appropriate bounce Amend the position of the ball so that to prevent sinking * this assumption will be satisfied if you prevent sinking! Bouncing & Sinking: a simple solution for balls & boxes
Here is the solution: 1.Store in a safe place the position of the ball before the update. This should be the position after the previous frame, before the current one – (x 0, y 0 ) 2.Just after update, check the HitTest. If there is no collision there is no bounce. 3.Now, when we know there is a hit: Assume there was no hit with (x 0, y 0 )*. Check on which side of the box the ball was. Apply the appropriate bounce. Amend the position of the ball so that to prevent sinking. * this assumption will be satisfied if you prevent sinking! let’s have a look at this point in greater detail... Bouncing & Sinking: a simple solution for balls & boxes
Decompose ball’s velocity into v x and v y if v x > 0 the ball was travelling rightwards and we only check the left side of the box if v x < 0 the ball was travelling leftwards and we only check the right side of the box if v y > 0 the ball was travelling upwards and we only check the bottom side of the box if v y < 0 the ball was travelling downwards and we only check the upper side of the box Bouncing & Sinking: a simple solution for balls & boxes
Decompose ball’s velocity into v x and v y if v x > 0 the ball was travelling rightwards and we only check the left side of the box if v x < 0 the ball was travelling rightwards and we only check the left side of the box if v y > 0 the ball was travelling upwards and we only check the bottom side of the box if v y < 0 the ball was travelling downwards and we only check the upper side of the box Bouncing & Sinking: a simple solution for balls & boxes
Decompose ball’s velocity into v x and v y if v x > 0 the ball was travelling rightwards and we only check the left side of the box if (vx > 0 && x0 + r GetLeft()) { vx *= -damp;// bounce with damping x1 = pWall->GetLeft() - r;// amend the position // (to prevent sinking) } // Repeat for remaining three sides... // and, finally, apply all the changes theBall.SetVelocity(vx, vy); theBall.SetPosition(x1, y1); Bouncing & Sinking: a simple solution for balls & boxes