### Sail

Spring mass system: rope +wind

```// Forked from "Falling rope" by PavlikEnemy
// https://turtletoy.net/turtle/efd6d6aeb6

Canvas.setpenopacity(-0.3);

const t = new Turtle();

const M = 0.1;
const G = 10;
const N = 50;
const L = 100;
const K = 2.0;
const A = 0.00005;
const dt = 0.02;
const V = 1;

const wind_x = 0.025;

const m = M / N;
const len = L / (N - 1);

let x = [];
let y = [];
let vx = [];
let vy = [];

for (let i = 0; i < N; i++) {
x[i] = -100
y[i] = -75 + L / (N - 1) * i;

vx[i] = 0;
vy[i] = 0;
}

let v = 0;
let a = 0.000075;

function walk(frame) {
new_x = [];
new_y = [];

[new_x[0], new_y[0]] = [x[0], y[0]];
[new_x[N - 1], new_y[N - 1]] = [x[N - 1], y[N - 1]];

for (let i = 1; i < N - 1; i++) {
let Fg = m * G;

let phi = Math.atan2(vy[i], vx[i])

let Fr_x = -A * vx[i]**2 * Math.cos(phi);
let Fr_y = -A * vy[i]**2 * Math.sin(phi);

let dx1 = x[i - 1] - x[i], dy1 = y[i - 1] - y[i];
let dx2 = x[i + 1] - x[i], dy2 = y[i + 1] - y[i];

let d1 = Math.sqrt(dx1**2 + dy1**2), phi1 = Math.atan2(dy1, dx1);
let d2 = Math.sqrt(dx2**2 + dy2**2), phi2 = Math.atan2(dy2, dx2);

let F1 = K * (d1 - len)**2;
let F2 = K * (d2 - len)**2;

let F1x = F1 * Math.cos(phi1), F1y = F1 * Math.sin(phi1);
let F2x = F2 * Math.cos(phi2), F2y = F2 * Math.sin(phi2);

if (d1 < len) {
F1x = -F1x;
F1y = -F1y;
}

if (d2 < len) {
F2x = -F2x;
F2y = -F2y;
}

let Fx = F1x + F2x + Fr_x + wind_x;
let Fy = F1y + F2y + Fr_y + Fg;

vx[i] += (Fx / m) * dt;
vy[i] += (Fy / m) * dt;

new_x[i] = x[i] + vx[i] * dt;
new_y[i] = y[i] + vy[i] * dt;
}

for (let i = 0; i < N; i++) {
[x[i], y[i]] = [new_x[i] + v, new_y[i] + v/4];
}

v += a;

if (frame >= 200) {
if (Math.abs(frame % 200 - 50) <= 3) {
t.jump(x[0], y[0]);
t.goto(x[N - 1], y[N - 1]);

let R = 20;
t.jump(x[N - 1] - R, y[N - 1] - R * 0.25);
t.goto(x[N - 1] - R * 0.8, y[N - 1] + R * 0.15);
t.goto(x[N - 1] + R * -0.1, y[N - 1] + R * 0.43);
t.goto(x[N - 1] + R * 0.9, y[N - 1] + R * 0.2);
t.goto(x[N - 1] - R, y[N - 1] - R * 0.25);

let r = 5;
t.jump(x[0], y[0]);
t.goto(x[0], y[0] - 2 * r);
let alpha = (Math.PI / 4) * (1 - 1 / 110 * (x[0] + 30));
t.goto(x[0] + 1.5 * r * Math.cos(alpha), y[0] - 7*r/4 + 1.5 * r * Math.sin(alpha));
t.goto(x[0], y[0] - 3*r/2);

let w = 5 + 25 * ((x[0] + 100) / 200);
let wx = x[N - 1] + 2 * R * (-1 + 2 * Math.random());
let wy = y[N - 1] + R * 0.45 + (100 - (y[N - 1] + R * 0.5)) * Math.random();
t.jump(wx, wy);
t.goto(wx + w, wy + w/4);

wx = x[N - 1] + 2 * R * (-1 + 2 * Math.random());
wy = -100 + (100 + (y[0] - 3 * r)) * Math.random();
t.jump(wx, wy);
t.goto(wx + w, wy + w/4);
}

if (frame % 200 <= 100) {
t.jump(x[0], y[0]);

if (frame < 600) {
let sc = (frame < 400) ? 0.5 : 0.75;

for (let i = 1; i < N; i++) {
t.goto((x[i] + 100) * sc - 100, y[i]);
}
}
else {
for (let i = 1; i < N; i++) {
t.goto(x[i], y[i]);
}
}
}
}

return frame < 2199;
}```