Release v0.1.6 2026-07-12

This commit is contained in:
Warren H
2026-07-12 23:20:15 -04:00
parent 35553c18dd
commit 122f159b94
55 changed files with 2229 additions and 587 deletions
+57
View File
@@ -0,0 +1,57 @@
import { Canvas } from "@react-three/fiber";
import { useGLTF } from "@react-three/drei";
import { Suspense, useMemo } from "react";
import * as THREE from "three";
import { clone as cloneSkeleton } from "three/examples/jsm/utils/SkeletonUtils.js";
import { BOSS_DEFINITIONS } from "../game/bossCatalog";
import { ALTERNATE_BOSS_CONFIG, bossVisualUrl } from "../game/bossVisuals";
import type { BossId } from "../game/types";
function PortraitModel({ bossId }: { bossId: BossId }) {
const gltf = useGLTF(bossVisualUrl(bossId), false, true);
const model = useMemo(() => {
const clone = cloneSkeleton(gltf.scene);
clone.updateMatrixWorld(true);
const bounds = new THREE.Box3().setFromObject(clone);
const center = bounds.getCenter(new THREE.Vector3());
const size = bounds.getSize(new THREE.Vector3());
const scale = 2.35 / Math.max(size.x, size.y, size.z, 0.001);
clone.traverse((object) => {
if (object instanceof THREE.Mesh) {
object.castShadow = false;
object.receiveShadow = false;
}
});
return { clone, center, scale };
}, [gltf.scene]);
return (
<primitive
object={model.clone}
position={[-model.center.x * model.scale, -model.center.y * model.scale, -model.center.z * model.scale]}
rotation={[0, bossId === "bulldrome" ? 0.35 : ALTERNATE_BOSS_CONFIG[bossId].rotationOffset + 0.35, 0]}
scale={model.scale}
/>
);
}
export function BossTrophyPortrait({ bossId }: { bossId: BossId }) {
const boss = BOSS_DEFINITIONS[bossId];
return (
<div className="trophy-portrait" aria-label={`${boss.name} portrait`} role="img">
<Canvas
camera={{ position: [3.4, 2.35, 4.8], zoom: 70, near: 0.1, far: 30 }}
dpr={1}
frameloop="demand"
gl={{ alpha: true, antialias: true, powerPreference: "low-power" }}
orthographic
>
<ambientLight intensity={1.9} />
<directionalLight color="#fff3cf" intensity={3.2} position={[3, 5, 4]} />
<directionalLight color={boss.accent} intensity={2.1} position={[-4, 2, -2]} />
<Suspense fallback={null}><PortraitModel bossId={bossId} /></Suspense>
</Canvas>
<span aria-hidden="true">{boss.icon}</span>
</div>
);
}