Search code examples
pymunk

Pymunk dynamic object overlapping static object


I am starting out with pymunk and have a static floor with a dynamic object (ball). When the ball falls onto the floor there is an initial overlap where the ball is absorbed into the floor before slowly being pushed back up.

Why does this happen? Is this normal?

Ball overlapping floor


    import pygame
    import pymunk
    import pymunk.pygame_util
    
    pygame.init()
    
    #game window
    SCREEN_WIDTH, SCREEN_HEIGHT = 600, 600
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    
    #pymunk space
    space = pymunk.Space()
    space.gravity = (0, 981)
    
    clock = pygame.time.Clock()
    fps = 60
    dt = 1/60
    
    draw_options = pymunk.pygame_util.DrawOptions(screen)
    
    def create_floor(space, width, height, pos):
        body = pymunk.Body(body_type = pymunk.Body.STATIC)
        body.position = pos
        shape = pymunk.Poly.create_box(body, (width, height))
        space.add(body, shape)
    
    
    def create_ball(space, radius, mass):
      body = pymunk.Body()
      body.position = (300, 250)
      shape = pymunk.Circle(body, radius)
      shape.mass = mass
      shape.color = (255, 0, 0, 100)
      space.add(body, shape)
      return shape
    
    ball = create_ball(space, 30, 10)
    create_floor(space, SCREEN_WIDTH, 20, (SCREEN_WIDTH / 2, SCREEN_HEIGHT - 10))
    
    run = True
    while run:
      
      clock.tick(fps)
      space.step(dt)
      
      screen.fill((255, 255, 255))
      space.debug_draw(draw_options)
    
      #event handler
      for event in pygame.event.get():
        if event.type == pygame.QUIT:
          run = False
    
    
      pygame.display.update()
    
    pygame.quit()


Solution

  • Yes, this is normal. There are however things that can be done to minimize this behavior:

    The easiest method is to call space.step() with a smaller timestep (and instead call it more times). Replace space.step(dt) with something like this:

    for _ in range(10):
        space.step(dt/10)
    

    Its also possible to limit the maximum speed that objects move with. The slower they move, the less overlap there will be. Finally, you can also try to adjust the collision_bias parameter on the space.