refactor(gootower): draw strands as pinched goo shapes instead of lines
Replace simple line-based strand rendering with filled polygon shapes that are thick at the ends and pinched thin in the middle, with curved edges and perpendicular sag for a drooping arc effect. Strands now connect smoothly to balls with tangent-aligned edges.
This commit is contained in:
parent
b6e7d932cd
commit
59a5d0606e
|
|
@ -654,7 +654,8 @@ export default class GooTowerGame extends Phaser.Scene {
|
|||
|
||||
this.drawGears(g);
|
||||
|
||||
// Strands first, under the balls.
|
||||
// Strands first, under the balls — drawn as pinched goo shapes (thick
|
||||
// at the ends, thin in the middle with curved edges).
|
||||
for (const s of st.strands) {
|
||||
if (s.broken) continue;
|
||||
const a = st.balls[s.a];
|
||||
|
|
@ -662,9 +663,60 @@ export default class GooTowerGame extends Phaser.Scene {
|
|||
if (!a || !b || a.dead || b.dead) continue;
|
||||
const stress = strandStress(s);
|
||||
const color = lerpColor(STRAND, STRAND_HOT, stress);
|
||||
const width = 7 - 3 * stress; // strands thin as they are pulled taut
|
||||
g.lineStyle(width, color, 1);
|
||||
g.lineBetween(a.x, a.y, b.x, b.y);
|
||||
|
||||
const dx = b.x - a.x;
|
||||
const dy = b.y - a.y;
|
||||
const len = Math.hypot(dx, dy);
|
||||
if (len < 1) continue;
|
||||
|
||||
// Unit direction along the strand and perpendicular to it.
|
||||
const ux = dx / len, uy = dy / len;
|
||||
const nx = -uy, ny = ux;
|
||||
|
||||
const baseW = 7 - 3 * stress;
|
||||
const endW = baseW;
|
||||
const midW = Math.max(1, baseW * 0.2);
|
||||
// Perpendicular sag of the centerline at the midpoint — gives the strand
|
||||
// a gentle drooping arc.
|
||||
const sagAmt = baseW * 0.5;
|
||||
|
||||
// Width profile: endW at both endpoints, pinched to midW at the center.
|
||||
// Zero derivative at t=0 and t=1 so the strand meets each ball tangentially.
|
||||
// w(t) = midW + (endW - midW) * (1 - 2·t·(1-t))
|
||||
// Sag profile: zero at endpoints, sagAmt at center.
|
||||
// s(t) = 4·sagAmt·t·(1-t)
|
||||
// Both are quadratics with zero derivative at the endpoints, giving
|
||||
// perfectly smooth (tangent-aligned) connections into the balls.
|
||||
// The second derivative of the edge offset is negative everywhere,
|
||||
// so the edges curve inward — a concave "pinched" look.
|
||||
|
||||
const samples = Math.max(8, Math.min(20, Math.round(len / 15)));
|
||||
const verts = [];
|
||||
|
||||
for (let i = 0; i <= samples; i++) {
|
||||
const t = i / samples;
|
||||
const tp = t * (1 - t); // peaks at 0.25 when t = 0.5
|
||||
const w = midW + (endW - midW) * (1 - 2 * tp);
|
||||
const sg = 4 * sagAmt * tp;
|
||||
// Center point (straight line + perpendicular sag)
|
||||
const cx = a.x + t * dx + nx * sg;
|
||||
const cy = a.y + t * dy + ny * sg;
|
||||
// Upper edge
|
||||
verts.push({ x: cx + nx * (w / 2), y: cy + ny * (w / 2) });
|
||||
}
|
||||
// Bottom edge, walking back from end → start.
|
||||
for (let i = samples; i >= 0; i--) {
|
||||
const t = i / samples;
|
||||
const tp = t * (1 - t);
|
||||
const w = midW + (endW - midW) * (1 - 2 * tp);
|
||||
const sg = 4 * sagAmt * tp;
|
||||
const cx = a.x + t * dx + nx * sg;
|
||||
const cy = a.y + t * dy + ny * sg;
|
||||
verts.push({ x: cx - nx * (w / 2), y: cy - ny * (w / 2) });
|
||||
}
|
||||
|
||||
g.fillStyle(color, 1);
|
||||
g.fillPoints(verts, true);
|
||||
}
|
||||
|
||||
// Balls.
|
||||
|
|
|
|||
Loading…
Reference in New Issue