feat: move poses

This commit is contained in:
TrèsAbhi committed 2024-01-20 16:59:18 -06:00
1 parent 103c1b4338
commit 480fda34ce
4 files changed
+120 -36

No files matched your search

@@ -10,7 +10,11 @@ import { Pose, poseEvent } from '../../../../../core/blitzkrieg/pose';
import { useTankopedia } from '../../../../../stores/tankopedia'; import { useTankopedia } from '../../../../../stores/tankopedia';
import { Duel } from '../page'; import { Duel } from '../page';
const DISTANCE = 15; const poseDistances: Record<Pose, number> = {
[Pose.HullDown]: 15,
[Pose.FaceHug]: 5,
[Pose.Default]: -1,
};
interface ControlsProps { interface ControlsProps {
duel: Duel; duel: Duel;
@@ -23,25 +27,33 @@ export function Controls({ duel }: ControlsProps) {
async () => await modelDefinitions, async () => await modelDefinitions,
[], [],
); );
const tankModelDefinition = awaitedModelDefinitions[duel.protagonist.tank.id]; const protagonistModelDefinition =
const turretModelDefinition = awaitedModelDefinitions[duel.protagonist.tank.id];
tankModelDefinition.turrets[duel.protagonist.turret.id]; const antagonistModelDefinition =
const gunModelDefinition = awaitedModelDefinitions[duel.antagonist.tank.id];
turretModelDefinition.guns[duel.protagonist.gun.id]; const protagonistTurretModelDefinition =
const turretOrigin = new Vector3( protagonistModelDefinition.turrets[duel.protagonist.turret.id];
tankModelDefinition.turretOrigin[0], const antagonistTurretModelDefinition =
tankModelDefinition.turretOrigin[1], antagonistModelDefinition.turrets[duel.antagonist.turret.id];
-tankModelDefinition.turretOrigin[2], const protagonistGunModelDefinition =
protagonistTurretModelDefinition.guns[duel.protagonist.gun.id];
const protagonistTurretOrigin = new Vector3(
protagonistModelDefinition.turretOrigin[0],
protagonistModelDefinition.turretOrigin[1],
-protagonistModelDefinition.turretOrigin[2],
); );
const gunOrigin = new Vector3( const protagonistGunOrigin = new Vector3(
turretModelDefinition.gunOrigin[0], protagonistTurretModelDefinition.gunOrigin[0],
turretModelDefinition.gunOrigin[1], protagonistTurretModelDefinition.gunOrigin[1],
-turretModelDefinition.gunOrigin[2], -protagonistTurretModelDefinition.gunOrigin[2],
); );
const antagonistGunHeight =
antagonistModelDefinition.turretOrigin[1] +
antagonistTurretModelDefinition.gunOrigin[1];
useEffect(() => { useEffect(() => {
camera.position.set(-5, 4, -20); camera.position.set(-4, 4, -16);
orbitControls.current?.target.set(0, 1.5, 0); orbitControls.current?.target.set(0, antagonistGunHeight / 2, 0);
const unsubscribeTankopedia = useTankopedia.subscribe( const unsubscribeTankopedia = useTankopedia.subscribe(
(state) => state.model.visual.controlsEnabled, (state) => state.model.visual.controlsEnabled,
@@ -51,27 +63,72 @@ export function Controls({ duel }: ControlsProps) {
); );
function handlePoseEvent(event: Pose) { function handlePoseEvent(event: Pose) {
const [pitch] = applyPitchYawLimits(
-Infinity,
0,
gunModelDefinition.pitch,
turretModelDefinition.yaw,
);
switch (event) { switch (event) {
case Pose.HullDown: { case Pose.HullDown: {
const [pitch] = applyPitchYawLimits(
-Infinity,
0,
protagonistGunModelDefinition.pitch,
protagonistTurretModelDefinition.yaw,
);
camera.position camera.position
.set(0, 0, 0) .set(0, 0, 0)
.add(turretOrigin) .add(protagonistTurretOrigin)
.add(gunOrigin) .add(protagonistGunOrigin)
.add( .add(
new Vector3( new Vector3(
0, 0,
DISTANCE * Math.sin(pitch), poseDistances[event] * Math.sin(pitch),
DISTANCE * -Math.cos(pitch), poseDistances[event] * -Math.cos(pitch),
), ),
); );
camera.lookAt(turretOrigin.clone().add(gunOrigin)); camera.lookAt(
orbitControls.current?.target.set(0, 1.5, 0); protagonistTurretOrigin.clone().add(protagonistGunOrigin),
);
orbitControls.current?.target.set(0, antagonistGunHeight, 0);
break;
}
case Pose.FaceHug: {
const [pitch] = applyPitchYawLimits(
0,
0,
protagonistGunModelDefinition.pitch,
protagonistTurretModelDefinition.yaw,
);
camera.position
.set(0, 0, 0)
.add(protagonistTurretOrigin)
.add(protagonistGunOrigin)
.add(
new Vector3(
0,
poseDistances[event] * Math.sin(pitch),
poseDistances[event] * -Math.cos(pitch),
),
);
orbitControls.current?.target
.set(0, 0, 0)
.add(protagonistTurretOrigin)
.add(protagonistGunOrigin)
.add(
new Vector3(
0,
0.5 * poseDistances[event] * Math.sin(pitch),
0.5 * poseDistances[event] * -Math.cos(pitch),
),
);
break;
}
case Pose.Default: {
camera.position.set(-4, 4, -16);
orbitControls.current?.target.set(0, antagonistGunHeight / 2, 0);
break;
} }
} }
} }
@@ -82,7 +139,7 @@ export function Controls({ duel }: ControlsProps) {
unsubscribeTankopedia(); unsubscribeTankopedia();
poseEvent.off(handlePoseEvent); poseEvent.off(handlePoseEvent);
}; };
}, [camera]); }, [camera, duel.protagonist.tank.id, duel.antagonist.tank.id]);
return ( return (
<OrbitControls <OrbitControls
@@ -71,7 +71,29 @@ export function TankSandbox({ duel }: TankSandboxProps) {
draft.model.physical.pitch = pitch; draft.model.physical.pitch = pitch;
draft.model.physical.yaw = yaw; draft.model.physical.yaw = yaw;
}); });
break;
} }
case Pose.FaceHug: {
mutateTankopedia((draft) => {
const [pitch, yaw] = applyPitchYawLimits(
0,
0,
gunModelDefinition.pitch,
turretModelDefinition.yaw,
);
modelTransformEvent.emit({ pitch, yaw });
draft.model.physical.pitch = pitch;
draft.model.physical.yaw = yaw;
});
break;
}
case Pose.Default:
break;
} }
} }
@@ -134,7 +156,7 @@ export function TankSandbox({ duel }: TankSandboxProps) {
<Canvas <Canvas
shadows shadows
ref={canvas} ref={canvas}
camera={{ fov: 20 }} camera={{ fov: 25 }}
onPointerDown={handlePointerDown} onPointerDown={handlePointerDown}
> >
<Controls duel={duel} /> <Controls duel={duel} />
@@ -40,14 +40,17 @@ export function Options({ isFullScreen, canvas }: OptionsProps) {
</DropdownMenu.Trigger> </DropdownMenu.Trigger>
<DropdownMenu.Content> <DropdownMenu.Content>
<DropdownMenu.Item <DropdownMenu.Item onClick={() => poseEvent.emit(Pose.HullDown)}>
onClick={() => {
console.log('called?');
poseEvent.emit(Pose.HullDown);
}}
>
Hull down Hull down
</DropdownMenu.Item> </DropdownMenu.Item>
<DropdownMenu.Item onClick={() => poseEvent.emit(Pose.FaceHug)}>
Face hug
</DropdownMenu.Item>
<DropdownMenu.Item onClick={() => poseEvent.emit(Pose.Default)}>
Default
</DropdownMenu.Item>
</DropdownMenu.Content> </DropdownMenu.Content>
</DropdownMenu.Root> </DropdownMenu.Root>
+2
View File
@@ -2,6 +2,8 @@ import { EventManager } from './eventManager';
export enum Pose { export enum Pose {
HullDown, HullDown,
FaceHug,
Default,
} }
export const poseEvent = new EventManager<Pose>(); export const poseEvent = new EventManager<Pose>();