mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: remove reactive pitch and yaw
This commit is contained in:
1 parent
4ddf77fc7f
commit
94cba0c9ba
12 files changed
+141
-190
No files matched your search
@@ -1,4 +1,3 @@
|
||||
import { normalizeAngleRad } from '@blitzkit/core';
|
||||
import { useThree, type ThreeEvent } from '@react-three/fiber';
|
||||
import { memo, useRef } from 'react';
|
||||
import { Group, Plane, Vector2, Vector3 } from 'three';
|
||||
@@ -153,15 +152,11 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
|
||||
const position = new Vector2();
|
||||
const delta = new Vector2();
|
||||
let pitch = 0;
|
||||
let yaw = 0;
|
||||
|
||||
function onPointerDown(event: ThreeEvent<PointerEvent>) {
|
||||
event.stopPropagation();
|
||||
|
||||
position.set(event.clientX, event.clientY);
|
||||
yaw = protagonist.yaw;
|
||||
pitch = protagonist.pitch;
|
||||
|
||||
mutateTankopediaEphemeral((draft) => {
|
||||
draft.controlsEnabled = false;
|
||||
@@ -190,9 +185,10 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
delta.set(event.clientX, event.clientY).sub(position);
|
||||
position.set(event.clientX, event.clientY);
|
||||
|
||||
[pitch, yaw] = applyPitchYawLimits(
|
||||
pitch,
|
||||
yaw + delta.x * (Math.PI / boundingRect.width),
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
modelTransformEvent.last!.pitch,
|
||||
modelTransformEvent.last!.yaw +
|
||||
delta.x * (Math.PI / boundingRect.width),
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
@@ -201,10 +197,6 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
}
|
||||
function handlePointerUp() {
|
||||
mutateDuel((draft) => {
|
||||
draft.protagonist.pitch = normalizeAngleRad(pitch);
|
||||
draft.protagonist.yaw = normalizeAngleRad(yaw);
|
||||
});
|
||||
mutateTankopediaEphemeral((draft) => {
|
||||
draft.controlsEnabled = true;
|
||||
});
|
||||
@@ -253,8 +245,6 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
|
||||
const position = new Vector2();
|
||||
const delta = new Vector2();
|
||||
let pitch = 0;
|
||||
let yaw = 0;
|
||||
|
||||
function onPointerDown(event: ThreeEvent<PointerEvent>) {
|
||||
event.stopPropagation();
|
||||
@@ -268,8 +258,6 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
});
|
||||
|
||||
position.set(event.clientX, event.clientY);
|
||||
pitch = protagonist.pitch;
|
||||
yaw = protagonist.yaw;
|
||||
|
||||
window.addEventListener('pointermove', handlePointerMove);
|
||||
window.addEventListener('pointerup', handlePointerUp);
|
||||
@@ -290,9 +278,11 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
delta.set(event.clientX, event.clientY).sub(position);
|
||||
position.set(event.clientX, event.clientY);
|
||||
|
||||
[pitch, yaw] = applyPitchYawLimits(
|
||||
pitch - delta.y * (Math.PI / boundingRect.height),
|
||||
yaw + delta.x * (Math.PI / boundingRect.width),
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
modelTransformEvent.last!.pitch -
|
||||
delta.y * (Math.PI / boundingRect.height),
|
||||
modelTransformEvent.last!.yaw +
|
||||
delta.x * (Math.PI / boundingRect.width),
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
@@ -304,10 +294,6 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
mutateTankopediaEphemeral((draft) => {
|
||||
draft.controlsEnabled = true;
|
||||
});
|
||||
mutateDuel((draft) => {
|
||||
draft.protagonist.pitch = normalizeAngleRad(pitch);
|
||||
draft.protagonist.yaw = normalizeAngleRad(yaw);
|
||||
});
|
||||
window.removeEventListener('pointermove', handlePointerMove);
|
||||
window.removeEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
@@ -341,8 +327,6 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
|
||||
const position = new Vector2();
|
||||
const delta = new Vector2();
|
||||
let pitch = 0;
|
||||
let yaw = 0;
|
||||
|
||||
function onPointerDown(event: ThreeEvent<PointerEvent>) {
|
||||
event.stopPropagation();
|
||||
@@ -356,9 +340,6 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
});
|
||||
|
||||
position.set(event.clientX, event.clientY);
|
||||
pitch = protagonist.pitch;
|
||||
yaw = protagonist.yaw;
|
||||
|
||||
window.addEventListener('pointermove', handlePointerMove);
|
||||
window.addEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
@@ -378,9 +359,11 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
delta.set(event.clientX, event.clientY).sub(position);
|
||||
position.set(event.clientX, event.clientY);
|
||||
|
||||
[pitch, yaw] = applyPitchYawLimits(
|
||||
pitch - delta.y * (Math.PI / boundingRect.height),
|
||||
yaw + delta.x * (Math.PI / boundingRect.width),
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
modelTransformEvent.last!.pitch -
|
||||
delta.y * (Math.PI / boundingRect.height),
|
||||
modelTransformEvent.last!.yaw +
|
||||
delta.x * (Math.PI / boundingRect.width),
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
@@ -392,10 +375,7 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
||||
mutateTankopediaEphemeral((draft) => {
|
||||
draft.controlsEnabled = true;
|
||||
});
|
||||
mutateDuel((draft) => {
|
||||
draft.protagonist.pitch = normalizeAngleRad(pitch);
|
||||
draft.protagonist.yaw = normalizeAngleRad(yaw);
|
||||
});
|
||||
|
||||
window.removeEventListener('pointermove', handlePointerMove);
|
||||
window.removeEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { I_HAT, J_HAT } from '@blitzkit/core';
|
||||
import { type MeshProps, useThree } from '@react-three/fiber';
|
||||
import { clamp } from 'lodash-es';
|
||||
import type { QuicklimeEvent } from 'quicklime';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import {
|
||||
Box3,
|
||||
@@ -186,16 +187,18 @@ export function StaticArmorSceneComponent({
|
||||
const distanceToBarrel = clip.distanceToPoint(barrelOrigin);
|
||||
const point = new Vector3();
|
||||
|
||||
function handleModelTransform(data: ModelTransformEventData) {
|
||||
function handleModelTransform(
|
||||
event: QuicklimeEvent<ModelTransformEventData>,
|
||||
) {
|
||||
clip.normal
|
||||
.set(0, 0, -1)
|
||||
.applyAxisAngle(I_HAT, data.pitch)
|
||||
.applyAxisAngle(J_HAT, data.yaw ?? 0);
|
||||
.applyAxisAngle(I_HAT, event.data.pitch)
|
||||
.applyAxisAngle(J_HAT, event.data.yaw);
|
||||
clip.constant = 0;
|
||||
|
||||
point
|
||||
.copy(gunOrigin)
|
||||
.applyAxisAngle(J_HAT, data.yaw ?? 0)
|
||||
.applyAxisAngle(J_HAT, event.data.yaw)
|
||||
.add(clip.normal.multiplyScalar(-distanceToBarrel))
|
||||
.add(neckOrigin);
|
||||
clip.normal.normalize();
|
||||
|
||||
+11
-10
@@ -3,6 +3,7 @@ import { useEffect } from 'react';
|
||||
import { awaitableEquipmentDefinitions } from '../../../../../core/awaitables/equipmentDefinitions';
|
||||
import { awaitableProvisionDefinitions } from '../../../../../core/awaitables/provisionDefinitions';
|
||||
import { applyPitchYawLimits } from '../../../../../core/blitz/applyPitchYawLimits';
|
||||
import { modelTransformEvent } from '../../../../../core/blitzkit/modelTransform';
|
||||
import { tankCharacteristics } from '../../../../../core/blitzkit/tankCharacteristics';
|
||||
import { useEquipment } from '../../../../../hooks/useEquipment';
|
||||
import { useTankModelDefinition } from '../../../../../hooks/useTankModelDefinition';
|
||||
@@ -75,16 +76,16 @@ export function Characteristics({ skeleton }: MaybeSkeletonComponentProps) {
|
||||
const hasDownImprovedVerticalStabilizer = useEquipment(124);
|
||||
|
||||
useEffect(() => {
|
||||
mutateDuel((draft) => {
|
||||
[draft.protagonist.pitch, draft.protagonist.yaw] = applyPitchYawLimits(
|
||||
draft.protagonist.pitch,
|
||||
draft.protagonist.yaw,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
hasDownImprovedVerticalStabilizer,
|
||||
);
|
||||
});
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
modelTransformEvent.last!.pitch,
|
||||
modelTransformEvent.last!.yaw,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
hasDownImprovedVerticalStabilizer,
|
||||
);
|
||||
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
}, [hasImprovedVerticalStabilizer, hasDownImprovedVerticalStabilizer]);
|
||||
|
||||
return (
|
||||
|
||||
+20
-32
@@ -1,5 +1,6 @@
|
||||
import { HeightIcon, WidthIcon } from '@radix-ui/react-icons';
|
||||
import { Flex, TextField } from '@radix-ui/themes';
|
||||
import type { QuicklimeEvent } from 'quicklime';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { degToRad, radToDeg } from 'three/src/math/MathUtils.js';
|
||||
import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits';
|
||||
@@ -28,31 +29,19 @@ export function QuickInputs() {
|
||||
const hasDownImprovedVerticalStabilizer = useEquipment(124);
|
||||
|
||||
useEffect(() => {
|
||||
if (!yawInput.current) return;
|
||||
|
||||
yawInput.current.value = radToDeg(protagonist.yaw).toFixed(1);
|
||||
}, [protagonist.yaw]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!pitchInput.current) return;
|
||||
|
||||
pitchInput.current.value = (
|
||||
-radToDeg(protagonist.pitch) + initialGunPitch
|
||||
).toFixed(1);
|
||||
}, [protagonist.pitch]);
|
||||
|
||||
useEffect(() => {
|
||||
function handleTransformEvent({ pitch, yaw }: ModelTransformEventData) {
|
||||
function handleTransformEvent(
|
||||
event: QuicklimeEvent<ModelTransformEventData>,
|
||||
) {
|
||||
if (!pitchInput.current || !yawInput.current) return;
|
||||
|
||||
pitchInput.current.value = (
|
||||
-radToDeg(pitch) +
|
||||
-radToDeg(event.data.pitch) +
|
||||
(tankModelDefinition.initial_turret_rotation?.pitch ?? 0)
|
||||
).toFixed(1);
|
||||
|
||||
if (yaw === undefined) return;
|
||||
if (event.data.yaw === undefined) return;
|
||||
|
||||
yawInput.current.value = radToDeg(yaw).toFixed(1);
|
||||
yawInput.current.value = radToDeg(event.data.yaw).toFixed(1);
|
||||
}
|
||||
|
||||
modelTransformEvent.on(handleTransformEvent);
|
||||
@@ -85,24 +74,27 @@ export function QuickInputs() {
|
||||
defaultValue="0.0"
|
||||
onBlur={() => {
|
||||
const value = Number(yawInput.current!.value);
|
||||
|
||||
if (isNaN(value)) {
|
||||
yawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1);
|
||||
yawInput.current!.value = radToDeg(
|
||||
modelTransformEvent.last!.yaw,
|
||||
).toFixed(1);
|
||||
return;
|
||||
}
|
||||
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
protagonist.pitch,
|
||||
modelTransformEvent.last!.pitch,
|
||||
degToRad(value),
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
hasDownImprovedVerticalStabilizer,
|
||||
);
|
||||
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
mutateDuel((state) => {
|
||||
state.protagonist.pitch = pitch;
|
||||
state.protagonist.yaw = yaw;
|
||||
});
|
||||
yawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1);
|
||||
yawInput.current!.value = radToDeg(
|
||||
modelTransformEvent.last!.yaw,
|
||||
).toFixed(1);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
@@ -128,25 +120,21 @@ export function QuickInputs() {
|
||||
const value = Number(pitchInput.current!.value);
|
||||
if (isNaN(value)) {
|
||||
pitchInput.current!.value = (
|
||||
-radToDeg(protagonist.pitch) + initialGunPitch
|
||||
-radToDeg(modelTransformEvent.last!.pitch) + initialGunPitch
|
||||
).toFixed(1);
|
||||
return;
|
||||
}
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
degToRad(-value + initialGunPitch),
|
||||
protagonist.yaw,
|
||||
modelTransformEvent.last!.yaw,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
hasDownImprovedVerticalStabilizer,
|
||||
);
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
mutateDuel((state) => {
|
||||
state.protagonist.pitch = pitch;
|
||||
state.protagonist.yaw = yaw;
|
||||
});
|
||||
pitchInput.current!.value = (
|
||||
-radToDeg(protagonist.pitch) + initialGunPitch
|
||||
-radToDeg(modelTransformEvent.last!.pitch) + initialGunPitch
|
||||
).toFixed(1);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
import { useEffect } from 'react';
|
||||
import { degToRad } from 'three/src/math/MathUtils.js';
|
||||
import { awaitableModelDefinitions } from '../../../../../../core/awaitables/modelDefinitions';
|
||||
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||
import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform';
|
||||
import { Duel } from '../../../../../../stores/duel';
|
||||
|
||||
const modelDefinitions = await awaitableModelDefinitions;
|
||||
|
||||
export function InitialAligner() {
|
||||
const tank = Duel.use((state) => state.protagonist.tank);
|
||||
const turret = Duel.use((state) => state.protagonist.turret);
|
||||
const gun = Duel.use((state) => state.protagonist.gun);
|
||||
|
||||
const tankModel = modelDefinitions.models[tank.id];
|
||||
const turretModel = tankModel.turrets[turret.id];
|
||||
const gunModel = turretModel.guns[gun.gun_type!.value.base.id];
|
||||
|
||||
useEffect(() => {
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
degToRad(8),
|
||||
degToRad(25),
|
||||
gunModel.pitch,
|
||||
turretModel.yaw,
|
||||
);
|
||||
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
+6
-11
@@ -39,9 +39,6 @@ export function SceneProps() {
|
||||
const material = useRef<MeshStandardMaterial>(null);
|
||||
const playground = useRef<Group>(null);
|
||||
|
||||
let lastPitch = Duel.use((state) => state.protagonist.pitch);
|
||||
let lastYaw = Duel.use((state) => state.protagonist.yaw);
|
||||
const display = TankopediaEphemeral.use((state) => state.display);
|
||||
const turret = Duel.use((state) => state.protagonist.turret);
|
||||
const track = Duel.use((state) => state.protagonist.track);
|
||||
const tank = Duel.use((state) => state.protagonist.tank);
|
||||
@@ -152,8 +149,8 @@ export function SceneProps() {
|
||||
|
||||
const desiredPitch = Math.asin(direction.y);
|
||||
const desiredYaw = Math.atan2(-direction.x, -direction.z);
|
||||
const deltaPitch = desiredPitch - lastPitch;
|
||||
const deltaYaw = desiredYaw - lastYaw;
|
||||
const deltaPitch = desiredPitch - modelTransformEvent.last!.pitch;
|
||||
const deltaYaw = desiredYaw - modelTransformEvent.last!.yaw;
|
||||
const deltaAngle = Math.sqrt(deltaPitch ** 2 + deltaYaw ** 2);
|
||||
const maxPossibleRotationInTime = gunRotationSpeed * deltaT;
|
||||
const clampedDeltaAngle = Math.min(maxPossibleRotationInTime, deltaAngle);
|
||||
@@ -163,14 +160,14 @@ export function SceneProps() {
|
||||
deltaAngle === 0 ? 0 : deltaYaw * (clampedDeltaAngle / deltaAngle);
|
||||
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
lastPitch + clampedDeltaPitch,
|
||||
lastYaw + clampedDeltaYaw,
|
||||
modelTransformEvent.last!.pitch + clampedDeltaPitch,
|
||||
modelTransformEvent.last!.yaw + clampedDeltaYaw,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
);
|
||||
|
||||
const actualDeltaPitch = pitch - lastPitch;
|
||||
const actualDeltaYaw = yaw - lastYaw;
|
||||
const actualDeltaPitch = pitch - modelTransformEvent.last!.pitch;
|
||||
const actualDeltaYaw = yaw - modelTransformEvent.last!.yaw;
|
||||
const deltaRotation = Math.abs(actualDeltaPitch) + Math.abs(actualDeltaYaw);
|
||||
const rotationSpeed = deltaRotation / deltaT;
|
||||
const turretTraversePenalty =
|
||||
@@ -190,8 +187,6 @@ export function SceneProps() {
|
||||
}
|
||||
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
lastPitch = pitch;
|
||||
lastYaw = yaw;
|
||||
|
||||
const gunDirection = new Vector3(0, 0, -1)
|
||||
.applyAxisAngle(I_HAT, pitch)
|
||||
|
||||
+6
-19
@@ -1,4 +1,3 @@
|
||||
import { normalizeAngleRad } from '@blitzkit/core';
|
||||
import { invalidate, useThree, type ThreeEvent } from '@react-three/fiber';
|
||||
import { useRef } from 'react';
|
||||
import { Group, Mesh, MeshStandardMaterial, Vector2 } from 'three';
|
||||
@@ -125,17 +124,12 @@ export function TankModel() {
|
||||
|
||||
if (!isVisible) return null;
|
||||
|
||||
let pitch = 0;
|
||||
let yaw = 0;
|
||||
|
||||
function onPointerDown(event: ThreeEvent<PointerEvent>) {
|
||||
event.stopPropagation();
|
||||
|
||||
if (!isTurret) return;
|
||||
|
||||
position.set(event.clientX, event.clientY);
|
||||
yaw = protagonist.yaw;
|
||||
pitch = protagonist.pitch;
|
||||
|
||||
mutateTankopediaEphemeral((draft) => {
|
||||
draft.controlsEnabled = false;
|
||||
@@ -164,9 +158,10 @@ export function TankModel() {
|
||||
delta.set(event.clientX, event.clientY).sub(position);
|
||||
position.set(event.clientX, event.clientY);
|
||||
|
||||
[pitch, yaw] = applyPitchYawLimits(
|
||||
pitch,
|
||||
yaw + delta.x * (Math.PI / boundingRect.width),
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
modelTransformEvent.last!.pitch,
|
||||
modelTransformEvent.last!.yaw +
|
||||
delta.x * (Math.PI / boundingRect.width),
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
@@ -175,10 +170,6 @@ export function TankModel() {
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
}
|
||||
function handlePointerUp() {
|
||||
mutateDuel((draft) => {
|
||||
draft.protagonist.pitch = normalizeAngleRad(pitch);
|
||||
draft.protagonist.yaw = normalizeAngleRad(yaw);
|
||||
});
|
||||
mutateTankopediaEphemeral((draft) => {
|
||||
draft.controlsEnabled = true;
|
||||
});
|
||||
@@ -231,8 +222,8 @@ export function TankModel() {
|
||||
});
|
||||
|
||||
position.set(event.clientX, event.clientY);
|
||||
pitch = protagonist.pitch;
|
||||
yaw = protagonist.yaw;
|
||||
pitch = modelTransformEvent.last!.pitch;
|
||||
yaw = modelTransformEvent.last!.yaw;
|
||||
|
||||
window.addEventListener('pointermove', handlePointerMove);
|
||||
window.addEventListener('pointerup', handlePointerUp);
|
||||
@@ -267,10 +258,6 @@ export function TankModel() {
|
||||
mutateTankopediaEphemeral((draft) => {
|
||||
draft.controlsEnabled = true;
|
||||
});
|
||||
mutateDuel((draft) => {
|
||||
draft.protagonist.pitch = normalizeAngleRad(pitch);
|
||||
draft.protagonist.yaw = normalizeAngleRad(yaw);
|
||||
});
|
||||
window.removeEventListener('pointermove', handlePointerMove);
|
||||
window.removeEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
|
||||
+37
-46
@@ -28,6 +28,7 @@ import {
|
||||
import { SmartCanvas } from '../../../../SmartCanvas';
|
||||
import { AutoClear } from './components/AutoClear';
|
||||
import { Controls } from './components/Control';
|
||||
import { InitialAligner } from './components/InitialAligner';
|
||||
import { InitialFogReveal } from './components/InitialFogReveal';
|
||||
import { Lighting } from './components/Lighting';
|
||||
import { SceneProps } from './components/SceneProps';
|
||||
@@ -114,56 +115,44 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
|
||||
function handlePoseEvent(pose: Pose) {
|
||||
switch (pose) {
|
||||
case Pose.HullDown: {
|
||||
mutateDuel((draft) => {
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
-Infinity,
|
||||
0,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
hasDownImprovedVerticalStabilizer,
|
||||
);
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
-Infinity,
|
||||
0,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
hasDownImprovedVerticalStabilizer,
|
||||
);
|
||||
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
draft.protagonist.pitch = pitch;
|
||||
draft.protagonist.yaw = yaw;
|
||||
});
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Pose.FaceHug: {
|
||||
mutateDuel((draft) => {
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
Infinity,
|
||||
0,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
);
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
Infinity,
|
||||
0,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
);
|
||||
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
draft.protagonist.pitch = pitch;
|
||||
draft.protagonist.yaw = yaw;
|
||||
});
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Pose.Default:
|
||||
mutateDuel((draft) => {
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
0,
|
||||
0,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
);
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
0,
|
||||
0,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
);
|
||||
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
draft.protagonist.pitch = pitch;
|
||||
draft.protagonist.yaw = yaw;
|
||||
});
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -177,15 +166,15 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
mutateDuel((draft) => {
|
||||
[draft.protagonist.pitch, draft.protagonist.yaw] = applyPitchYawLimits(
|
||||
draft.protagonist.pitch,
|
||||
draft.protagonist.yaw,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
);
|
||||
});
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
modelTransformEvent.last!.pitch,
|
||||
modelTransformEvent.last!.yaw,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
);
|
||||
|
||||
modelTransformEvent.dispatch({ pitch, yaw });
|
||||
}, [protagonistGun, protagonistTurret]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -246,6 +235,8 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
|
||||
)}
|
||||
<Lighting display={display} />
|
||||
</Suspense>
|
||||
|
||||
<InitialAligner />
|
||||
</SmartCanvas>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { Quicklime } from 'quicklime';
|
||||
|
||||
export interface ModelTransformEventData {
|
||||
yaw?: number;
|
||||
yaw: number;
|
||||
pitch: number;
|
||||
}
|
||||
|
||||
export const modelTransformEvent = new Quicklime<ModelTransformEventData>();
|
||||
export const modelTransformEvent = new Quicklime<ModelTransformEventData>({
|
||||
pitch: 0,
|
||||
yaw: 0,
|
||||
});
|
||||
@@ -4,10 +4,8 @@ import {
|
||||
type ProvisionDefinitions,
|
||||
type TankDefinition,
|
||||
} from '@blitzkit/core';
|
||||
import { degToRad } from 'three/src/math/MathUtils.js';
|
||||
import type { DuelMember } from '../../stores/duel';
|
||||
import { genericDefaultEquipmentMatrix } from '../../stores/duel/constants';
|
||||
import { applyPitchYawLimits } from '../blitz/applyPitchYawLimits';
|
||||
|
||||
export function tankToDuelMember(
|
||||
tank: TankDefinition,
|
||||
@@ -15,16 +13,7 @@ export function tankToDuelMember(
|
||||
provisionDefinitions: ProvisionDefinitions,
|
||||
) {
|
||||
const turret = tank.turrets.at(-1)!;
|
||||
const turretModel = model.turrets[turret.id];
|
||||
const gun = turret.guns.at(-1)!;
|
||||
const gunModel = turretModel.guns[gun.gun_type!.value.base.id];
|
||||
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
degToRad(8),
|
||||
degToRad(25),
|
||||
gunModel.pitch,
|
||||
turretModel.yaw,
|
||||
);
|
||||
|
||||
return {
|
||||
camouflage: true,
|
||||
@@ -37,8 +26,6 @@ export function tankToDuelMember(
|
||||
shell: tank.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0],
|
||||
tank,
|
||||
track: tank.tracks.at(-1)!,
|
||||
yaw,
|
||||
pitch,
|
||||
turret,
|
||||
assaultDistance:
|
||||
(gun.gun_type!.value.base.assault_ranges?.ranges[0].distance ?? 0) / 2,
|
||||
|
||||
@@ -45,9 +45,8 @@ export function useTankTransform(
|
||||
}
|
||||
|
||||
function handleModelTransformInner(data?: ModelTransformEventData) {
|
||||
const duel = duelStore.getState();
|
||||
const yaw = data?.yaw ?? duel.protagonist.yaw;
|
||||
const pitch = data?.pitch ?? duel.protagonist.pitch;
|
||||
const yaw = data?.yaw ?? modelTransformEvent.last!.yaw;
|
||||
const pitch = data?.pitch ?? modelTransformEvent.last!.pitch;
|
||||
|
||||
gunPosition
|
||||
.set(0, 0, 0)
|
||||
@@ -102,20 +101,8 @@ export function useTankTransform(
|
||||
|
||||
modelTransformEvent.on(handleModelTransform);
|
||||
|
||||
const unsubscribes = [
|
||||
duelStore.subscribe(
|
||||
(state) => state.protagonist.pitch,
|
||||
() => handleModelTransformInner(),
|
||||
),
|
||||
duelStore.subscribe(
|
||||
(state) => state.protagonist.yaw,
|
||||
() => handleModelTransformInner(),
|
||||
),
|
||||
() => modelTransformEvent.off(handleModelTransform),
|
||||
];
|
||||
|
||||
return () => {
|
||||
unsubscribes.forEach((unsubscribe) => unsubscribe());
|
||||
modelTransformEvent.off(handleModelTransform);
|
||||
};
|
||||
}, [track, turret]);
|
||||
}
|
||||
@@ -33,8 +33,6 @@ export interface DuelMember {
|
||||
shell: ShellDefinition;
|
||||
track: TrackDefinition;
|
||||
equipmentMatrix: EquipmentMatrix;
|
||||
pitch: number;
|
||||
yaw: number;
|
||||
consumables: number[];
|
||||
provisions: number[];
|
||||
camouflage: boolean;
|
||||
|
||||
Reference in new issue
Block a user