mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-26 03:59:53 +01: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 { clamp } from 'lodash-es';
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import {
|
import {
|
||||||
|
ArrowHelper,
|
||||||
AxesHelper,
|
AxesHelper,
|
||||||
Group,
|
Group,
|
||||||
MeshStandardMaterial,
|
MeshStandardMaterial,
|
||||||
TextureLoader,
|
TextureLoader,
|
||||||
Vector2,
|
Vector2,
|
||||||
|
Vector3,
|
||||||
} from 'three';
|
} 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 { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral';
|
||||||
import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent';
|
import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent';
|
||||||
import { TankopediaDisplay } from '../../../../../../stores/tankopediaPersistent/constants';
|
import { TankopediaDisplay } from '../../../../../../stores/tankopediaPersistent/constants';
|
||||||
|
|
||||||
const emptyVector = new Vector2();
|
const emptyVector = new Vector2();
|
||||||
|
const modelDefinitions = await awaitableModelDefinitions;
|
||||||
|
|
||||||
export function SceneProps() {
|
export function SceneProps() {
|
||||||
const helper = useRef<AxesHelper>(null);
|
const shellTargetHelper = useRef<AxesHelper>(null);
|
||||||
|
const shellPathHelper = useRef<ArrowHelper>(null);
|
||||||
const show = TankopediaPersistent.use(
|
const show = TankopediaPersistent.use(
|
||||||
(state) => state.showGrid && !state.showEnvironment,
|
(state) => state.showGrid && !state.showEnvironment,
|
||||||
);
|
);
|
||||||
@@ -23,6 +31,44 @@ export function SceneProps() {
|
|||||||
const material = useRef<MeshStandardMaterial>(null);
|
const material = useRef<MeshStandardMaterial>(null);
|
||||||
const display = TankopediaEphemeral.use((state) => state.display);
|
const display = TankopediaEphemeral.use((state) => state.display);
|
||||||
const playground = useRef<Group>(null);
|
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 }) => {
|
useFrame(({ camera }) => {
|
||||||
if (!material.current) return;
|
if (!material.current) return;
|
||||||
@@ -31,11 +77,12 @@ export function SceneProps() {
|
|||||||
|
|
||||||
texture.anisotropy = 2;
|
texture.anisotropy = 2;
|
||||||
|
|
||||||
useFrame(({ raycaster, scene, camera }) => {
|
useFrame(({ raycaster, camera, clock }) => {
|
||||||
if (
|
if (
|
||||||
display !== TankopediaDisplay.ShootingRange ||
|
display !== TankopediaDisplay.ShootingRange ||
|
||||||
!playground.current ||
|
!playground.current ||
|
||||||
!helper.current
|
!shellTargetHelper.current ||
|
||||||
|
!shellPathHelper.current
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -49,7 +96,21 @@ export function SceneProps() {
|
|||||||
|
|
||||||
if (intersections.length === 0) return;
|
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 (
|
return (
|
||||||
@@ -63,7 +124,8 @@ export function SceneProps() {
|
|||||||
|
|
||||||
{display === TankopediaDisplay.ShootingRange && (
|
{display === TankopediaDisplay.ShootingRange && (
|
||||||
<>
|
<>
|
||||||
<axesHelper ref={helper} />
|
<axesHelper ref={shellTargetHelper} />
|
||||||
|
<arrowHelper ref={shellPathHelper} position={shellOrigin} />
|
||||||
|
|
||||||
<group ref={playground}>
|
<group ref={playground}>
|
||||||
<mesh rotation={[-Math.PI / 2, 0, 0]} receiveShadow>
|
<mesh rotation={[-Math.PI / 2, 0, 0]} receiveShadow>
|
||||||
@@ -80,6 +142,11 @@ export function SceneProps() {
|
|||||||
<boxGeometry args={[1, 3, 1]} />
|
<boxGeometry args={[1, 3, 1]} />
|
||||||
<meshStandardMaterial color={0xff8040} />
|
<meshStandardMaterial color={0xff8040} />
|
||||||
</mesh>
|
</mesh>
|
||||||
|
|
||||||
|
<mesh position={shellOrigin}>
|
||||||
|
<sphereGeometry args={[0.1, 32, 32]} />
|
||||||
|
<meshStandardMaterial depthTest={false} />
|
||||||
|
</mesh>
|
||||||
</group>
|
</group>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in new issue
Block a user