Back to City Breaker
SOURCE / PINNED RELEASE

Made of little things.

City Breaker

Release
94d2b8664b10…
Author-recorded commit
df23103cbcc1…
License
LICENSE
Author’s source reference
nostr://npub1sj2vketepqw9v6fmge5fdzuj7atj9sv6qv2jss05n2z6rl64lcfqumdsnt/wss%3A%2F%2Fgit.napplet.soy%2F/n-cf8b858653e

Archive hash verified: eeeed725668c1ece…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

src/ui/glyphs.ts
// Vector silhouettes. Coordinates are in a unit box, nose toward +x.
type Poly = number[];

const SWEPT_BOMBER: Poly = [1, 0, 0.55, 0.08, 0.05, 0.9, -0.15, 0.9, 0.1, 0.1, -0.7, 0.08, -0.95, 0.35, -1, 0.35, -0.9, 0, -1, -0.35, -0.95, -0.35, -0.7, -0.08, 0.1, -0.1, -0.15, -0.9, 0.05, -0.9, 0.55, -0.08];
const BEAR: Poly = [1, 0, 0.6, 0.07, 0.2, 0.95, 0.05, 0.95, 0.05, 0.08, -0.75, 0.07, -0.95, 0.4, -1, 0.4, -0.92, 0, -1, -0.4, -0.95, -0.4, -0.75, -0.07, 0.05, -0.08, 0.05, -0.95, 0.2, -0.95, 0.6, -0.07];
const BLINDER: Poly = [1, 0, 0.5, 0.07, -0.1, 0.65, -0.3, 0.65, -0.15, 0.1, -0.75, 0.1, -1, 0.35, -1, -0.35, -0.75, -0.1, -0.15, -0.1, -0.3, -0.65, -0.1, -0.65, 0.5, -0.07];
const STRAIGHT: Poly = [1, 0, 0.5, 0.08, 0.25, 0.85, 0.05, 0.85, 0.05, 0.08, -0.7, 0.07, -0.95, 0.4, -1, 0.4, -0.9, 0, -1, -0.4, -0.95, -0.4, -0.7, -0.07, 0.05, -0.08, 0.05, -0.85, 0.25, -0.85, 0.5, -0.08];
const DELTA: Poly = [1, 0, 0.2, 0.08, -0.6, 0.55, -0.75, 0.55, -0.7, 0.1, -1, 0.3, -1, -0.3, -0.7, -0.1, -0.75, -0.55, -0.6, -0.55, 0.2, -0.08];
const FITTER: Poly = [1, 0, 0.3, 0.08, -0.25, 0.6, -0.45, 0.6, -0.3, 0.08, -0.8, 0.07, -1, 0.35, -1, -0.35, -0.8, -0.07, -0.3, -0.08, -0.45, -0.6, -0.25, -0.6, 0.3, -0.08];
const STARFIGHTER: Poly = [1, 0, 0.3, 0.06, 0.05, 0.4, -0.1, 0.4, -0.1, 0.06, -0.8, 0.06, -1, 0.3, -1, -0.3, -0.8, -0.06, -0.1, -0.06, -0.1, -0.4, 0.05, -0.4, 0.3, -0.06];
const PHANTOM: Poly = [1, 0, 0.35, 0.1, -0.1, 0.6, -0.4, 0.62, -0.35, 0.12, -0.8, 0.1, -1, 0.42, -1.02, -0.42, -0.8, -0.1, -0.35, -0.12, -0.4, -0.62, -0.1, -0.6, 0.35, -0.1];
const LIGHTNING: Poly = [1, 0, 0.3, 0.1, -0.5, 0.65, -0.75, 0.65, -0.65, 0.12, -1, 0.2, -1, -0.2, -0.65, -0.12, -0.75, -0.65, -0.5, -0.65, 0.3, -0.1];
const DRONE: Poly = [1, 0, 0, 0.15, -0.6, 0.6, -0.8, 0.6, -0.6, 0, -0.8, -0.6, -0.6, -0.6, 0, -0.15];
const FOXBAT: Poly = [1, 0, 0.35, 0.1, -0.2, 0.7, -0.55, 0.7, -0.55, 0.15, -0.9, 0.15, -1, 0.45, -1.05, -0.45, -0.9, -0.15, -0.55, -0.15, -0.55, -0.7, -0.2, -0.7, 0.35, -0.1];

export const GLYPHS: Record<string, Poly> = {
  'Tu-16': SWEPT_BOMBER, 'Tu-16PP': SWEPT_BOMBER, 'Tu-22': BLINDER, 'Tu-95': BEAR, 'Il-28': STRAIGHT, 'Yak-28': STRAIGHT,
  'MiG-21': DELTA, 'Su-7': FITTER, 'MiG-25R': FOXBAT, 'F-104G': STARFIGHTER, 'F-4': PHANTOM, Lightning: LIGHTNING, drone: DRONE,
};

export const GLYPH_SIZE: Record<string, number> = {
  'Tu-16': 0.55, 'Tu-16PP': 0.55, 'Tu-22': 0.5, 'Tu-95': 0.7, 'Il-28': 0.4, 'Yak-28': 0.4, 'MiG-21': 0.3, 'Su-7': 0.33,
  'MiG-25R': 0.4, 'F-104G': 0.3, 'F-4': 0.34, Lightning: 0.32, drone: 0.2,
};

export function tracePlane(ctx: CanvasRenderingContext2D, kind: string, x: number, y: number, hdg: number, size: number): void {
  const poly = GLYPHS[kind] ?? SWEPT_BOMBER;
  const c = Math.cos(hdg);
  const s = Math.sin(hdg);
  ctx.beginPath();
  for (let i = 0; i < poly.length; i += 2) {
    const px = poly[i] * size;
    const py = poly[i + 1] * size;
    const X = x + px * c - py * s;
    const Y = y + px * s + py * c;
    if (i === 0) ctx.moveTo(X, Y);
    else ctx.lineTo(X, Y);
  }
  ctx.closePath();
}