// Simple spring class - fairly unrealistic but gets the job done quickly // you can modify the stiffness but a chain of springs with a stiffness above 0.5 gets unstable class Spring extends Line{ float restLength; float stiffness; Point moveBy; // Constructor Spring(Point a, Point b){ super(a, b); stiffness = 0.5f; restLength = len; moveBy = new Point(0.0f, 0.0f); } // Move points to new positions void updateSpring(){ vx = b.x - a.x; vy = b.y - a.y; len = sqrt(vx * vx + vy * vy); float diff = 0.0f; if(len > 0.0f){ diff = (len - restLength) / len; } float mul = diff * stiffness; moveBy.x = -vx*mul; moveBy.y = -vy*mul; a.x -= moveBy.x; a.y -= moveBy.y; b.x += moveBy.x; b.y += moveBy.y; updateLine(); } // These two constrain methods I developed to deal with the uncontrollable length of the springs // The spring will lax out and then it will look like an inner cord snaps to full length - not pretty but it's a good enough workaround void constrainFromA(float minLength, float maxLength){ updateLine(); if(len < minLength){ b.x = a.x + minLength * dx; b.y = a.x + minLength * dy; updateLine(); } else if(len > maxLength){ b.x = a.x + maxLength * dx; b.y = a.y + maxLength * dy; updateLine(); } } void constrainFromB(float minLength, float maxLength){ updateLine(); if(len < minLength){ a.x = b.x + minLength * dx; a.y = b.x + minLength * dy; updateLine(); } else if(len > maxLength){ a.x = b.x + maxLength * dx; a.y = b.y + maxLength * dy; updateLine(); } } }