0

I've modified this example of inverse kinematics in JavaScript with HTML5 Canvas and made it dynamic by seperating it into a function, and it works, but the example only uses 3 points -- start, middle, and end, and I'd like to change the number of points at will. Here's my current fiddle...

function _kinematics(joints, fx, mouse) {
  joints.forEach(function (joint) {
    joint.target = joint.target || {
      x: fx.canvas.width / 2,
      y: fx.canvas.height / 2
    };
    joint.start = joint.start || {
      x: 0,
      y: 0
    };
    joint.middle = joint.middle || {
      x: 0,
      y: 0
    };
    joint.end = joint.end || {
      x: 0,
      y: 0
    };
    joint.length = joint.length || 50;
  });
  var theta,
    $theta,
    _theta,
    dx,
    dy,
    distance;
  joints.forEach(function (joint) {
    if (mouse) {
      joint.target.x = mouse.x;
      joint.target.y = mouse.y;
    }
    dx = joint.target.x - joint.start.x;
    dy = joint.target.y - joint.start.y;
    distance = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
    _theta = Math.atan2(dy, dx);
    if (distance < joint.length) {
      theta = Math.acos(distance / (joint.length + joint.length)) + _theta;
      dx = dx - joint.length * Math.cos(theta);
      dy = dy - joint.length * Math.sin(theta);
      $theta = Math.atan2(dy, dx);
    } else {
      theta = $theta = _theta;
    }
    joint.middle.x = joint.start.x + Math.cos(theta) * joint.length;
    joint.middle.y = joint.start.y + Math.sin(theta) * joint.length;
    joint.end.x = joint.middle.x + Math.cos($theta) * joint.length;
    joint.end.y = joint.middle.y + Math.sin($theta) * joint.length;
    fx.beginPath();
    fx.moveTo(joint.start.x, joint.start.y);
    /* for (var i = 0; i < joint.points.length / 2; i++) {
        fx.lineTo(joint.points[i].x, joint.points[i].y);
    } */
    fx.lineTo(joint.middle.x, joint.middle.y);
    /* for (var j = joint.points.length / 2; j < joint.points.length; j++) {
        fx.lineTo(joint.points[j].x, joint.points[j].y);
    } */
    fx.lineTo(joint.end.x, joint.end.y);
    fx.strokeStyle = "rgba(0,0,0,0.5)";
    fx.stroke();
    fx.beginPath();
    fx.arc(joint.start.x, joint.start.y, 10, 0, Math.PI * 2);
    fx.fillStyle = "rgba(255,0,0,0.5)";
    fx.fill();
    fx.beginPath();
    fx.arc(joint.middle.x, joint.middle.y, 10, 0, Math.PI * 2);
    fx.fillStyle = "rgba(0,255,0,0.5)";
    fx.fill();
    fx.beginPath();
    fx.arc(joint.end.x, joint.end.y, 10, 0, Math.PI * 2);
    fx.fillStyle = "rgba(0,0,255,0.5)";
    fx.fill();
  });
}

That's just the function, I've omitted the rest for brevity. As you can see, the commented-out lines were my attempt to draw the other points.

Also, here's where I populate the joints array with the points and such. See commented lines.

populate(_joints, $joints, function() {
  var coords = randCoords(map);
  var o = {
    start: {
      x: coords.x,
      y: coords.y
    },
    // points: [],
    target: {
      x: mouse.x,
      y: mouse.y
    }
  };
  /* for (var p = 0; p < 10; p++) {
    o.points.push({
      x: p === 0 ? o.start.x + (o.length || 50) : o.points[p - 1].x + (o.length || 50),
      y: p === 0 ? o.start.y + (o.length || 50) : o.points[p - 1].y + (o.length || 50)
    });
  }; */
  return o;
});

How would I make this function work with n points?

Raiden
  • 311
  • 3
  • 17
  • I found this on [Google](http://www.lorenzonuvoletta.com/complex-multiple-segments-inverse-kinematics/). Maybe it will help. – markE Mar 08 '16 at 02:39
  • Yeah, I found it about 30 minutes ago. Bit messy, but I might be able to implement it. – Raiden Mar 08 '16 at 02:43

0 Answers0