One commited on
Commit
6ef3cfc
Β·
verified Β·
1 Parent(s): bccd59e

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +139 -1
index.html CHANGED
@@ -83,7 +83,7 @@ function genKoiPatches(type) {
83
  }
84
  return arr;
85
  }
86
- let fishes = [], bubbles = [], seaweeds = [], backSeaweeds = [], farSeaweeds = [], motes = [], rays = [], rocks = [], grass = [], fgGrass = [];
87
  let playerFish = null; // the fish controlled by gamepad (spawned with F key)
88
  const GAMEPAD_DEADZONE = 0.15; // ignore small stick movements
89
  let curNight = 0; // v7: shared night factor (dims the top-light + sheen)
@@ -894,6 +894,7 @@ function buildScene() {
894
  bubbles = [];
895
  seaweeds = [];
896
  backSeaweeds = []; // v4: blurry background seaweed (not fish-touchable)
 
897
  farSeaweeds = []; // v5: ultra-far pre-rendered blurry sprites (deepest layer)
898
  motes = [];
899
  rays = [];
@@ -1047,6 +1048,50 @@ function buildScene() {
1047
  }
1048
  }
1049
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1050
  // v5: ultra-far pre-rendered blurry seaweed β€” deepest layer, heavily blurred sprites
1051
  const nFarClusters = Math.max(6, Math.floor(W / 180)); // 50% more than previous far count
1052
  for (let i = 0; i < nFarClusters; i++) {
@@ -1488,6 +1533,96 @@ function stalkCurveX(w, f) {
1488
  // v4.3: draw background seaweed procedurally β€” multi-wave organic motion instead of
1489
  // rigid sprite rotation. Far stalks get a soft low-alpha halo pass to keep their
1490
  // "far away" look without any runtime blur filters (no slowdown).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1491
  function drawBackSeaweeds(t) {
1492
  // v6: no runtime canvas filter β€” blur() forces a CPU re-rasterize every frame
1493
  // and was the main FPS cost. Softness now comes from the halo pass below instead.
@@ -2107,6 +2242,9 @@ function frame(now) {
2107
  // v5: ultra-far pre-rendered blurry seaweed β€” deepest layer, behind everything else
2108
  drawFarSeaweeds(t);
2109
 
 
 
 
2110
  // v4: background seaweed β€” drawn behind sand/rocks for depth
2111
  drawBackSeaweeds(t); // v4.3: procedural multi-wave motion (no separate update pass)
2112
 
 
83
  }
84
  return arr;
85
  }
86
+ let fishes = [], bubbles = [], seaweeds = [], backSeaweeds = [], midSeaweeds = [], farSeaweeds = [], motes = [], rays = [], rocks = [], grass = [], fgGrass = [];
87
  let playerFish = null; // the fish controlled by gamepad (spawned with F key)
88
  const GAMEPAD_DEADZONE = 0.15; // ignore small stick movements
89
  let curNight = 0; // v7: shared night factor (dims the top-light + sheen)
 
894
  bubbles = [];
895
  seaweeds = [];
896
  backSeaweeds = []; // v4: blurry background seaweed (not fish-touchable)
897
+ midSeaweeds = []; // v6: middle-distance seaweed with halo pass (between back and far)
898
  farSeaweeds = []; // v5: ultra-far pre-rendered blurry sprites (deepest layer)
899
  motes = [];
900
  rays = [];
 
1048
  }
1049
  }
1050
 
1051
+ // v6: middle-distance seaweed using halo stroke pass (median properties between back and far)
1052
+ const nMidClusters = Math.max(5, Math.floor(W / 190));
1053
+ for (let i = 0; i < nMidClusters; i++) {
1054
+ const cx = rand(25, W - 25);
1055
+ // Median hue between backSeaweeds (165-200) and farSeaweeds (170-210)
1056
+ const clusterHue = rand(183, 197); // midpoint of both ranges
1057
+ const nStalks = 2 + ((Math.random() * 3) | 0);
1058
+ for (let j = 0; j < nStalks; j++) {
1059
+ const hue = clusterHue + rand(-12, 12);
1060
+ // Median properties: height between backSeaweeds (0.35-0.65H) and farSeaweeds (0.4-0.7H)
1061
+ const st = {
1062
+ x: cx + rand(-22, 22),
1063
+ h: rand(H * 0.42, H * 0.68), // median height
1064
+ segs: 9,
1065
+ phase: rand(0, Math.PI * 2),
1066
+ speed: rand(0.6, 1.15), // median sway speed between back (0.7-1.3) and far (0.5-1.0)
1067
+ hue,
1068
+ width: rand(3, 6.5), // median width
1069
+ tipW: rand(1.8, 3.2),
1070
+ branches: [],
1071
+ // Organic curve parameters (like backSeaweeds for halo pass technique)
1072
+ cA1: rand(9, 16), cF1: rand(0.7, 1.5), cP1: rand(0, Math.PI * 2),
1073
+ cA2: rand(3.5, 9), cF2: rand(1.8, 3.0), cP2: rand(0, Math.PI * 2),
1074
+ // Multi-wave organic motion parameters
1075
+ waveA1: rand(7, 15), waveF1: rand(0.45, 1.1), wavePh1: rand(0, Math.PI * 2),
1076
+ waveA2: rand(3.5, 9), waveF2: rand(1.2, 2.0), wavePh2: rand(0, Math.PI * 2),
1077
+ waveA3: rand(2.5, 6), waveF3: rand(2.2, 3.4), wavePh3: rand(0, Math.PI * 2)
1078
+ };
1079
+ // Add branches (median count between back and far)
1080
+ const nBr = 1 + ((Math.random() * 3) | 0);
1081
+ for (let k = 0; k < nBr; k++) {
1082
+ st.branches.push({
1083
+ f: rand(0.28, 0.82),
1084
+ side: Math.random() < 0.5 ? -1 : 1,
1085
+ len: rand(11, 26),
1086
+ up: rand(9, 22),
1087
+ w: rand(1.8, 3.5),
1088
+ ph: rand(0, Math.PI * 2)
1089
+ });
1090
+ }
1091
+ midSeaweeds.push(st);
1092
+ }
1093
+ }
1094
+
1095
  // v5: ultra-far pre-rendered blurry seaweed β€” deepest layer, heavily blurred sprites
1096
  const nFarClusters = Math.max(6, Math.floor(W / 180)); // 50% more than previous far count
1097
  for (let i = 0; i < nFarClusters; i++) {
 
1533
  // v4.3: draw background seaweed procedurally β€” multi-wave organic motion instead of
1534
  // rigid sprite rotation. Far stalks get a soft low-alpha halo pass to keep their
1535
  // "far away" look without any runtime blur filters (no slowdown).
1536
+ // v6: middle-distance seaweed using halo stroke pass (median depth between back and far)
1537
+ function drawMidSeaweeds(t) {
1538
+ for (const w of midSeaweeds) {
1539
+ const baseY = sandAt(w.x) + 10;
1540
+ const n = w.segs;
1541
+ // Slightly more blue-tinted and softer than backSeaweeds
1542
+ const coreStyle = `hsla(${w.hue},48%,30%,0.65)`;
1543
+ const haloStyle = `hsla(${w.hue},42%,34%,0.16)`;
1544
+
1545
+ // stalk sway at fraction f: three overlapping waves, root planted (f^2), tip free (f)
1546
+ const swayAt = (f) =>
1547
+ Math.sin(t * w.waveF1 + w.wavePh1 + f * 2.4) * w.waveA1 * f * f +
1548
+ Math.sin(t * w.waveF2 + w.wavePh2 + f * 3.8) * w.waveA2 * f * f +
1549
+ Math.sin(t * w.waveF3 + w.wavePh3 + f * 5.4) * w.waveA3 * f;
1550
+
1551
+ // Wider halo pass for more softness (between backSeaweeds and farSeaweeds)
1552
+ for (let pass = 0; pass < 2; pass++) {
1553
+ const isHalo = pass === 0;
1554
+ ctx.strokeStyle = isHalo ? haloStyle : coreStyle;
1555
+ ctx.lineCap = 'round';
1556
+ ctx.lineJoin = 'round';
1557
+ ctx.lineWidth = (w.width + w.tipW) / 2 * (isHalo ? 2.2 : 1); // wider halo than backSeaweeds
1558
+
1559
+ // stalk outline: up one side, round tip, down the other
1560
+ ctx.beginPath();
1561
+ let prevX = 0, prevY = baseY;
1562
+ let lastPx = 0, lastPy = baseY;
1563
+ for (let i = 0; i <= n; i++) {
1564
+ const f = i / n;
1565
+ const px = w.x + stalkCurveX(w, f) + swayAt(f);
1566
+ const py = baseY - w.h * f;
1567
+ const dx = px - prevX, dy = py - prevY;
1568
+ const dl = Math.hypot(dx, dy) || 1;
1569
+ const nx = -dy / dl, ny = dx / dl;
1570
+ const hw = (w.width * (1 - f) + w.tipW * f) / 2;
1571
+ if (i === 0) ctx.moveTo(px + nx * hw, py + ny * hw);
1572
+ else ctx.lineTo(px + nx * hw, py + ny * hw);
1573
+ prevX = px; prevY = py;
1574
+ lastPx = px; lastPy = py;
1575
+ }
1576
+ // round tip cap
1577
+ const dxT = lastPx - prevX, dyT = lastPy - prevY;
1578
+ const dlT = Math.hypot(dxT, dyT) || 1;
1579
+ const nxT = -dyT / dlT, nyT = dxT / dlT;
1580
+ ctx.quadraticCurveTo(lastPx, lastPy, lastPx + dxT * 0.5 + nxT * (w.tipW / 2), lastPy + dyT * 0.5 + nyT * (w.tipW / 2));
1581
+ // down the other side
1582
+ for (let i = n; i >= 0; i--) {
1583
+ const f = i / n;
1584
+ const px = w.x + stalkCurveX(w, f) + swayAt(f);
1585
+ const py = baseY - w.h * f;
1586
+ let dx, dy;
1587
+ if (i === n) { dx = prevX - px; dy = prevY - py; }
1588
+ else {
1589
+ const f2 = (i + 1) / n;
1590
+ const px2 = w.x + stalkCurveX(w, f2) + swayAt(f2);
1591
+ const py2 = baseY - w.h * f2;
1592
+ dx = px2 - px; dy = py2 - py;
1593
+ }
1594
+ const dl = Math.hypot(dx, dy) || 1;
1595
+ const nx = -dy / dl, ny = dx / dl;
1596
+ const hw = (w.width * (1 - f) + w.tipW * f) / 2;
1597
+ ctx.lineTo(px - nx * hw, py - ny * hw);
1598
+ }
1599
+ ctx.closePath();
1600
+ ctx.stroke();
1601
+
1602
+ // branches flutter with the stalk
1603
+ for (const b of w.branches) {
1604
+ const idx = Math.min(n, Math.max(1, Math.round(b.f * n)));
1605
+ const f = idx / n;
1606
+ const ax = w.x + stalkCurveX(w, f) + swayAt(f);
1607
+ const ay = baseY - w.h * f;
1608
+ const flutter = Math.sin(t * w.waveF2 * 1.4 + b.ph) * (3 + w.waveA2 * 0.4);
1609
+ const bx = ax + b.side * b.len + flutter;
1610
+ const by = ay - b.up;
1611
+ ctx.beginPath();
1612
+ ctx.lineWidth = isHalo ? b.w * 2.2 : b.w;
1613
+ ctx.strokeStyle = isHalo ? haloStyle : `hsla(${w.hue + 6},50%,40%,0.7)`;
1614
+ ctx.moveTo(ax, ay);
1615
+ ctx.bezierCurveTo(
1616
+ ax + b.side * b.len * 0.3, ay - b.up * 0.75,
1617
+ bx - b.side * b.len * 0.35, by + b.up * 0.6,
1618
+ bx, by
1619
+ );
1620
+ ctx.stroke();
1621
+ }
1622
+ }
1623
+ }
1624
+ }
1625
+
1626
  function drawBackSeaweeds(t) {
1627
  // v6: no runtime canvas filter β€” blur() forces a CPU re-rasterize every frame
1628
  // and was the main FPS cost. Softness now comes from the halo pass below instead.
 
2242
  // v5: ultra-far pre-rendered blurry seaweed β€” deepest layer, behind everything else
2243
  drawFarSeaweeds(t);
2244
 
2245
+ // v6: middle-distance seaweed with halo pass (between far and back)
2246
+ drawMidSeaweeds(t);
2247
+
2248
  // v4: background seaweed β€” drawn behind sand/rocks for depth
2249
  drawBackSeaweeds(t); // v4.3: procedural multi-wave motion (no separate update pass)
2250