I'm trying to program a simple simulator of collisions between blocks with PyGame. I've tried to watch several videos online on how to detect collisions in a better way and I've managed to write this function:
def block_collisions(self, block1, block2, collision_tolerance=10):
""" check whether the two passed block objects happen to collide """
# storing initial velocities of the two blocks
block1_initialV = block1.v
block2_initialV = block2.v
if block1.block.colliderect(block2.block):
# the collision can happn only on the left and right side of the blocks since it is a rectilinear motion
if abs(block2.block.right - block1.block.left) < collision_tolerance and block1.v < 0 :
self.collision_sound.play()
# calculating new velocities
block1.v = (2*block2.m*block2_initialV + (block1.m - block2.m)*block1_initialV) / (block1.m + block2.m)
block2.v = (2*block1.m*block1_initialV + (block2.m - block1.m)*block2_initialV) / (block1.m + block2.m)
if abs(block2.block.left - block1.block.right) < collision_tolerance and block1.v > 0:
self.collision_sound.play()
# calculating new velocities
block1.v = (2*block2.m*block2_initialV + (block1.m - block2.m)*block1_initialV) / (block1.m + block2.m)
block2.v = (2*block1.m*block1_initialV + (block2.m - block1.m)*block2_initialV) / (block1.m + block2.m)
the new velocities are calculated using the formula of elastic collisions (the linear momentum and kinetic energy are conserved). Where block1 and block2 are two object of a class (which I've written) and block1/2.block is the PyGame Rect object used to represent the block. Block1/2.v and block1/2.x are block's velocity and position, while block/2.m is the mass of the block. The block has a width = height = f(m) = 20 + 10ln(m). The function above is called inside the main loop of the application in this part:
while self.running:
...
# updating the value of block's coordinates and check for collisions
for b_ in self.blocks:
# checking for collisions with other blocks
for b__ in self.blocks:
if not b_ == b__:
self.block_collisions(b_, b__)
# updating blocks coordinates
b_.x += round(b_.v, 0)
...
where self.blocks is a list containing several Block class onbjects (each of which has the same properties described above). When I try to run the animation, initially it works fine, but at a certain moment the blocks colliding with each other remain attached instead of bouncing. I can tell, because I've added a sound to this animation, that when this bug occurs it is due to the blocks that still are in collision (the sound repeats itself) and can't somehow separe (maybe because the velocity is calculated more than one time and this cause a flutuation between +k and -j values, which results in an overall velocity of k-j for the two blocks). I can't tell what's the issue in here, have you got any ideas?