Active ragdoll in pymunk

107 Views Asked by At

I'm writing a script in pymunk/pygame to create a character for a game. At this point, I have a ragdoll (the skeleton) with body parts linked by PinJoints.

The problem is that in this way I don't have an active ragdoll, but only a dead stickman that falls like butter on the ground. How can I make it standing and, eventually, make procedural animations on it, like walking or climbing or grabbing objects?

This is the code to define the ragdoll (sorry if it's not so 'pythonic'


class BonePoint():
    def __init__(self, x, y, group):
        self.body = pymunk.Body()
        self.body.position = x, y
        self.shape = pymunk.Circle(self.body, radius=10)
        self.shape.elasticity = 0.5
        self.shape.density = 1
        self.shape.filter = pymunk.ShapeFilter(group = group)
        space.add(self.shape, self.body)
    
    def draw(self):
        x, y = self.body.position
        pygame.draw.circle(screen, (255,0,0), (int(x), int(y)), 10)


class Bone():
    def __init__(self, body1, attachement, min, max, identifier = "body"):
        self.body1 = body1
        if identifier == "body":
            self.body2 = attachement
        elif identifier == "position":
            self.body2 = pymunk.Body(body_type=pymunk.Body.STATIC)
            self.body2.position = attachement
        joint = pymunk.PinJoint(self.body1, self.body2)
        space.add(joint)
    def draw(self):
        pos1 = self.body1.position
        pos2 = self.body2.position
        pygame.draw.line(screen, (0,0,0), pos1, pos2, 10)

class Player():
    def __init__(self, x, y):
        self.shoulders = BonePoint(x, y, 1)
        self.head = BonePoint(x, y-40, 1)
        self.left_elbow = BonePoint(x-50, y, 1)
        self.left_hand = BonePoint(x-100, y, 1)
        self.right_elbow = BonePoint(x+50, y, 1)
        self.right_hand = BonePoint(x+100, y, 1)
        self.hip = BonePoint(x, y+100, 1)
        self.left_knee = BonePoint(x, y+150, 1)
        self.right_knee = BonePoint(x, y+150, 1)
        self.left_foot = BonePoint(x, y+200, 1)
        self.right_foot = BonePoint(x, y+200, 1)
        
        self.neck_bone = Bone(self.shoulders.body, self.head.body, -pi/4, pi/4)
        self.left_arm_bone = Bone(self.shoulders.body, self.left_elbow.body, -pi/2, pi/2)
        self.left_forearm_bone = Bone(self.left_elbow.body, self.left_hand.body, 0, pi)
        self.right_arm_bone = Bone(self.shoulders.body, self.right_elbow.body, -pi/2, pi/2)
        self.right_forearm_bone = Bone(self.right_elbow.body, self.right_hand.body, 0, pi)
        self.left_thigh_bone = Bone(self.hip.body, self.left_knee.body, -pi/4, pi/1.5)
        self.left_leg_bone = Bone(self.left_knee.body, self.left_foot.body, -pi/1.5, 0)
        self.right_thigh_bone = Bone(self.hip.body, self.right_knee.body, -pi/4, pi/1.5)
        self.right_leg_bone = Bone(self.right_knee.body, self.right_foot.body, -pi/1.5, 0)
        self.torso_bone = Bone(self.shoulders.body, self.hip.body, -pi/2, pi/2)
        
        
    def draw_player(self):
        self.shoulders.draw()
        self.head.draw()
        self.left_elbow.draw()
        self.left_hand.draw()
        self.right_elbow.draw()
        self.right_hand.draw()
        self.hip.draw()
        self.left_knee.draw()
        self.right_knee.draw()
        self.left_foot.draw()
        self.right_foot.draw()
        
        self.neck_bone.draw()
        self.left_arm_bone.draw()
        self.left_forearm_bone.draw()
        self.right_arm_bone.draw()
        self.right_forearm_bone.draw()
        self.torso_bone.draw()
        self.left_thigh_bone.draw()
        self.left_leg_bone.draw()
        self.right_thigh_bone.draw()
        self.right_leg_bone.draw()

Ps. I tried using RotaryLimitJoints, but apparently they don't work

1

There are 1 best solutions below

0
viblo On

The easiest is the classic death ragdoll, that happens when the player can not control the character anymore.

In those cases, what you do is you animate the character "normally" while the player is in control and move the physics bodies accordingly to match. Then when the player lose control (i.e. character death), you let the physics bodies "free".