Jump to content
  • Advertisement
Bob Dylan

Calculating direction after circle-circle collision

This topic is 366 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I know how to calculate the scalar of the velocity vector after a collision with 2 circles (as per this link: https://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331)

These circles cannot rotate and do not have friction but can have different masses, however I cannot seem to find out any way to find the unit vector that I need to multiply the scalar of velocity by to get the new velocity of the particles after the collision.

I also know how to check if 2 circles are colliding.

Also, I am only dealing with this in a purely "maths-sense" (ie. the circles have a center and a radius), and would like to know how I can represent these circles on the screen in python 3.0.

The vector class:

class Vector():
def __init__(self,x,y):
    self.x = x
    self.y = y

def add(self, newVector):
    return Vector(self.x+newVector.x, self.y+newVector.y)

def subtract(self,newVector):
    return Vector(self.x-newVector.x, self.y-newVector.y)

def equals(self, newVector):
    return Vector(newVector.x,newVector.y)

def scalarMult(self, scalar):
    return Vector(self.x*scalar, self.y*scalar)

def dotProduct(self, newVector):
    return (self.x*newVector.x)+(self.y*newVector.y

def distance(self):
    return math.sqrt((self.x)**2 +(self.y)**2)

The circle class:

class Particles():
def __init__(self,currentPos, oldPos, accel, dt,mass, center, radius):
    self.currentPos = currentPos
    self.oldPos = oldPos
    self.accel = accel
    self.dt = dt
    self.mass = mass
    self.center = center
    self.radius = radius

def doVerletPosition(currentPos, oldPos, accel, dt):
    a = currentPos.subtract(oldPos)
    b = currentPos.add(a)
    c = accel.scalarMult(dt)
    d = c.scalarMult(dt)
    return d.add(b)

def doVerletVelocity(currentPos, oldPos, dt):
    deltaD = (currentPos.subtract(oldPos))
    return deltaD.scalarMult(1/dt)

def collisionDetection(self, center, radius):
    xCenter = (self.radius).xComponent()
    yCenter = (self.radius).yComponent()
    xOther = radius.xComponent()
    yOther = radius.yComponent()
    if ((xCenter - xOther)**2 + (yCenter-yOther)**2 < (self.radius + radius)**2):
        return True
    else:
        return False

I do know about AABBs, but I am only using around 10 particles for now, and AABBs are not necessary now.

Share this post


Link to post
Share on other sites
Advertisement

The usual billiard physics will hopefully help you. It can be narrow down to weighted disks easily. I haven't read that link thought. But at first glance it covers what you are looking for.

Edited by _Silence_

Share this post


Link to post
Share on other sites

Ah that is somehow easy Its not that hard:

- You take the difference between the two centers in world space: R = B - A

- Normalize that and you have your direction: N = R / |R|

- Calculate the penetration distance by subtracting the summed radius of both circles from the projected difference by the direction (btw: This distance is the length of the difference): d = (RadiusA+RadiusB) - Dot(R, N)

- Calculate relative velocity: VAB = VA - VB

- Calculate impulse strength: j = -(1 + e) * Dot(VAB, N) / (1/MassA + 1/MassB);

- Calculate and apply impulse on velocities:

VA -= j * (1 / MassA) * N

VB += j * (1 / MassB) * N

 

Thats one step. Next step is to resolve penetration. This is handled in the "how to create a custom 2D physics engine" series as well - so check that out.

Edited by Finalspace

Share this post


Link to post
Share on other sites
34 minutes ago, Dirk Gregorius said:

This obviously has not the dimensions of an impulse.

Right, its not an impulse at all! My bad. Its a minimum translation vector!

An impulse would be at the relative velocity projected along the direction divided by the sum of their masses.

Edited by Finalspace

Share this post


Link to post
Share on other sites
Quote

An impulse would be at the relative velocity projected along the direction divided by the sum of their masses.

Nope, impulse = mass * velocity. Not velocity divided by mass. You are also not taking the rotational effects into account. E.g. the inertia contribution seen by the impulse at the application point in the direction of the normal. This is sometimes referred to as effective mass.

float EffectiveMassInv = 1/m1 + 1/m2 + dot(n, InvI1 * n) + dot(n, InvI2 * n);
float EffectiveMass = 1 / EffectiveMassInv;

Then you can compute equal and opposite impulses on each body like

float Lambda = EffectiveMass * -RelVelocity;
Body1->ApplyImpulseAt( -n * Lambda, ContactPoint );
Body2->ApplyImpulseAt( n, Lambda, ContactPoint );

 

 

Edited by Dirk Gregorius

Share this post


Link to post
Share on other sites
On 17.10.2017 at 7:56 PM, Dirk Gregorius said:

Nope, impulse = mass * velocity. Not velocity divided by mass. You are also not taking the rotational effects into account. E.g. the inertia contribution seen by the impulse at the application point in the direction of the normal. This is sometimes referred to as effective mass.


float EffectiveMassInv = 1/m1 + 1/m2 + dot(n, InvI1 * n) + dot(n, InvI2 * n);
float EffectiveMass = 1 / EffectiveMassInv;

Then you can compute equal and opposite impulses on each body like


float Lambda = EffectiveMass * -RelVelocity;
Body1->ApplyImpulseAt( -n * Lambda, ContactPoint );
Body2->ApplyImpulseAt( n, Lambda, ContactPoint );

 

 

The OP dont care about rotations, so i havent included it. 

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!