mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: turret moment
This commit is contained in:
1 parent
7f9a54ef85
commit
e5ddbc7297
1 file changed
+72
-5
+72
-5
@@ -2,20 +2,28 @@ import { useFrame, useLoader } from '@react-three/fiber';
|
||||
import { clamp } from 'lodash-es';
|
||||
import { useRef } from 'react';
|
||||
import {
|
||||
ArrowHelper,
|
||||
AxesHelper,
|
||||
Group,
|
||||
MeshStandardMaterial,
|
||||
TextureLoader,
|
||||
Vector2,
|
||||
Vector3,
|
||||
} from 'three';
|
||||
import { awaitableModelDefinitions } from '../../../../../../core/awaitables/modelDefinitions';
|
||||
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||
import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform';
|
||||
import { Duel } from '../../../../../../stores/duel';
|
||||
import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral';
|
||||
import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent';
|
||||
import { TankopediaDisplay } from '../../../../../../stores/tankopediaPersistent/constants';
|
||||
|
||||
const emptyVector = new Vector2();
|
||||
const modelDefinitions = await awaitableModelDefinitions;
|
||||
|
||||
export function SceneProps() {
|
||||
const helper = useRef<AxesHelper>(null);
|
||||
const shellTargetHelper = useRef<AxesHelper>(null);
|
||||
const shellPathHelper = useRef<ArrowHelper>(null);
|
||||
const show = TankopediaPersistent.use(
|
||||
(state) => state.showGrid && !state.showEnvironment,
|
||||
);
|
||||
@@ -23,6 +31,44 @@ export function SceneProps() {
|
||||
const material = useRef<MeshStandardMaterial>(null);
|
||||
const display = TankopediaEphemeral.use((state) => state.display);
|
||||
const playground = useRef<Group>(null);
|
||||
const protagonistTurret = Duel.use((state) => state.protagonist.turret);
|
||||
const protagonistTrack = Duel.use((state) => state.protagonist.track);
|
||||
const protagonistTank = Duel.use((state) => state.protagonist.tank);
|
||||
const protagonistGun = Duel.use((state) => state.protagonist.gun);
|
||||
const protagonistModelDefinition =
|
||||
modelDefinitions.models[protagonistTank.id];
|
||||
const protagonistTrackModelDefinition =
|
||||
modelDefinitions.models[protagonistTank.id].tracks[protagonistTrack.id];
|
||||
const protagonistGunModelDefinition =
|
||||
protagonistModelDefinition.turrets[protagonistTurret.id].guns[
|
||||
protagonistGun.gun_type!.value.base.id
|
||||
];
|
||||
const protagonistTurretModelDefinition =
|
||||
protagonistModelDefinition.turrets[protagonistTurret.id];
|
||||
const protagonistHullOrigin = new Vector3(
|
||||
protagonistTrackModelDefinition.origin.x,
|
||||
protagonistTrackModelDefinition.origin.y,
|
||||
-protagonistTrackModelDefinition.origin.z,
|
||||
);
|
||||
const protagonistTurretOrigin = new Vector3(
|
||||
protagonistModelDefinition.turret_origin.x,
|
||||
protagonistModelDefinition.turret_origin.y,
|
||||
-protagonistModelDefinition.turret_origin.z,
|
||||
);
|
||||
const protagonistGunOrigin = new Vector3(
|
||||
protagonistTurretModelDefinition.gun_origin.x,
|
||||
protagonistTurretModelDefinition.gun_origin.y,
|
||||
-protagonistTurretModelDefinition.gun_origin.z,
|
||||
);
|
||||
const protagonistGunOriginOnlyY = new Vector3(
|
||||
0,
|
||||
protagonistTurretModelDefinition.gun_origin.y,
|
||||
0,
|
||||
);
|
||||
const shellOrigin = new Vector3()
|
||||
.add(protagonistHullOrigin)
|
||||
.add(protagonistTurretOrigin)
|
||||
.add(protagonistGunOriginOnlyY);
|
||||
|
||||
useFrame(({ camera }) => {
|
||||
if (!material.current) return;
|
||||
@@ -31,11 +77,12 @@ export function SceneProps() {
|
||||
|
||||
texture.anisotropy = 2;
|
||||
|
||||
useFrame(({ raycaster, scene, camera }) => {
|
||||
useFrame(({ raycaster, camera, clock }) => {
|
||||
if (
|
||||
display !== TankopediaDisplay.ShootingRange ||
|
||||
!playground.current ||
|
||||
!helper.current
|
||||
!shellTargetHelper.current ||
|
||||
!shellPathHelper.current
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -49,7 +96,21 @@ export function SceneProps() {
|
||||
|
||||
if (intersections.length === 0) return;
|
||||
|
||||
helper.current.position.copy(intersections[0].point);
|
||||
const target = intersections[0].point;
|
||||
const path = target.clone().sub(shellOrigin);
|
||||
const direction = path.clone().normalize();
|
||||
|
||||
shellTargetHelper.current.position.copy(intersections[0].point);
|
||||
shellPathHelper.current.setDirection(direction);
|
||||
shellPathHelper.current.setLength(path.length());
|
||||
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
Math.asin(direction.y),
|
||||
Math.atan2(-direction.x, -direction.z),
|
||||
protagonistGunModelDefinition.pitch,
|
||||
);
|
||||
|
||||
modelTransformEvent.emit({ pitch, yaw });
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -63,7 +124,8 @@ export function SceneProps() {
|
||||
|
||||
{display === TankopediaDisplay.ShootingRange && (
|
||||
<>
|
||||
<axesHelper ref={helper} />
|
||||
<axesHelper ref={shellTargetHelper} />
|
||||
<arrowHelper ref={shellPathHelper} position={shellOrigin} />
|
||||
|
||||
<group ref={playground}>
|
||||
<mesh rotation={[-Math.PI / 2, 0, 0]} receiveShadow>
|
||||
@@ -80,6 +142,11 @@ export function SceneProps() {
|
||||
<boxGeometry args={[1, 3, 1]} />
|
||||
<meshStandardMaterial color={0xff8040} />
|
||||
</mesh>
|
||||
|
||||
<mesh position={shellOrigin}>
|
||||
<sphereGeometry args={[0.1, 32, 32]} />
|
||||
<meshStandardMaterial depthTest={false} />
|
||||
</mesh>
|
||||
</group>
|
||||
</>
|
||||
)}
|
||||
|
||||
Reference in new issue
Block a user