feat: basic impulse resolving for 2D collisions

This commit is contained in:
2026-04-03 21:41:32 +03:00
parent a47f8e4944
commit 4c13578125

View File

@@ -6,8 +6,6 @@ public class CollisionResolver2D : ICollisionResolver2D
{ {
public void Resolve(CollisionDetectionInformation collisionInformation) public void Resolve(CollisionDetectionInformation collisionInformation)
{ {
Vector2D displacementVector = collisionInformation.Normal * collisionInformation.Penetration;
ICollider2D left = collisionInformation.Detector; ICollider2D left = collisionInformation.Detector;
ICollider2D right = collisionInformation.Detected; ICollider2D right = collisionInformation.Detected;
@@ -17,6 +15,20 @@ public class CollisionResolver2D : ICollisionResolver2D
if (isLeftStatic && isRightStatic) if (isLeftStatic && isRightStatic)
return; return;
Displace(collisionInformation, left, right, isLeftStatic, isRightStatic);
Bounce(collisionInformation, left, right, isLeftStatic, isRightStatic);
left.Recalculate();
right.Recalculate();
left.Resolve(collisionInformation);
right.Resolve(collisionInformation);
}
private static void Displace(CollisionDetectionInformation collisionInformation, ICollider2D left, ICollider2D right, bool isLeftStatic, bool isRightStatic)
{
Vector2D displacementVector = collisionInformation.Normal * collisionInformation.Penetration;
if (isLeftStatic) if (isLeftStatic)
right.Transform.Position += displacementVector; right.Transform.Position += displacementVector;
else if (isRightStatic) else if (isRightStatic)
@@ -33,11 +45,32 @@ public class CollisionResolver2D : ICollisionResolver2D
right.Transform.Position += leftMomentumPercentage * displacementVector; right.Transform.Position += leftMomentumPercentage * displacementVector;
left.Transform.Position -= rightMomentumPercentage * displacementVector; left.Transform.Position -= rightMomentumPercentage * displacementVector;
} }
}
left.Recalculate(); private static void Bounce(CollisionDetectionInformation collisionInformation, ICollider2D left, ICollider2D right, bool isLeftStatic, bool isRightStatic)
right.Recalculate(); {
Vector2D leftVelocity = left.RigidBody2D?.Velocity ?? Vector2D.Zero;
Vector2D rightVelocity = right.RigidBody2D?.Velocity ?? Vector2D.Zero;
left.Resolve(collisionInformation); Vector2D relativeVelocity = leftVelocity - rightVelocity;
right.Resolve(collisionInformation); float velocityAlongNormal = Vector2D.Dot(relativeVelocity, collisionInformation.Normal);
if (velocityAlongNormal > 0)
{
collisionInformation = collisionInformation.Reverse();
velocityAlongNormal = -velocityAlongNormal;
}
float e = (left.RigidBody2D?.Material.Restitution ?? 0f).Add(right.RigidBody2D?.Material.Restitution ?? 0f).Divide(2f);
float leftMassEffective = isLeftStatic ? float.PositiveInfinity : left.RigidBody2D?.Mass ?? float.Epsilon;
float rightMassEffective = isRightStatic ? float.PositiveInfinity : right.RigidBody2D?.Mass ?? float.Epsilon;
float impulse = -(1f + e) * velocityAlongNormal / ((1f / leftMassEffective) + (1f / rightMassEffective));
if (!isLeftStatic)
left.RigidBody2D?.Velocity += impulse / leftMassEffective * collisionInformation.Normal;
if (!isRightStatic)
right.RigidBody2D?.Velocity -= impulse / rightMassEffective * collisionInformation.Normal;
} }
} }