Skip to content

Instantly share code, notes, and snippets.

@chribbe
Created November 30, 2012 13:30
A CodePen by Christian Östman. The Rope
<html>
<head>
</head>
<body>
</body>
</html>
var GRAVITY = {x:0,y:10};
var FRICTION = {x:0.94,y:0.91};
var NUM_JOINTS = 12;
var DISTANCE = 1.2;
var WEIGHT = 6;
var target = {x:0,y:0}
//Arrays
var px = new Array();
var py = new Array();
var oldx = new Array();
var oldy = new Array();
var ax = new Array();
var ay = new Array();
// rendering
var paper;
var path;
var rect;
window.onmousemove = function(event)
{
target.x = event.clientX;
target.y = event.clientY;
}
window.onload = function()
{
createRope();
// Creates canvas 320 × 200 at 10, 50
paper = Raphael(0, 0, 800, 400);
var pathStr = "M10 10";
path = paper.path(pathStr);
path.attr({stroke: "#000000", "stroke-width": 3, "stroke-linecap": "round"}),
setInterval(render,1000/60)
rect = paper.rect(5, 5, 40, 40, 3);
rect.attr({fill:"#7dcbdd"});
}
function collideRope()
{
for (var i = 0; i < NUM_JOINTS; i++)
{
if(py[i] > 250) //set border limit
py[i] = 250;
}
}
function render()
{
updateRope(); //handels with both the gravity and weight force
// collideRope(); //handels collisions with the ground
//attach first point to the mouse x and y position
px[0] = target.x;
py[0] = target.y;
var pathStr = "M" + target.x + " " + target.y;
for(var j = 0; j <=NUM_JOINTS; j++)
{
pathStr += "L" + px[j];
pathStr += " " + py[j];
}
path.attr("path",pathStr);
}
function updateRope()
{
// FORCE
for (var i = 1; i <= NUM_JOINTS; i++) {
py[i] += (GRAVITY.y * 1/36);
px[i] += (GRAVITY.x * 1/36);
}
// FRICTION
for (var i = 0; i <= NUM_JOINTS; i++) {
var previousx = px[i];
var previousy = py[i];
px[i] += (px[i] - oldx[i]) * FRICTION.x;
py[i] += (py[i] - oldy[i]) * FRICTION.y;
oldx[i] = previousx; //equal old to previous
oldy[i] = previousy;
}
py[NUM_JOINTS] += (WEIGHT * 1/36);
// TENSION
var jointDistance = DISTANCE / NUM_JOINTS; //calculate average distance between join
for (var i = 1; i <= NUM_JOINTS; i++) {
var dx = (px[i] - px[i - 1]) / 100; //calculate distance between each join and the previous
var dy = (py[i] - py[i - 1]) / 100;
var d = Math.sqrt((dx * dx) + (dy * dy));//pythagoras to determine the real distance
var force = d - jointDistance; //force equals current distance minus the distance it should be in a 'relaxed' state
ax[i] = (dx / d) * 0.5 * 100 * force; //calculate acceleration
ay[i] = (dy / d) * 0.5 * 100 * force;
px[i] -= ax[i]; //add acceleration to position
py[i] -= ay[i];
px[i - 1] += ax[i]; //add opposite acceleration to the previous join
py[i - 1] += ay[i];
}
var dx = px[NUM_JOINTS] - px[NUM_JOINTS-1]; //calculate angle
var dy = py[NUM_JOINTS] - py[NUM_JOINTS-1];
rect.attr({x:px[NUM_JOINTS] - 25,y:py[NUM_JOINTS],transform:"r" +-(Math.atan2(dx,dy)*(180/Math.PI)) }) //position equals last join
}
function createRope()
{
for (var i = 0; i <= NUM_JOINTS; i++)
{
px[i] = 0;
py[i] = 0;
oldx[i] = 0;
oldy[i] = 0;
ax[i] = 0;
ay[i] = 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment