Upload index.html
Browse files- index.html +28 -11
index.html
CHANGED
|
@@ -108,6 +108,13 @@ class Fish {
|
|
| 108 |
x: 0.72 - t * 1.62 + rand(-0.07, 0.07), // +0.72s → -0.90s along the body
|
| 109 |
w: rand(0.08, 0.2), // bar width, in units of s
|
| 110 |
style,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
});
|
| 112 |
}
|
| 113 |
} else {
|
|
@@ -416,26 +423,36 @@ class Fish {
|
|
| 416 |
c.restore();
|
| 417 |
}
|
| 418 |
|
| 419 |
-
// v14: tiger stripes on ~20% of fish (mutually exclusive with spots)
|
| 420 |
-
//
|
| 421 |
-
//
|
|
|
|
| 422 |
// sheen so the iridescent shimmer still plays across the stripes.
|
| 423 |
if (this.stripes) {
|
| 424 |
c.save();
|
| 425 |
c.clip(bodyPath);
|
|
|
|
| 426 |
for (const st of this.stripes) {
|
| 427 |
const sx = st.x * s; // bar center, fish-local x
|
| 428 |
-
const
|
| 429 |
-
const
|
| 430 |
c.fillStyle = st.style;
|
| 431 |
c.beginPath();
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 435 |
}
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
}
|
| 440 |
c.closePath();
|
| 441 |
c.fill();
|
|
|
|
| 108 |
x: 0.72 - t * 1.62 + rand(-0.07, 0.07), // +0.72s → -0.90s along the body
|
| 109 |
w: rand(0.08, 0.2), // bar width, in units of s
|
| 110 |
style,
|
| 111 |
+
// v14.1: organic shape — each bar bends and tapers instead of a straight line
|
| 112 |
+
cAmp: rand(0.03, 0.09), // whole-bar bend amplitude (units of s)
|
| 113 |
+
cFreq: rand(0.8, 2.0), // waves of bend across the bar's height
|
| 114 |
+
cPh: rand(0, Math.PI * 2),
|
| 115 |
+
tAmp: rand(0.15, 0.45), // width taper (fraction of half-width)
|
| 116 |
+
tFreq: rand(0.8, 2.0),
|
| 117 |
+
tPh: rand(0, Math.PI * 2),
|
| 118 |
});
|
| 119 |
}
|
| 120 |
} else {
|
|
|
|
| 423 |
c.restore();
|
| 424 |
}
|
| 425 |
|
| 426 |
+
// v14.1: tiger stripes on ~20% of fish (mutually exclusive with spots). Each bar is
|
| 427 |
+
// a wavy, tapering band — its centerline bends and its width varies down the body,
|
| 428 |
+
// so no stripe reads as a straight line. Sampled along both edges so it still rides
|
| 429 |
+
// the traveling wave (wy); clipped to the outline and drawn BEFORE the additive
|
| 430 |
// sheen so the iridescent shimmer still plays across the stripes.
|
| 431 |
if (this.stripes) {
|
| 432 |
c.save();
|
| 433 |
c.clip(bodyPath);
|
| 434 |
+
const N = 8; // samples down each edge for smooth organic curves
|
| 435 |
for (const st of this.stripes) {
|
| 436 |
const sx = st.x * s; // bar center, fish-local x
|
| 437 |
+
const hw0 = st.w * s / 2; // base half-width
|
| 438 |
+
const H = s * 1.35; // vertical span (clipped by the body outline)
|
| 439 |
c.fillStyle = st.style;
|
| 440 |
c.beginPath();
|
| 441 |
+
// left edge, top → bottom: bend the centerline + taper the width with t
|
| 442 |
+
for (let j = 0; j <= N; j++) {
|
| 443 |
+
const t = j / N;
|
| 444 |
+
const cx = sx + Math.sin(t * st.cFreq * Math.PI + st.cPh) * st.cAmp * s;
|
| 445 |
+
const hwL = hw0 * (1 + st.tAmp * Math.sin(t * st.tFreq * Math.PI + st.tPh));
|
| 446 |
+
const xL = cx - hwL, yL = wy(xL) + (t - 0.5) * H;
|
| 447 |
+
if (j === 0) c.moveTo(xL, yL); else c.lineTo(xL, yL);
|
| 448 |
}
|
| 449 |
+
// right edge, bottom → top
|
| 450 |
+
for (let j = N; j >= 0; j--) {
|
| 451 |
+
const t = j / N;
|
| 452 |
+
const cx = sx + Math.sin(t * st.cFreq * Math.PI + st.cPh) * st.cAmp * s;
|
| 453 |
+
const hwR = hw0 * (1 + st.tAmp * Math.sin(t * st.tFreq * Math.PI + st.tPh));
|
| 454 |
+
const xR = cx + hwR, yR = wy(xR) + (t - 0.5) * H;
|
| 455 |
+
c.lineTo(xR, yR);
|
| 456 |
}
|
| 457 |
c.closePath();
|
| 458 |
c.fill();
|