mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +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 { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||
import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment';
|
||||
import {
|
||||
modelTransformEvent,
|
||||
type ModelTransformEventData,
|
||||
} from '../../../../../../core/blitzkit/modelTransform';
|
||||
import { Pose, poseEvent } from '../../../../../../core/blitzkit/pose';
|
||||
import { Duel } from '../../../../../../stores/duel';
|
||||
import {
|
||||
@@ -16,6 +20,7 @@ import {
|
||||
TankopediaEphemeral,
|
||||
} from '../../../../../../stores/tankopediaEphemeral';
|
||||
import { TankopediaDisplay } from '../../../../../../stores/tankopediaPersistent/constants';
|
||||
import { aimTarget } from './SceneProps/constants';
|
||||
|
||||
const poseDistances: Record<Pose, number> = {
|
||||
[Pose.HullDown]: 15,
|
||||
@@ -199,6 +204,8 @@ export function Controls() {
|
||||
}, [camera, protagonistTank.id, antagonistTank.id]);
|
||||
|
||||
useEffect(() => {
|
||||
let isInitialIteration = true;
|
||||
|
||||
function handleDisturbance() {
|
||||
setAutoRotate(false);
|
||||
}
|
||||
@@ -243,6 +250,8 @@ export function Controls() {
|
||||
document.body.addEventListener('scroll', handleScroll);
|
||||
|
||||
const sniperModeCameraOffset = new Vector3();
|
||||
let pitch = 0;
|
||||
let yaw = 0;
|
||||
|
||||
function updateCamera() {
|
||||
if (!orbitControls.current) return;
|
||||
@@ -261,19 +270,32 @@ export function Controls() {
|
||||
|
||||
if (shootingRangeZoom === ShootingRangeZoom.Arcade) {
|
||||
orbitControls.current.target.set(0, gunHeight + 3, 0);
|
||||
camera.position.set(
|
||||
0,
|
||||
gunHeight + ARCADE_MODE_DISTANCE * Math.sin(ARCADE_MODE_ANGLE),
|
||||
ARCADE_MODE_DISTANCE * Math.cos(ARCADE_MODE_ANGLE),
|
||||
);
|
||||
|
||||
if (isInitialIteration) {
|
||||
isInitialIteration = false;
|
||||
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 {
|
||||
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 {
|
||||
camera.position.set(...inspectModeInitialPosition);
|
||||
orbitControls.current.target.set(0, gunHeight / 2, 0);
|
||||
@@ -285,6 +307,13 @@ export function Controls() {
|
||||
camera.updateProjectionMatrix();
|
||||
}
|
||||
|
||||
function handleModelTransform(event: ModelTransformEventData) {
|
||||
pitch = event.pitch;
|
||||
yaw = event.yaw ?? yaw;
|
||||
}
|
||||
|
||||
modelTransformEvent.on(handleModelTransform);
|
||||
|
||||
updateCamera();
|
||||
|
||||
const unsubscribeDisplay = tankopediaEphemeralStore.subscribe(
|
||||
@@ -308,6 +337,7 @@ export function Controls() {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
canvas.removeEventListener('wheel', handleWheel);
|
||||
document.body.removeEventListener('scroll', handleScroll);
|
||||
modelTransformEvent.off(handleModelTransform);
|
||||
};
|
||||
}, [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 { TankopediaDisplay } from '../../../../../../../stores/tankopediaPersistent/constants';
|
||||
import { TargetCircle } from './components/TargetCircle';
|
||||
import { aimTarget } from './constants';
|
||||
|
||||
const [modelDefinitions, equipmentDefinitions, provisionDefinitions] =
|
||||
await Promise.all([
|
||||
@@ -106,6 +107,8 @@ export function SceneProps() {
|
||||
const gunRotationSpeed = degToRad(characteristics.gunTraverseSpeed);
|
||||
const mockTank = useLoader(GLTFLoader, asset(`3d/tanks/models/12305.glb`));
|
||||
const texture = useLoader(TextureLoader, imgur('C28Z8nU'));
|
||||
const path = new Vector3();
|
||||
const direction = new Vector3();
|
||||
texture.anisotropy = 2;
|
||||
|
||||
useFrame(({ camera }) => {
|
||||
@@ -136,16 +139,16 @@ export function SceneProps() {
|
||||
);
|
||||
|
||||
let length: number;
|
||||
let direction: Vector3;
|
||||
|
||||
if (cameraIntersections.length === 0) {
|
||||
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 {
|
||||
const target = cameraIntersections[0].point;
|
||||
const path = target.clone().sub(shellOrigin);
|
||||
aimTarget.copy(cameraIntersections[0].point);
|
||||
path.copy(aimTarget).sub(shellOrigin);
|
||||
length = path.length();
|
||||
direction = path.clone().normalize();
|
||||
direction.copy(path).normalize();
|
||||
}
|
||||
|
||||
const deltaT = clock.elapsedTime - lastTime;
|
||||
|
||||
Reference in new issue
Block a user