105 lines
3.2 KiB
JavaScript
105 lines
3.2 KiB
JavaScript
/**
|
|
* 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;
|
|
}
|
|
}
|