mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: consistent zoom
This commit is contained in:
1 parent
2f9791d34c
commit
d19d4e0e26
3 files changed
+51
-15
No files matched your search
+40
-10
@@ -8,6 +8,10 @@ import { degToRad } from 'three/src/math/MathUtils.js';
|
|||||||
import { awaitableModelDefinitions } from '../../../../../../core/awaitables/modelDefinitions';
|
import { awaitableModelDefinitions } from '../../../../../../core/awaitables/modelDefinitions';
|
||||||
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||||
import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment';
|
import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment';
|
||||||
|
import {
|
||||||
|
modelTransformEvent,
|
||||||
|
type ModelTransformEventData,
|
||||||
|
} from '../../../../../../core/blitzkit/modelTransform';
|
||||||
import { Pose, poseEvent } from '../../../../../../core/blitzkit/pose';
|
import { Pose, poseEvent } from '../../../../../../core/blitzkit/pose';
|
||||||
import { Duel } from '../../../../../../stores/duel';
|
import { Duel } from '../../../../../../stores/duel';
|
||||||
import {
|
import {
|
||||||
@@ -16,6 +20,7 @@ import {
|
|||||||
TankopediaEphemeral,
|
TankopediaEphemeral,
|
||||||
} from '../../../../../../stores/tankopediaEphemeral';
|
} from '../../../../../../stores/tankopediaEphemeral';
|
||||||
import { TankopediaDisplay } from '../../../../../../stores/tankopediaPersistent/constants';
|
import { TankopediaDisplay } from '../../../../../../stores/tankopediaPersistent/constants';
|
||||||
|
import { aimTarget } from './SceneProps/constants';
|
||||||
|
|
||||||
const poseDistances: Record<Pose, number> = {
|
const poseDistances: Record<Pose, number> = {
|
||||||
[Pose.HullDown]: 15,
|
[Pose.HullDown]: 15,
|
||||||
@@ -199,6 +204,8 @@ export function Controls() {
|
|||||||
}, [camera, protagonistTank.id, antagonistTank.id]);
|
}, [camera, protagonistTank.id, antagonistTank.id]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
let isInitialIteration = true;
|
||||||
|
|
||||||
function handleDisturbance() {
|
function handleDisturbance() {
|
||||||
setAutoRotate(false);
|
setAutoRotate(false);
|
||||||
}
|
}
|
||||||
@@ -243,6 +250,8 @@ export function Controls() {
|
|||||||
document.body.addEventListener('scroll', handleScroll);
|
document.body.addEventListener('scroll', handleScroll);
|
||||||
|
|
||||||
const sniperModeCameraOffset = new Vector3();
|
const sniperModeCameraOffset = new Vector3();
|
||||||
|
let pitch = 0;
|
||||||
|
let yaw = 0;
|
||||||
|
|
||||||
function updateCamera() {
|
function updateCamera() {
|
||||||
if (!orbitControls.current) return;
|
if (!orbitControls.current) return;
|
||||||
@@ -261,19 +270,32 @@ export function Controls() {
|
|||||||
|
|
||||||
if (shootingRangeZoom === ShootingRangeZoom.Arcade) {
|
if (shootingRangeZoom === ShootingRangeZoom.Arcade) {
|
||||||
orbitControls.current.target.set(0, gunHeight + 3, 0);
|
orbitControls.current.target.set(0, gunHeight + 3, 0);
|
||||||
camera.position.set(
|
|
||||||
0,
|
if (isInitialIteration) {
|
||||||
gunHeight + ARCADE_MODE_DISTANCE * Math.sin(ARCADE_MODE_ANGLE),
|
isInitialIteration = false;
|
||||||
ARCADE_MODE_DISTANCE * Math.cos(ARCADE_MODE_ANGLE),
|
camera.position.set(
|
||||||
);
|
0,
|
||||||
|
gunHeight + ARCADE_MODE_DISTANCE * Math.sin(ARCADE_MODE_ANGLE),
|
||||||
|
ARCADE_MODE_DISTANCE * Math.cos(ARCADE_MODE_ANGLE),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
camera.position
|
||||||
|
.copy(aimTarget)
|
||||||
|
.sub(orbitControls.current.target)
|
||||||
|
.normalize()
|
||||||
|
.multiplyScalar(-ARCADE_MODE_DISTANCE)
|
||||||
|
.add(orbitControls.current.target);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
orbitControls.current.target.copy(shellOrigin);
|
orbitControls.current.target.copy(shellOrigin);
|
||||||
camera.position.copy(
|
|
||||||
sniperModeCameraOffset.set(0, 0, 1e-4).add(shellOrigin),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(ShootingRangeZoom[shootingRangeZoom], camera.zoom);
|
camera.position
|
||||||
|
.copy(aimTarget)
|
||||||
|
.sub(shellOrigin)
|
||||||
|
.normalize()
|
||||||
|
.multiplyScalar(-1e-4)
|
||||||
|
.add(shellOrigin);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
camera.position.set(...inspectModeInitialPosition);
|
camera.position.set(...inspectModeInitialPosition);
|
||||||
orbitControls.current.target.set(0, gunHeight / 2, 0);
|
orbitControls.current.target.set(0, gunHeight / 2, 0);
|
||||||
@@ -285,6 +307,13 @@ export function Controls() {
|
|||||||
camera.updateProjectionMatrix();
|
camera.updateProjectionMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleModelTransform(event: ModelTransformEventData) {
|
||||||
|
pitch = event.pitch;
|
||||||
|
yaw = event.yaw ?? yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
modelTransformEvent.on(handleModelTransform);
|
||||||
|
|
||||||
updateCamera();
|
updateCamera();
|
||||||
|
|
||||||
const unsubscribeDisplay = tankopediaEphemeralStore.subscribe(
|
const unsubscribeDisplay = tankopediaEphemeralStore.subscribe(
|
||||||
@@ -308,6 +337,7 @@ export function Controls() {
|
|||||||
window.removeEventListener('keydown', handleKeyDown);
|
window.removeEventListener('keydown', handleKeyDown);
|
||||||
canvas.removeEventListener('wheel', handleWheel);
|
canvas.removeEventListener('wheel', handleWheel);
|
||||||
document.body.removeEventListener('scroll', handleScroll);
|
document.body.removeEventListener('scroll', handleScroll);
|
||||||
|
modelTransformEvent.off(handleModelTransform);
|
||||||
};
|
};
|
||||||
}, [display === TankopediaDisplay.ShootingRange]);
|
}, [display === TankopediaDisplay.ShootingRange]);
|
||||||
|
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
import { Vector3 } from 'three';
|
||||||
|
|
||||||
|
export const aimTarget = new Vector3();
|
||||||
+8
-5
@@ -24,6 +24,7 @@ import { TankopediaEphemeral } from '../../../../../../../stores/tankopediaEphem
|
|||||||
import { TankopediaPersistent } from '../../../../../../../stores/tankopediaPersistent';
|
import { TankopediaPersistent } from '../../../../../../../stores/tankopediaPersistent';
|
||||||
import { TankopediaDisplay } from '../../../../../../../stores/tankopediaPersistent/constants';
|
import { TankopediaDisplay } from '../../../../../../../stores/tankopediaPersistent/constants';
|
||||||
import { TargetCircle } from './components/TargetCircle';
|
import { TargetCircle } from './components/TargetCircle';
|
||||||
|
import { aimTarget } from './constants';
|
||||||
|
|
||||||
const [modelDefinitions, equipmentDefinitions, provisionDefinitions] =
|
const [modelDefinitions, equipmentDefinitions, provisionDefinitions] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@@ -106,6 +107,8 @@ export function SceneProps() {
|
|||||||
const gunRotationSpeed = degToRad(characteristics.gunTraverseSpeed);
|
const gunRotationSpeed = degToRad(characteristics.gunTraverseSpeed);
|
||||||
const mockTank = useLoader(GLTFLoader, asset(`3d/tanks/models/12305.glb`));
|
const mockTank = useLoader(GLTFLoader, asset(`3d/tanks/models/12305.glb`));
|
||||||
const texture = useLoader(TextureLoader, imgur('C28Z8nU'));
|
const texture = useLoader(TextureLoader, imgur('C28Z8nU'));
|
||||||
|
const path = new Vector3();
|
||||||
|
const direction = new Vector3();
|
||||||
texture.anisotropy = 2;
|
texture.anisotropy = 2;
|
||||||
|
|
||||||
useFrame(({ camera }) => {
|
useFrame(({ camera }) => {
|
||||||
@@ -136,16 +139,16 @@ export function SceneProps() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let length: number;
|
let length: number;
|
||||||
let direction: Vector3;
|
|
||||||
|
|
||||||
if (cameraIntersections.length === 0) {
|
if (cameraIntersections.length === 0) {
|
||||||
length = FAR_DISTANCE;
|
length = FAR_DISTANCE;
|
||||||
direction = new Vector3(0, 0, -1).applyQuaternion(camera.quaternion);
|
direction.set(0, 0, -1).applyQuaternion(camera.quaternion);
|
||||||
|
aimTarget.copy(shellOrigin).addScaledVector(direction, length);
|
||||||
} else {
|
} else {
|
||||||
const target = cameraIntersections[0].point;
|
aimTarget.copy(cameraIntersections[0].point);
|
||||||
const path = target.clone().sub(shellOrigin);
|
path.copy(aimTarget).sub(shellOrigin);
|
||||||
length = path.length();
|
length = path.length();
|
||||||
direction = path.clone().normalize();
|
direction.copy(path).normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
const deltaT = clock.elapsedTime - lastTime;
|
const deltaT = clock.elapsedTime - lastTime;
|
||||||
|
|||||||
Reference in new issue
Block a user