Last active
April 21, 2017 19:32
-
-
Save exerro/4d08fa273abf69262cbe3c4e239b4ffa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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