mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
feat: aiming caster
This commit is contained in:
1 parent
5a34a35638
commit
65c52c2e82
3 files changed
+45
-21
No files matched your search
+39
-15
@@ -1,7 +1,7 @@
|
||||
import { OrbitControls } from '@react-three/drei';
|
||||
import { invalidate, useThree } from '@react-three/fiber';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { PerspectiveCamera, Vector3 } from 'three';
|
||||
import { AxesHelper, PerspectiveCamera, Vector2, Vector3 } from 'three';
|
||||
import { OrbitControls as OrbitControlsClass } from 'three-stdlib';
|
||||
import { degToRad } from 'three/src/math/MathUtils.js';
|
||||
import { awaitableModelDefinitions } from '../../../../../../core/awaitables/modelDefinitions';
|
||||
@@ -22,11 +22,13 @@ const modelDefinitions = await awaitableModelDefinitions;
|
||||
|
||||
const ARCADE_MODE_DISTANCE = 16;
|
||||
const ARCADE_MODE_ANGLE = Math.PI / 8;
|
||||
|
||||
export const ARCADE_MODE_FOV = 54;
|
||||
export const INSPECT_MODE_FOV = 25;
|
||||
|
||||
const emptyVector = new Vector2();
|
||||
|
||||
export function Controls() {
|
||||
const helper = useRef<AxesHelper>(null);
|
||||
const display = TankopediaEphemeral.use((state) => state.display);
|
||||
const duelStore = Duel.useStore();
|
||||
const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
|
||||
@@ -79,6 +81,8 @@ export function Controls() {
|
||||
protagonistTurretOrigin.y +
|
||||
protagonistGunOrigin.y;
|
||||
const initialPosition = [-8, gunHeight + 4, -13] as const;
|
||||
const raycaster = useThree((state) => state.raycaster);
|
||||
const scene = useThree((state) => state.scene);
|
||||
|
||||
useEffect(() => {
|
||||
if (!orbitControls.current) return;
|
||||
@@ -232,19 +236,39 @@ export function Controls() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {}, [display]);
|
||||
|
||||
return (
|
||||
<OrbitControls
|
||||
maxDistance={20}
|
||||
minDistance={5}
|
||||
ref={orbitControls}
|
||||
enabled={tankopediaEphemeralStore.getState().controlsEnabled}
|
||||
rotateSpeed={0.25}
|
||||
enableDamping={false}
|
||||
maxPolarAngle={degToRad(100)}
|
||||
autoRotate={autoRotate}
|
||||
autoRotateSpeed={1 / 4}
|
||||
/>
|
||||
<>
|
||||
<axesHelper ref={helper} />
|
||||
<OrbitControls
|
||||
maxDistance={20}
|
||||
minDistance={5}
|
||||
ref={orbitControls}
|
||||
enabled={tankopediaEphemeralStore.getState().controlsEnabled}
|
||||
rotateSpeed={0.25}
|
||||
enableDamping={false}
|
||||
maxPolarAngle={degToRad(100)}
|
||||
autoRotate={autoRotate}
|
||||
autoRotateSpeed={1 / 4}
|
||||
onChange={() => {
|
||||
if (display !== TankopediaDisplay.ShootingRange || !helper.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
raycaster.setFromCamera(emptyVector, camera);
|
||||
|
||||
const intersections = raycaster.intersectObjects(
|
||||
scene.children,
|
||||
true,
|
||||
);
|
||||
const first = intersections.find(
|
||||
(intersection) => intersection.object !== helper.current,
|
||||
);
|
||||
|
||||
if (first === undefined) return;
|
||||
|
||||
helper.current.position.copy(first.point);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
+1
@@ -34,6 +34,7 @@ export function Lighting() {
|
||||
|
||||
{times(LIGHTS_COUNT, (index) => (
|
||||
<directionalLight
|
||||
key={index}
|
||||
castShadow
|
||||
position={[
|
||||
Math.sin(2 * Math.PI * (index / LIGHTS_COUNT)),
|
||||
|
||||
+5
-6
@@ -14,7 +14,6 @@ import { useOnScreen } from '../../../../../hooks/useOnScreen';
|
||||
import { useTankModelDefinition } from '../../../../../hooks/useTankModelDefinition';
|
||||
import { Duel } from '../../../../../stores/duel';
|
||||
import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
|
||||
import { TankopediaPersistent } from '../../../../../stores/tankopediaPersistent';
|
||||
import { TankopediaDisplay } from '../../../../../stores/tankopediaPersistent/constants';
|
||||
import { Armor } from '../../../../Armor';
|
||||
import { ArmorPlateDisplay } from '../../../../Armor/components/ArmorPlateDisplay';
|
||||
@@ -39,15 +38,15 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
|
||||
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
|
||||
const canvas = useRef<HTMLCanvasElement>(null);
|
||||
const hasImprovedVerticalStabilizer = useEquipment(122);
|
||||
const protagonist = Duel.use((state) => state.protagonist);
|
||||
const protagonistGun = Duel.use((state) => state.protagonist.gun);
|
||||
const protagonistTurret = Duel.use((state) => state.protagonist.turret);
|
||||
const mutateDuel = Duel.useMutation();
|
||||
const tankModelDefinition = useTankModelDefinition();
|
||||
const turretModelDefinition =
|
||||
tankModelDefinition.turrets[protagonist.turret.id];
|
||||
tankModelDefinition.turrets[protagonistTurret.id];
|
||||
const gunModelDefinition =
|
||||
turretModelDefinition.guns[protagonist.gun.gun_type!.value.base.id];
|
||||
turretModelDefinition.guns[protagonistGun.gun_type!.value.base.id];
|
||||
const display = TankopediaEphemeral.use((state) => state.display);
|
||||
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
||||
const onScreen = useOnScreen(canvas);
|
||||
|
||||
useImperativeHandle(ref, () => canvas.current!, []);
|
||||
@@ -141,7 +140,7 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
|
||||
hasImprovedVerticalStabilizer,
|
||||
);
|
||||
});
|
||||
}, [protagonist.gun, protagonist.turret]);
|
||||
}, [protagonistGun, protagonistTurret]);
|
||||
|
||||
useEffect(() => {
|
||||
if (display !== TankopediaDisplay.DynamicArmor) {
|
||||
|
||||
Reference in new issue
Block a user