Siekacz
Siekacz

Reputation: 303

Elastic collisions in Python/Pygame

I have a serious problem with dealing with elastic collisions in gravitational field. I've tried to implement this in consistency with the law of conservation of energy, but it goes wrong, as shown in this video. Firstly, two objects stick together, and several hundred frames after the collision, they reach enormous speeds.

The complete code is online here, but the method responsible for giving output velocities after a collision is this function from world.py:

def collision(self, obj1, obj2):
    R = obj1.radius + obj2.radius   # code is used to "jump back in time" to avoid penetration when there's a collision
    dx = obj1.x - obj2.x            #
    dy = obj1.y - obj2.y            #
    K = math.hypot(dx, dy)          #   
    dvx = obj1.vx - obj2.vx         #   
    dvy = obj1.vy - obj2.vy         #
    dv = math.hypot(dvx, dvy)       #
    deltat = (R - K)/dv             #
    print dv
    print deltat
    obj1.x = obj1.rect.centerx = obj1.x - obj1.vx # *deltat
    obj2.x = obj2.rect.centerx = obj2.x - obj2.vx # *deltat
    obj1.y = obj1.rect.centery = obj1.y - obj1.vy # *deltat
    obj2.y = obj2.rect.centery = obj2.y - obj2.vy # *deltat
    dx = obj2.x - obj1.x
    dy = obj2.y - obj1.x
    delta = math.hypot(dx, dy)
    nx = dx/delta
    ny = dy/delta
    vx1bc = obj1.vx * nx
    vx2bc = obj2.vx * nx
    vy1bc = obj1.vy * ny
    vy2bc = obj2.vy * ny
    vx2ac = (obj2["energy_loss"]*(vx1bc - vx2bc) + vx1bc + (obj2["mass"]/obj1["mass"]*vx2bc))/((obj2["mass"]/obj1["mass"])+1)
    vy2ac = (obj2["energy_loss"]*(vy1bc - vy2bc) + vy1bc + (obj2["mass"]/obj1["mass"]*vy2bc))/((obj2["mass"]/obj1["mass"])+1)
    vx1ac = (vx1bc + obj2["mass"]/obj1["mass"]*vx2bc - obj2["mass"]/obj1["mass"]*vx2ac)*obj1["energy_loss"]
    vy1ac = (vy1bc + obj2["mass"]/obj1["mass"]*vy2bc - obj2["mass"]/obj1["mass"]*vy2ac)*obj1["energy_loss"]
    V1cx = obj1.vx * ny
    V1cy = obj1.vy * ny
    V2cx = obj2.vx * ny
    V2cy = obj2.vy * ny
    alfa = math.atan2(ny, nx)
    alfa_deg = math.degrees(alfa)
    v1a = math.hypot(vx1ac, vy1ac)
    v2a = math.hypot(vx2ac, vy2ac)
    obj1.vx = v1a*math.cos(alfa)+V1cx * math.sin(alfa)
    obj2.vx = v2a*math.cos(alfa)+V2cx * math.sin(alfa)
    obj1.vy = v1a*math.sin(alfa)+V1cx * math.cos(alfa)
    obj2.vy = v2a*math.sin(alfa)+V2cx * math.cos(alfa)

Upvotes: 3

Views: 1898

Answers (1)

Syklis
Syklis

Reputation: 109

Your code uses a lot of different variables, and they also have not-so-relative names. That makes it difficult to keep up with all the stuff, and also difficult for others to see what your program does. Maybe you should append variables to lists and access them? Also I recommend you to take a look at a great physics tutorial: http://www.petercollingridge.co.uk/pygame-physics-simulation

Upvotes: 1

Related Questions