[Python] Kinetic energy explodes while resolving collisions in physics simulation

Discussão em 'Python' iniciado por Stack, Setembro 15, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to make a basic collision simulation in 2D using python, but even in elastic collisions, the total kinetic energy seems to be exploding after a few collisions with each other, which should not be happening.

    I'm using Pygame to display the simulation.

    while running:
    for event in pygame.event.get():
    if (event.type == pygame.QUIT):
    running = False
    screen.fill((0,0,0))
    for i in l:
    pygame.draw.circle(screen, (255, 255, 255), (int(i.position.x), int(i.position.y)), i.radius)
    #next frame calculations
    i.update()
    i.WallCollision(a-r, b-r, r, r)
    for i in range(len(l)):
    for j in range(i+1, len(l)):
    l.Collision(l[j], 1)
    print("Kinetic energy = " + str(sum([0.5*i.mass*i.velocity.ab()**2 for i in l])))

    screen.blit
    pygame.display.update()


    These are my collision detection, updation and resolving functions.

    class entity:
    def __init__(self, radius: float , position: Vector2D=Vector2D(0,0), velocity: Vector2D=Vector2D(0,0), impulse: Vector2D=Vector2D(0,0), acceleration: Vector2D = Vector2D(0,0), mass: float =1.0, e_wall: float = 1.0):
    self.acceleration = acceleration
    self.velocity = velocity
    self.position = position
    self.mass = mass
    self.e_wall = e_wall
    self.radius = radius
    self.impulse = impulse
    self.dt = 1
    def update(self):
    self.velocity = ((self.velocity * self.mass) + self.impulse ) * (1/self.mass)
    self.velocity = self.velocity + self.acceleration #* self.dt
    self.position = self.position + self.velocity #* self.dt
    self.impulse = Vector2D(0,0)

    def WallCollision(self, x_max:float , y_max:float, x_min:float, y_min:float):
    if (self.position.x > x_max):
    self.position.x = x_max
    if (self.position.x < x_min):
    self.position.x = x_min
    if (self.position.y > y_max):
    self.position.y = y_max
    if (self.position.y < y_min):
    self.position.y = y_min
    if (self.position.x >= x_max or self.position.x <= x_min):
    self.velocity.x = -self.e_wall * self.velocity.x
    if (self.position.y >= y_max or self.position.y <= y_min):
    self.velocity.y = -self.e_wall * self.velocity.y
    #self.acceleration = Vector2D(0,0)
    def Collision(self, other: 'entity', e: float=0):
    u1 = self.velocity
    u2 = other.velocity
    m1 = self.mass
    m2 = other.mass
    n = Vector2D.norm(other.position - self.position)
    if Vector2D.ab(self.position - other.position) <= (self.radius + other.radius) and (u1 - u2).dot(n) > 0:

    error= (self.radius + other.radius) - (self.position - other.position).ab()
    if (error > 0):
    self.position = self.position - n*(error/2)
    other.position = other.position + n*(error/2)

    k=(1/m1 + 1/m2)
    j1=n*(1+e)*(u1-u2).dot(n)*(-1/k)
    j2=n*(1+e)*(u2-u1).dot(n)*(-1/k)
    else:
    j1=Vector2D(0,0)
    self.impulse = self.impulse + j1
    other.impulse = other.impulse - j1


    I can't seem to understand why the total Kinetic Energy keeps increasing.

    Continue reading...

Compartilhe esta Página