I added a ‘VerletHinge’ class that’s a little hacky but it works to give rotation limits on certain joints. Provides slightly more lifelike flailing… also added a little drawing touch and made the ragdoll hang out until clicked.

[processing]

VerletPoint vPointA = new VerletPoint(100, 100);

VerletPoint[] vPointArr = new VerletPoint[9];

VerletStick[] vStickArr = new VerletStick[8];

VerletHinge[] vHingeArr = new VerletHinge[5];

int nVP = 9;

int nVS = 8;

int nVH = 5;

int xDIM = 300;

int yDIM = 120;

float GraV = .15

xSTART = xDIM/2;

ySTART = yDIM/4;

rdSCALE = 12;

boolean initRD = false;

void setup() {

background(255);

fill(255);

stroke(#568984);

size(xDIM, yDIM);

smooth();

frameRate(30);

strokeWeight(3);

vPointArr[0] = new VerletPoint(xSTART, ySTART+rdSCALE/2); //

vPointArr[1] = new VerletPoint(xSTART-rdSCALE*1.5, ySTART+rdSCALE);

vPointArr[2] = new VerletPoint(xSTART, ySTART+rdSCALE);

vPointArr[3] = new VerletPoint(xSTART+rdSCALE*1.5, ySTART+rdSCALE);

vPointArr[4] = new VerletPoint(xSTART, ySTART+rdSCALE*2);

vPointArr[5] = new VerletPoint(xSTART-rdSCALE, ySTART+rdSCALE*3);

vPointArr[6] = new VerletPoint(xSTART-rdSCALE, ySTART+rdSCALE*4);

vPointArr[7] = new VerletPoint(xSTART+rdSCALE, ySTART+rdSCALE*3);

vPointArr[8] = new VerletPoint(xSTART+rdSCALE, ySTART+rdSCALE*4);

vStickArr[0] = new VerletStick(vPointArr[0], vPointArr[2]);

vStickArr[1] = new VerletStick(vPointArr[2], vPointArr[1]);

vStickArr[2] = new VerletStick(vPointArr[2], vPointArr[3]);

vStickArr[3] = new VerletStick(vPointArr[2], vPointArr[4]);

vStickArr[4] = new VerletStick(vPointArr[4], vPointArr[5]);

vStickArr[5] = new VerletStick(vPointArr[5], vPointArr[6]);

vStickArr[6] = new VerletStick(vPointArr[4], vPointArr[7]);

vStickArr[7] = new VerletStick(vPointArr[7], vPointArr[8]);

vHingeArr[0] = new VerletHinge(vPointArr[5], vPointArr[4], vPointArr[7], 45, 160);

vHingeArr[1] = new VerletHinge(vPointArr[1], vPointArr[2], vPointArr[4], 45, 90);

vHingeArr[2] = new VerletHinge(vPointArr[4], vPointArr[2], vPointArr[3], 45, 90);

vHingeArr[3] = new VerletHinge(vPointArr[6], vPointArr[5], vPointArr[4], 10, 160);

vHingeArr[4] = new VerletHinge(vPointArr[8], vPointArr[7], vPointArr[4], 10, 160);

}

void draw() {

background(225);

if(initRD == false){

vPointArr[0].x = xSTART;

vPointArr[0].y = ySTART;

}

if(mousePressed){

initRD = true;

vPointArr[0].x = mouseX;

vPointArr[0].y = mouseY;

}else{

vPointA.y += GraV;

}

vPointA.update();

vPointA.bounds(0, 0, xDIM, yDIM);

for(int p = 0; p < nVP; p++){

if(p==0,1,3,6,8){

vPointArr[p].y += GraV;

}

vPointArr[p].update();

vPointArr[p].bounds(0, 0, xDIM, yDIM);

}

for(int s = 0; s < nVS; s++){

vStickArr[s].update();

}

for(int h = 0; h < nVH; h++){

//ustr = str(vHingeArr[h].pointA.x)+”,”+str(vHingeArr[h].pointB.x)+”,”+str(vHingeArr[h].pointC.x)

// +”-“+str(vHingeArr[h].aMin)+”,”+str(vHingeArr[h].aMax)+”,”+str(vHingeArr[h].aAng)

//println(ustr);

vHingeArr[h].update();

}

oCOL = 0;

iCOL = 255;

stroke(oCOL); strokeWeight(3); //ARMS

line(vPointArr[2].x, vPointArr[2].y, vPointArr[1].x, vPointArr[1].y);

line(vPointArr[2].x, vPointArr[2].y, vPointArr[3].x, vPointArr[3].y);

stroke(iCOL); strokeWeight(2);

line(vPointArr[2].x, vPointArr[2].y, vPointArr[1].x, vPointArr[1].y);

line(vPointArr[2].x, vPointArr[2].y, vPointArr[3].x, vPointArr[3].y);

stroke(oCOL); strokeWeight(4); //SHINS

line(vPointArr[5].x, vPointArr[5].y, vPointArr[6].x, vPointArr[6].y);

line(vPointArr[7].x, vPointArr[7].y, vPointArr[8].x, vPointArr[8].y);

stroke(iCOL); strokeWeight(3);

line(vPointArr[5].x, vPointArr[5].y, vPointArr[6].x, vPointArr[6].y);

line(vPointArr[7].x, vPointArr[7].y, vPointArr[8].x, vPointArr[8].y);

stroke(oCOL); strokeWeight(5); //THIGHS

line(vPointArr[4].x, vPointArr[4].y, vPointArr[5].x, vPointArr[5].y);

line(vPointArr[4].x, vPointArr[4].y, vPointArr[7].x, vPointArr[7].y);

stroke(iCOL); strokeWeight(4);

line(vPointArr[4].x, vPointArr[4].y, vPointArr[5].x, vPointArr[5].y);

line(vPointArr[4].x, vPointArr[4].y, vPointArr[7].x, vPointArr[7].y);

stroke(oCOL); strokeWeight(6); //CHEST

line(vPointArr[2].x, vPointArr[2].y, vPointArr[4].x, vPointArr[4].y);

stroke(iCOL); strokeWeight(5);

line(vPointArr[2].x, vPointArr[2].y, vPointArr[4].x, vPointArr[4].y);

stroke(oCOL); strokeWeight(7); //HEAD

line(vPointArr[0].x, vPointArr[0].y, vPointArr[2].x, vPointArr[2].y);

stroke(iCOL); strokeWeight(5);

line(vPointArr[0].x, vPointArr[0].y, vPointArr[2].x, vPointArr[2].y);

}

class VerletPoint {

float x, y, oldX, oldY;

VerletPoint(float _x, float _y) {

setPosition(_x, _y);

}

void setPosition(float _x, float _y) {

x = oldX = _x;

y = oldY = _y;

}

void update(){

float tempX = x, tempY = y;

x += getVx();

y += getVy();

oldX = tempX;

oldY = tempY;

}

void bounds(float left, float top, float right, float bottom){

x = constrain(x, left, right);

y = constrain(y, top, bottom-5);

}

void setVx(float value){

oldX = x – value;

}

float getVx(){

return x – oldX;

}

void setVy(float value){

oldY = y – value;

}

float getVy(){

return y – oldY;

}

void render(){

ellipse(x, y, 10, 10);

}

}

class VerletStick {

VerletPoint pointA, pointB;

float len;

VerletStick(VerletPoint _pointA, VerletPoint _pointB){

pointA = _pointA;

pointB = _pointB;

len = dist(pointA.x, pointA.y , pointB.x, pointB.y);

}

void update(){

float dst = dist(pointA.x, pointA.y , pointB.x, pointB.y);

float diff = len – dst;

float offsetX = (diff * (pointB.x – pointA.x) / dst) / 2;

float offsetY = (diff * (pointB.y – pointA.y) / dst) / 2;

pointA.x -= offsetX; pointA.y -= offsetY; pointB.x += offsetX; pointB.y += offsetY;

}

void render(){

line(pointA.x, pointA.y , pointB.x, pointB.y);

}

}

void getAngleABC( PVector a, PVector b, PVector c ){

q1 = b.x-a.x;

q2 = dist(a.x,a.y, b.x,b.y);

q3 = q1/q2;

q4 = degrees(asin(q3));

angBA = degrees(asin((b.x-a.x)/(dist(a.x,a.y, b.x,b.y))));

angBC = degrees(asin((b.x-c.x)/(dist(c.x,c.y, b.x,b.y))));

angABC = abs(angBA-angBC);

return angABC;

}

// ptB

// stickA / stickB

// ptA ptC

class VerletHinge {

VerletPoint pointA, pointB, pointC;

int aMin, aMax;

float aAng;

VerletHinge(VerletPoint _pointA, VerletPoint _pointB, VerletPoint _pointC, int _aMin, int _aMax){

aMin = _aMin; aMax = _aMax;

pointA = _pointA;

pointB = _pointB;

pointC = _pointC;

aAng = getAngleABC(pointA, pointB, pointC);

}

void update(){

aAng = getAngleABC(pointA, pointB, pointC);

//HACK – just move the points closer/further away from each other

if(aAng<aMin){

aCS = constrain((pointC.y – pointA.y) / (pointC.x – pointA.x), 0, 1);

aCRate = constrain(abs(radians(aAng-aMin)), 0, 10);

pointA.x -= aCRate; pointA.y -= aCRate*aCS;

pointC.x += aCRate; pointC.y += aCRate*aCS;

}

if(aAng>aMax){

//println(“doing”);

aCS = (pointC.y – pointA.y) / (pointC.x – pointA.x);

aCRate = abs(radians(aAng-aMin));

if(pointC.x>pointA.x){

pointA.x += aCRate; pointA.y += aCRate*aCS;

pointC.x -= aCRate; pointC.y -= aCRate*aCS;

} else if(pointA.x>pointC.x){

pointA.x -= aCRate; pointA.y -= aCRate*aCS;

pointC.x += aCRate; pointC.y += aCRate*aCS;

}

}

}

void render(){

//line(stickA.pointA.x, stickA.pointA.y , stickA.pointB.x, stickA.pointB.y);

//line(stickB.pointA.x, stickB.pointA.y , stickB.pointB.x, stickB.pointB.y);

}

}

[/processing]