40 lines
1.9 KiB
Python
40 lines
1.9 KiB
Python
def collide2d(a, b, e):
|
|
"""Returns the velocities of balls a and b after collision.
|
|
|
|
e is the *coefficient of restitution*, a parameter between 0 and 1
|
|
which determines how much the objects bounce off each other.
|
|
When e is 0, the two objects completely stick together.
|
|
When e is 1, the two objects bounce off each other completely.
|
|
|
|
This is a 2-dimensional collision because a and b each have a 2d
|
|
velocity vector, like two balls moving on a plane. We can separate
|
|
each velocity vector into two components: a normal vector (pointed
|
|
straight at the other ball) and a tangent vector (perpendicular to
|
|
the normal). The tangent vectors don't participate in the collision
|
|
at all, so we just need to calculate how the normal vectors change
|
|
after the collision. This is easier, since it's a 1-dimensional
|
|
collision.
|
|
|
|
Afterwards we combine the updated normal vector with the tangent
|
|
vector to get the resulting velocity vector for each ball.
|
|
"""
|
|
a_to_b = b.position - a.position
|
|
av_normal = a.velocity.project(a_to_b)
|
|
av_tangent = a.velocity - av_normal
|
|
bv_normal = b.velocity.project(-a_to_b)
|
|
bv_tangent = b.velocity - bv_normal
|
|
av_normal_after, bv_normal_after = collide1d(av_normal, a.mass, bv_normal, b.mass, e)
|
|
av_after = av_normal_after + av_tangent
|
|
bv_after = bv_normal_after + bv_tangent
|
|
return av_after, bv_after
|
|
|
|
def collide1d(av, am, bv, bm, e):
|
|
"""Returns the velicoties of a and b after a 1-dimensional collision,
|
|
where a and b are headed directly at each other. This formula is from Wikipedia:
|
|
https://en.wikipedia.org/wiki/Elastic_collision#One-dimensional_Newtonian
|
|
"""
|
|
velocity_center_of_mass = (av * am + bv * bm) / (am + bm)
|
|
av_after = velocity_center_of_mass * (1 + e) - av * e
|
|
bv_after = velocity_center_of_mass * (1 + e) - bv * e
|
|
return av_after, bv_after
|