/** * The angular "cut-corner" shapes of the cyberpunk UI: rectangles with * two opposing corners sliced off (top-left + bottom-right), drawn with * a Graphics so they can be hit-tested with a plain rectangle. * * Static helpers — no state, no scene bookkeeping: * * CyberShape.draw(panel, 320, 52, { fill: 0x0a1120, stroke: 0x00e5ff, ... }); * CyberShape.frame(scene, w/2, h/2, w, h, { color: neon, alpha: 0.35 }); */ export class CyberShape { /** * The cut-corner polygon, centered on (0,0). `notch` is the size of * each corner slice (clamped so it can never eat the whole shape). */ static points(w, h, notch) { const n = Math.max(0, Math.min(notch ?? 0, w / 2, h / 2)); const x = w / 2; const y = h / 2; return [ { x: -x + n, y: -y }, { x, y: -y }, { x, y: y - n }, { x: x - n, y }, { x: -x, y }, { x: -x, y: -y + n }, ]; } /** * Draw a cut-corner panel into an existing Graphics (at its origin). * * o: { * notch, // corner slice size (px); default min(14, h*0.28) * fill, fillAlpha, // panel fill (color int) * stroke, strokeAlpha, // edge (color int) * lineWidth, // edge width * glow, glowAlpha, // optional soft outer pass (color int) * } * Omit `fill`/`stroke` to draw only the part you gave. */ static draw(g, w, h, o = {}) { const pts = CyberShape.points(w, h, o.notch ?? Math.min(14, h * 0.28)); if (o.fill !== undefined) { g.fillStyle(o.fill, o.fillAlpha ?? 1); g.fillPoints(pts, true); } if (o.stroke !== undefined) { g.lineStyle(o.lineWidth ?? 1.5, o.stroke, o.strokeAlpha ?? 1); g.strokePoints(pts, true); } if (o.glow !== undefined) { g.lineStyle((o.lineWidth ?? 1.5) + 4, o.glow, o.glowAlpha ?? 0.25); g.strokePoints(pts, true); } } /** * A new cut-corner panel Graphics centered at (x, y) in the scene. * Same options as draw(). Returns the Graphics. */ static panel(scene, x, y, w, h, o = {}) { const g = scene.add.graphics().setPosition(x, y); CyberShape.draw(g, w, h, o); return g; } /** * HUD corner brackets + edge ticks framing a rect centered at (x, y) — * the viewfinder chrome around the console. * * o: { color, alpha, length, lineWidth, ticks } */ static frame(scene, x, y, w, h, o = {}) { const color = o.color ?? 0x00e5ff; const alpha = o.alpha ?? 0.5; const length = o.length ?? 26; const lw = o.lineWidth ?? 2; const g = scene.add.graphics().setPosition(x, y); g.lineStyle(lw, color, alpha); const hw = w / 2; const hh = h / 2; const corner = (cx, cy, sx, sy) => { g.lineBetween(cx, cy, cx, cy + sy * length); g.lineBetween(cx, cy, cx + sx * length, cy); }; corner(-hw, -hh, 1, 1); corner(hw, -hh, -1, 1); corner(-hw, hh, 1, -1); corner(hw, hh, -1, -1); if (o.ticks !== false) { g.lineStyle(lw, color, alpha * 0.7); const t = 7; g.lineBetween(0, -hh, 0, -hh + t); g.lineBetween(0, hh, 0, hh - t); g.lineBetween(-hw, 0, -hw + t, 0); g.lineBetween(hw, 0, hw - t, 0); } return g; } }