Files
AgentCompany/landing/components/world/lighting.ts
T
ZacharyZhang-NYandClaude Opus 5.5 2d7af224dd
CI / Typecheck, lint, tests, e2e (push) Failing after 3m51s
Website: 16-bit pixel-art rebuild with a live Three.js office, downloads from Gitea v1.5.1
- Title screen over a real-time voxel office rendered at low resolution and quantized to a rotating 32-colour palette with Bayer dithering; day part and season re-light the scene and every surface.
- 16-bit UI kit: name-plate dialogs, menu cursor, inventory, XP bar, badges, NPC speech, GAME OVER with CONTINUE, hand-placed 12x12 icons, Fusion Pixel font (Latin subset preloaded).
- Sections as a game: quest log (onboarding), character select (AI CEO / AI Co-Founder), inventory (features), party roster (providers), live download XP, save point (all v1.5.1 builds), FAQ as NPC dialog, credits.
- Downloads and source point to the Gitea release; the download function only redirects to git.zacharyzhang.com.
- Tailwind and the old components removed; unit tests for platform/downloads, rewritten e2e suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:37:23 -04:00

53 lines
2.2 KiB
TypeScript

import { AmbientLight, DirectionalLight, Vector3 } from "three";
import { INK, type DayPart } from "../../lib/palette";
import type { Office } from "./office";
interface Light {
sun: [number, number, number];
sunInk: number;
sunPower: number;
fill: number;
lampInk: number;
lamps: number;
screens: number;
glow: number;
}
const LIGHT: Record<DayPart, Light> = {
dawn: { sun: [-0.6, 0.5, 0.62], sunInk: INK.glow, sunPower: 1.6, fill: 2.0, lampInk: INK.glow, lamps: 0, screens: 0.85, glow: 0 },
day: { sun: [-0.35, 0.85, 0.4], sunInk: INK.white, sunPower: 1.55, fill: 1.85, lampInk: INK.glow, lamps: 0, screens: 0.75, glow: 0 },
dusk: { sun: [0.7, 0.45, 0.55], sunInk: INK.glow, sunPower: 1.5, fill: 2.0, lampInk: INK.glow, lamps: 4, screens: 1, glow: 0.8 },
night: { sun: [-0.3, 0.9, 0.3], sunInk: INK.sun, sunPower: 1.2, fill: 3.2, lampInk: INK.gold, lamps: 8, screens: 1, glow: 1.6 },
};
export function createLights(): { sun: DirectionalLight; sky: AmbientLight } {
const sun = new DirectionalLight();
sun.castShadow = true;
sun.shadow.mapSize.set(1024, 1024);
sun.shadow.bias = -0.0008;
sun.shadow.normalBias = 0.03;
Object.assign(sun.shadow.camera, { left: -16, right: 16, top: 16, bottom: -16, near: 1, far: 60 });
return { sun, sky: new AmbientLight() };
}
/** Points the sun, tints the ambient fill and switches lamps and screens for a day part. */
export function applyLighting(lights: { sun: DirectionalLight; sky: AmbientLight }, office: Office, colours: string[], part: DayPart): void {
const light = LIGHT[part];
lights.sun.position.copy(new Vector3(...light.sun).normalize().multiplyScalar(24));
lights.sun.color.set(colours[light.sunInk]!);
lights.sun.intensity = light.sunPower;
lights.sky.color.set(colours[INK.white]!);
lights.sky.intensity = light.fill;
for (const lamp of office.lamps) {
lamp.color.set(colours[light.lampInk]!);
lamp.intensity = light.lamps;
}
for (const glow of office.glows) {
glow.color.set(colours[INK.screen]!);
glow.intensity = light.glow;
}
office.bulbs.color.set(colours[light.lamps > 0 ? light.lampInk : INK.paper]!);
for (const screen of office.screens) screen.color.set(colours[INK.screen]!).multiplyScalar(light.screens);
office.steam.color.set(colours[INK.cloud]!);
}