Search code examples
pythonpygamephysicschipmunkpymunk

Creating DampedRotarySpring in pymunk between a dynamic body and a moving static body


I'm trying to do what the title says. I have a character with a gun constrained to its hand, and I'm trying to get the gun to point at the cursor. I figured that a DampedRotarySpring would be a nice way to do it, but it turns out not to be as simple as that. The gun is a dynamic body with a Segment shape, and for the cursor I create a static body whose position I set to the mouse location with pygame each step.

When I run the program, the gun simply does not move at all except for the effect of gravity or collisions.

Here is the relevant code:

# add crosshairs at the location of the mouse
pointer_body = pymunk.Body()
pointer_shape1 = pymunk.Segment(pointer_body, (0,CROSSHAIRS_SIZE), (0,-CROSSHAIRS_SIZE), 1) # vertical segment
pointer_shape2 = pymunk.Segment(pointer_body, (-CROSSHAIRS_SIZE,0), (CROSSHAIRS_SIZE,0), 1) # horizontal segment

# add a spring that will angle the gun toward the mouse
spring = pymunk.DampedRotarySpring(me.gun.body, pointer_body, 0, 0.01, 1)

space.add(pointer_shape1, pointer_shape2, spring)

while True:
    # handle event queue
    for event in pygame.event.get():
        if event.type == pygame.MOUSEMOTION:
            from math import atan2
            # update location of pointer
            pointer_body.position = flipy(pygame.mouse.get_pos())
            pointer_body.angle = atan2( (pointer_body.position.y - me.gun.body.position.y), (pointer_body.position.x - me.gun.body.position.x) )

Edit:

Here is a Gist repository of all my code: https://gist.github.com/4470807. The main loop is in ragdoll.py.


Solution

  • The problem with the code in the gist is that you have attached the gun to the hand with two joints to keep them in the same place and same rotation. However, the the hand is a rouge body and wont rotate. Therefor the gun wont rotate when its pulled by the spring between it and the cursor, because that other joint is stronger.

    Im not sure exactly how you want the setup, but you can see that it all works if you remove the RotaryLimitJoint from the gun-hand.

    Take a look at a fixed fork of the code for the exact details: https://gist.github.com/4505219

    Some tips for future troubleshooting that I did to find the problem:

    1. Make everything 10x bigger so its easy to see what happens. I know pymunk only draws in one size, but it was easy to just add a 0 on the end of all sizes in the code.
    2. Make the hand not move so its easier to see how it rotates (removed all stuff in the update_hand_position method)
    3. Disable collisions between all shapes in the scene so that the rotating gun is not hindered by some body part. (did a simple loop of space.shapes and ran shape.group=1)