Skip to content

Instantly share code, notes, and snippets.

@exerro
Last active April 21, 2017 19:32
Show Gist options
  • Save exerro/4d08fa273abf69262cbe3c4e239b4ffa to your computer and use it in GitHub Desktop.
Save exerro/4d08fa273abf69262cbe3c4e239b4ffa to your computer and use it in GitHub Desktop.
local diff = e1.position:sub( e2.position );
local dist = diff:len();
local radius = e1.shape.radius + e2.shape.radius;
if dist < radius then
return Collision( e1, e2, radius - dist, diff:div( dist ) )
end
function World:resolve_collision( collision )
local entity1 = collision.entity1
local entity2 = collision.entity2
local mass1 = entity1:get_mass()
local mass2 = entity2:get_mass()
local restitution = max( entity1.material.restitution, entity2.material.restitution ) -- coef of restitution
local friction = max( entity1.material.friction, entity2.material.friction ) -- coef of friction
local static_body = Body.Static
local normal = collision.normal
local position1, velocity1 = collision.position1, collision.velocity1
local position2, velocity2 = collision.position2, collision.velocity2
if entity2.body == static_body then
entity1, entity2 = entity2, entity1
position1, position2 = position2, position1
velocity1, velocity2 = velocity2, velocity1
normal = -normal
end
-- resolve position instantaneously
if (entity1.body == Body.Static) then
entity2.position = entity2.position - normal * collision.penetration
self:clip_entity( entity2 )
else
local masst = mass1 + mass2
local res1 = entity2.body == Body.Static and 1 or entity1.body == Body.Static and 0 or mass2 / masst -- scaling factor of effect on each entity's instantaneous movement
local res2 = entity1.body == Body.Static and 1 or entity2.body == Body.Static and 0 or mass1 / masst
local nx, ny = normal.x, normal.y
local e1p, e2p = position1, position2
local e1x, e1y = e1p.x, e1p.y
local e2x, e2y = e2p.x, e2p.y
local rs1, rs2 = collision.penetration * res1, collision.penetration * res2
entity1.position = entity1.position + Vec2( nx * rs1, ny * rs1 ) -- entity1.position:add( normal:mul( collision.penetration * res1 ) )
entity2.position = entity2.position - Vec2( nx * rs2, ny * rs2 ) -- entity2.position:sub( normal:mul( collision.penetration * res2 ) )
self:clip_entity( entity1 )
self:clip_entity( entity2 )
end
-- apply restitution
if (entity1.body == Body.Static) then
entity2.velocity = entity2.velocity:sub( normal:mul( velocity2:dot( normal ) * (1 + restitution) ) )
else
local e1v, e2v = velocity1, velocity2
local u1 = e1v:dot( normal ) -- initial speed of e1 -> e2
local u2 = e2v:dot( normal ) -- initial speed of e2 -> e1
local im = u1*mass1 + u2*mass2 -- initial momentum
local app = u2 - u1 -- speed of approach
-- e = sep / app => sep = e * app (where e is restitution)
local sep = restitution * app
-- (1) sep = v1 - v2 => v1 = sep + v2
-- assuming elastic collision => conservation of momentum
-- (2) m1*v1 + m2*v2 = m1*u1 + m2*u2 = im
-- substituting (1) into (2)
-- (3) m1*sep + m1*v2 + m2*v2 = im
-- ... v2(m2 + m1) = im - m1*sep
-- ... v2 = (im - m1*sep) / (m2 + m1)
local v2 = (im - mass1*sep) / (mass2 + mass1)
local v1 = sep + v2
local d1 = u1 - v1
local d2 = u2 - v2
entity1.velocity = entity1.velocity - Vec2( normal.x * d1, normal.y * d1 ) -- entity1.velocity:sub( normal:mul( u1 - v1 ) )
entity2.velocity = entity2.velocity - Vec2( normal.x * d2, normal.y * d2 ) -- entity2.velocity:sub( normal:mul( u2 - v2 ) )
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment