{"id":214,"date":"2011-02-20T14:13:26","date_gmt":"2011-02-20T14:13:26","guid":{"rendered":"http:\/\/www.funkboxing.com\/wordpress\/?p=214"},"modified":"2021-01-03T18:16:28","modified_gmt":"2021-01-03T18:16:28","slug":"simple-ragdoll-now-with-50-more-flailing","status":"publish","type":"post","link":"http:\/\/funkboxing.com\/wordpress\/?p=214","title":{"rendered":"Simple Ragdoll &#8211; now with 50% MORE FLAILING!"},"content":{"rendered":"<p>I added a &#8216;VerletHinge&#8217; class that&#8217;s a little hacky but it works to give rotation limits on certain joints. Provides slightly more lifelike flailing&#8230; also added a little drawing touch and made the ragdoll hang out until clicked.<br \/>\n[processing]<\/p>\n<p>VerletPoint vPointA = new VerletPoint(100, 100);<br \/>\nVerletPoint[] vPointArr = new VerletPoint[9];<br \/>\nVerletStick[] vStickArr = new VerletStick[8];<br \/>\nVerletHinge[] vHingeArr = new VerletHinge[5];<\/p>\n<p>int nVP = 9;<br \/>\nint nVS = 8;<br \/>\nint nVH = 5;<\/p>\n<p>int xDIM = 300;<br \/>\nint yDIM = 120;<\/p>\n<p>float GraV = .15<\/p>\n<p>xSTART = xDIM\/2;<br \/>\nySTART = yDIM\/4;<br \/>\nrdSCALE = 12;<\/p>\n<p>boolean initRD = false;<\/p>\n<p>void setup() {<br \/>\nbackground(255);<br \/>\nfill(255);<br \/>\nstroke(#568984);<br \/>\nsize(xDIM, yDIM);<br \/>\nsmooth();<br \/>\nframeRate(30);<br \/>\nstrokeWeight(3);<\/p>\n<p>vPointArr[0] = new VerletPoint(xSTART, ySTART+rdSCALE\/2); \/\/<br \/>\nvPointArr[1] = new VerletPoint(xSTART-rdSCALE*1.5, ySTART+rdSCALE);<br \/>\nvPointArr[2] = new VerletPoint(xSTART, ySTART+rdSCALE);<br \/>\nvPointArr[3] = new VerletPoint(xSTART+rdSCALE*1.5, ySTART+rdSCALE);<br \/>\nvPointArr[4] = new VerletPoint(xSTART, ySTART+rdSCALE*2);<br \/>\nvPointArr[5] = new VerletPoint(xSTART-rdSCALE, ySTART+rdSCALE*3);<br \/>\nvPointArr[6] = new VerletPoint(xSTART-rdSCALE, ySTART+rdSCALE*4);<br \/>\nvPointArr[7] = new VerletPoint(xSTART+rdSCALE, ySTART+rdSCALE*3);<br \/>\nvPointArr[8] = new VerletPoint(xSTART+rdSCALE, ySTART+rdSCALE*4);<\/p>\n<p>vStickArr[0] = new VerletStick(vPointArr[0], vPointArr[2]);<br \/>\nvStickArr[1] = new VerletStick(vPointArr[2], vPointArr[1]);<br \/>\nvStickArr[2] = new VerletStick(vPointArr[2], vPointArr[3]);<br \/>\nvStickArr[3] = new VerletStick(vPointArr[2], vPointArr[4]);<br \/>\nvStickArr[4] = new VerletStick(vPointArr[4], vPointArr[5]);<br \/>\nvStickArr[5] = new VerletStick(vPointArr[5], vPointArr[6]);<br \/>\nvStickArr[6] = new VerletStick(vPointArr[4], vPointArr[7]);<br \/>\nvStickArr[7] = new VerletStick(vPointArr[7], vPointArr[8]);<\/p>\n<p>vHingeArr[0] = new VerletHinge(vPointArr[5], vPointArr[4], vPointArr[7], 45, 160);<\/p>\n<p>vHingeArr[1] = new VerletHinge(vPointArr[1], vPointArr[2], vPointArr[4], 45, 90);<br \/>\nvHingeArr[2] = new VerletHinge(vPointArr[4], vPointArr[2], vPointArr[3], 45, 90);<\/p>\n<p>vHingeArr[3] = new VerletHinge(vPointArr[6], vPointArr[5], vPointArr[4], 10, 160);<br \/>\nvHingeArr[4] = new VerletHinge(vPointArr[8], vPointArr[7], vPointArr[4], 10, 160);<\/p>\n<p>}<\/p>\n<p>void draw() {<br \/>\nbackground(225);<\/p>\n<p>if(initRD == false){<br \/>\nvPointArr[0].x = xSTART;<br \/>\nvPointArr[0].y = ySTART;<br \/>\n}<br \/>\nif(mousePressed){<br \/>\ninitRD = true;<br \/>\nvPointArr[0].x = mouseX;<br \/>\nvPointArr[0].y = mouseY;<br \/>\n}else{<\/p>\n<p>vPointA.y += GraV;<br \/>\n}<br \/>\nvPointA.update();<br \/>\nvPointA.bounds(0, 0, xDIM, yDIM);<\/p>\n<p>for(int p = 0; p &lt; nVP; p++){<br \/>\nif(p==0,1,3,6,8){<br \/>\nvPointArr[p].y += GraV;<br \/>\n}<br \/>\nvPointArr[p].update();<br \/>\nvPointArr[p].bounds(0, 0, xDIM, yDIM);<br \/>\n}<\/p>\n<p>for(int s = 0; s &lt; nVS; s++){<br \/>\nvStickArr[s].update();<br \/>\n}<\/p>\n<p>for(int h = 0; h &lt; nVH; h++){<br \/>\n\/\/ustr = str(vHingeArr[h].pointA.x)+&#8221;,&#8221;+str(vHingeArr[h].pointB.x)+&#8221;,&#8221;+str(vHingeArr[h].pointC.x)<br \/>\n\/\/ +&#8221;-&#8220;+str(vHingeArr[h].aMin)+&#8221;,&#8221;+str(vHingeArr[h].aMax)+&#8221;,&#8221;+str(vHingeArr[h].aAng)<br \/>\n\/\/println(ustr);<br \/>\nvHingeArr[h].update();<br \/>\n}<br \/>\noCOL = 0;<br \/>\niCOL = 255;<\/p>\n<p>stroke(oCOL); strokeWeight(3); \/\/ARMS<br \/>\nline(vPointArr[2].x, vPointArr[2].y, vPointArr[1].x, vPointArr[1].y);<br \/>\nline(vPointArr[2].x, vPointArr[2].y, vPointArr[3].x, vPointArr[3].y);<br \/>\nstroke(iCOL); strokeWeight(2);<br \/>\nline(vPointArr[2].x, vPointArr[2].y, vPointArr[1].x, vPointArr[1].y);<br \/>\nline(vPointArr[2].x, vPointArr[2].y, vPointArr[3].x, vPointArr[3].y);<br \/>\nstroke(oCOL); strokeWeight(4); \/\/SHINS<br \/>\nline(vPointArr[5].x, vPointArr[5].y, vPointArr[6].x, vPointArr[6].y);<br \/>\nline(vPointArr[7].x, vPointArr[7].y, vPointArr[8].x, vPointArr[8].y);<br \/>\nstroke(iCOL); strokeWeight(3);<br \/>\nline(vPointArr[5].x, vPointArr[5].y, vPointArr[6].x, vPointArr[6].y);<br \/>\nline(vPointArr[7].x, vPointArr[7].y, vPointArr[8].x, vPointArr[8].y);<br \/>\nstroke(oCOL); strokeWeight(5); \/\/THIGHS<br \/>\nline(vPointArr[4].x, vPointArr[4].y, vPointArr[5].x, vPointArr[5].y);<br \/>\nline(vPointArr[4].x, vPointArr[4].y, vPointArr[7].x, vPointArr[7].y);<br \/>\nstroke(iCOL); strokeWeight(4);<br \/>\nline(vPointArr[4].x, vPointArr[4].y, vPointArr[5].x, vPointArr[5].y);<br \/>\nline(vPointArr[4].x, vPointArr[4].y, vPointArr[7].x, vPointArr[7].y);<br \/>\nstroke(oCOL); strokeWeight(6); \/\/CHEST<br \/>\nline(vPointArr[2].x, vPointArr[2].y, vPointArr[4].x, vPointArr[4].y);<br \/>\nstroke(iCOL); strokeWeight(5);<br \/>\nline(vPointArr[2].x, vPointArr[2].y, vPointArr[4].x, vPointArr[4].y);<br \/>\nstroke(oCOL); strokeWeight(7); \/\/HEAD<br \/>\nline(vPointArr[0].x, vPointArr[0].y, vPointArr[2].x, vPointArr[2].y);<br \/>\nstroke(iCOL); strokeWeight(5);<\/p>\n<p>line(vPointArr[0].x, vPointArr[0].y, vPointArr[2].x, vPointArr[2].y);<br \/>\n}<\/p>\n<p>class VerletPoint {<br \/>\nfloat x, y, oldX, oldY;<br \/>\nVerletPoint(float _x, float _y) {<br \/>\nsetPosition(_x, _y);<br \/>\n}<br \/>\nvoid setPosition(float _x, float _y) {<br \/>\nx = oldX = _x;<br \/>\ny = oldY = _y;<br \/>\n}<br \/>\nvoid update(){<br \/>\nfloat tempX = x, tempY = y;<br \/>\nx += getVx();<br \/>\ny += getVy();<br \/>\noldX = tempX;<br \/>\noldY = tempY;<br \/>\n}<br \/>\nvoid bounds(float left, float top, float right, float bottom){<br \/>\nx = constrain(x, left, right);<br \/>\ny = constrain(y, top, bottom-5);<br \/>\n}<br \/>\nvoid setVx(float value){<br \/>\noldX = x &#8211; value;<br \/>\n}<br \/>\nfloat getVx(){<br \/>\nreturn x &#8211; oldX;<br \/>\n}<br \/>\nvoid setVy(float value){<br \/>\noldY = y &#8211; value;<br \/>\n}<br \/>\nfloat getVy(){<br \/>\nreturn y &#8211; oldY;<br \/>\n}<br \/>\nvoid render(){<br \/>\nellipse(x, y, 10, 10);<br \/>\n}<br \/>\n}<\/p>\n<p>class VerletStick {<br \/>\nVerletPoint pointA, pointB;<br \/>\nfloat len;<br \/>\nVerletStick(VerletPoint _pointA, VerletPoint _pointB){<br \/>\npointA = _pointA;<br \/>\npointB = _pointB;<br \/>\nlen = dist(pointA.x, pointA.y , pointB.x, pointB.y);<br \/>\n}<br \/>\nvoid update(){<br \/>\nfloat dst = dist(pointA.x, pointA.y , pointB.x, pointB.y);<br \/>\nfloat diff = len &#8211; dst;<br \/>\nfloat offsetX = (diff * (pointB.x &#8211; pointA.x) \/ dst) \/ 2;<br \/>\nfloat offsetY = (diff * (pointB.y &#8211; pointA.y) \/ dst) \/ 2;<br \/>\npointA.x -= offsetX; pointA.y -= offsetY; pointB.x += offsetX; pointB.y += offsetY;<br \/>\n}<br \/>\nvoid render(){<br \/>\nline(pointA.x, pointA.y , pointB.x, pointB.y);<br \/>\n}<br \/>\n}<\/p>\n<p>void getAngleABC( PVector a, PVector b, PVector c ){<br \/>\nq1 = b.x-a.x;<br \/>\nq2 = dist(a.x,a.y, b.x,b.y);<br \/>\nq3 = q1\/q2;<br \/>\nq4 = degrees(asin(q3));<br \/>\nangBA = degrees(asin((b.x-a.x)\/(dist(a.x,a.y, b.x,b.y))));<br \/>\nangBC = degrees(asin((b.x-c.x)\/(dist(c.x,c.y, b.x,b.y))));<br \/>\nangABC = abs(angBA-angBC);<br \/>\nreturn angABC;<br \/>\n}<\/p>\n<p>\/\/ ptB<br \/>\n\/\/ stickA \/ stickB<br \/>\n\/\/ ptA ptC<br \/>\nclass VerletHinge {<\/p>\n<p>VerletPoint pointA, pointB, pointC;<br \/>\nint aMin, aMax;<br \/>\nfloat aAng;<\/p>\n<p>VerletHinge(VerletPoint _pointA, VerletPoint _pointB, VerletPoint _pointC, int _aMin, int _aMax){<br \/>\naMin = _aMin; aMax = _aMax;<br \/>\npointA = _pointA;<br \/>\npointB = _pointB;<br \/>\npointC = _pointC;<\/p>\n<p>aAng = getAngleABC(pointA, pointB, pointC);<br \/>\n}<\/p>\n<p>void update(){<br \/>\naAng = getAngleABC(pointA, pointB, pointC);<\/p>\n<p>\/\/HACK &#8211; just move the points closer\/further away from each other<br \/>\nif(aAng&lt;aMin){<br \/>\naCS = constrain((pointC.y &#8211; pointA.y) \/ (pointC.x &#8211; pointA.x), 0, 1);<br \/>\naCRate = constrain(abs(radians(aAng-aMin)), 0, 10);<br \/>\npointA.x -= aCRate; pointA.y -= aCRate*aCS;<br \/>\npointC.x += aCRate; pointC.y += aCRate*aCS;<br \/>\n}<\/p>\n<p>if(aAng&gt;aMax){<br \/>\n\/\/println(&#8220;doing&#8221;);<br \/>\naCS = (pointC.y &#8211; pointA.y) \/ (pointC.x &#8211; pointA.x);<br \/>\naCRate = abs(radians(aAng-aMin));<br \/>\nif(pointC.x&gt;pointA.x){<br \/>\npointA.x += aCRate; pointA.y += aCRate*aCS;<br \/>\npointC.x -= aCRate; pointC.y -= aCRate*aCS;<br \/>\n} else if(pointA.x&gt;pointC.x){<br \/>\npointA.x -= aCRate; pointA.y -= aCRate*aCS;<br \/>\npointC.x += aCRate; pointC.y += aCRate*aCS;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\nvoid render(){<br \/>\n\/\/line(stickA.pointA.x, stickA.pointA.y , stickA.pointB.x, stickA.pointB.y);<br \/>\n\/\/line(stickB.pointA.x, stickB.pointA.y , stickB.pointB.x, stickB.pointB.y);<br \/>\n}<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<p>[\/processing]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I added a &#8216;VerletHinge&#8217; class that&#8217;s a little hacky but it works to give rotation limits on certain joints. Provides slightly more lifelike flailing&#8230; 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]; <a href='http:\/\/funkboxing.com\/wordpress\/?p=214' class='excerpt-more'>[&#8230;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[5,47],"tags":[30],"_links":{"self":[{"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/214"}],"collection":[{"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=214"}],"version-history":[{"count":5,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/214\/revisions"}],"predecessor-version":[{"id":2235,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/214\/revisions\/2235"}],"wp:attachment":[{"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=214"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=214"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=214"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}