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
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".