[Python] Collision glitchy because of movement in pymunk

Discussão em 'Python' iniciado por Stack, Junho 20, 2025.

  1. Stack

    Stack Membro Participativo

    I'm currently working on a little project (a video game) that asks me to use accurates physics events. My goal, to make it minimal for you guys, is to have 2 rectangles who can move (here with the keyboard) and can collide. In case of collision, they push them selves (as it would be as normal) and the eventually rotate according to the collision angle.

    All of this is perfectly provided by the munk library.

    However, with my code (which is a minimal reproductible example), the two box collides as expected but can, if we try harder, merge them selves increasing the velocity till' making an pymunk error.

    In the update function I tried to set manually the velocity but it made the same problem

    # Literally
    self.body.velocity = (self.direction.x * dt * 10000, self.direction.y * dt * 10000)


    So I need tour help !

    Moreover, I would love to give my blocks some inertia, like that when I stop pressing any key (implying I'm no more giving any direction to my players) it continues a bit to go worward until it stops (taht's why I added this : space.damping = .5)

    import pygame
    import pymunk
    import pymunk.pygame_util

    class Player:
    def __init__(self, space):
    self.mass = 3
    self.body = pymunk.Body(self.mass, pymunk.moment_for_box(self.mass, (50, 100)))
    self.shape = pymunk.Poly.create_box(self.body, (50, 100))
    self.shape.friction = 0.7
    self.shape.elasticity = 0.0
    space.add(self.body, self.shape)
    self.direction = (0,0)

    def move(self, dir_vec):
    self.direction = tuple(dir_vec)

    def update(self, dt):
    speed = 200 # px/s
    desired_v = pymunk.Vec2d(self.direction[0], self.direction[1]) * speed
    delta_v = desired_v - self.body.velocity
    impulse = delta_v * self.mass
    self.body.apply_impulse_at_local_point(impulse)


    pygame.init()

    WIDTH, HEIGHT = 1920//2, 1080//2

    window = pygame.display.set_mode((WIDTH, HEIGHT))

    players = []

    def draw(space, window, draw_options):
    window.fill("white")
    space.debug_draw(draw_options)
    pygame.display.update()


    def run(window, width, height):
    run = True
    clock = pygame.time.Clock()
    FPS = 60

    # Create a pymunk space
    space = pymunk.Space()
    space.damping = .5
    space.iterations = 30
    space.collision_slop = 0.05

    players.append(Player(space))
    players.append(Player(space))

    draw_options = pymunk.pygame_util.DrawOptions(window)

    while run:
    for event in pygame.event.get():
    if event.type == pygame.QUIT:
    run = False
    break

    keys = pygame.key.get_pressed()

    dir_p1 = pygame.Vector2(0, 0)
    dir_p2 = pygame.Vector2(0, 0)

    if keys[pygame.K_z]:
    dir_p1.y -= 1
    if keys[pygame.K_q]:
    dir_p1.x -= 1
    if keys[pygame.K_s]:
    dir_p1.y += 1
    if keys[pygame.K_d]:
    dir_p1.x += 1
    if keys[pygame.K_UP]:
    dir_p2.y -= 1
    if keys[pygame.K_DOWN]:
    dir_p2.x -= 1
    if keys[pygame.K_LEFT]:
    dir_p2.y += 1
    if keys[pygame.K_RIGHT]:
    dir_p2.x += 1

    players[0].move(dir_p1)
    players[1].move(dir_p2)

    for player in players:
    player.update(1/FPS)

    draw(space, window, draw_options)
    space.step(1/FPS)
    clock.tick(FPS)

    pygame.quit()

    return

    if __name__ == "__main__":
    run(window, WIDTH, HEIGHT)

    Continue reading...

Compartilhe esta Página