mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
feat: separate target circle
This commit is contained in:
1 parent
26d3bdaac7
commit
20f54a39d6
2 files changed
+62
-50
No files matched your search
+37
@@ -0,0 +1,37 @@
|
|||||||
|
import { imgur } from '@blitzkit/core';
|
||||||
|
import { Box, type BoxProps } from '@radix-ui/themes';
|
||||||
|
import { forwardRef } from 'react';
|
||||||
|
import { Var } from '../../../../../../../../core/radix/var';
|
||||||
|
|
||||||
|
export const TargetCircle = forwardRef<HTMLDivElement, BoxProps>(
|
||||||
|
({ style, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
ref={ref}
|
||||||
|
width="10em"
|
||||||
|
height="10em"
|
||||||
|
style={{
|
||||||
|
borderRadius: '50%',
|
||||||
|
border: `0.125rem solid ${Var('green-9')}`,
|
||||||
|
...style,
|
||||||
|
}}
|
||||||
|
position="relative"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
width="1rem"
|
||||||
|
height="1rem"
|
||||||
|
position="absolute"
|
||||||
|
top="50%"
|
||||||
|
left="50%"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url(${imgur('kU9Xejd')})`,
|
||||||
|
backgroundSize: 'contain',
|
||||||
|
transform: 'translateX(-50%) scale(90%)',
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
+25
-50
@@ -1,5 +1,4 @@
|
|||||||
import { asset, I_HAT, imgur, J_HAT } from '@blitzkit/core';
|
import { asset, I_HAT, imgur, J_HAT } from '@blitzkit/core';
|
||||||
import { Box } from '@radix-ui/themes';
|
|
||||||
import { Html } from '@react-three/drei';
|
import { Html } from '@react-three/drei';
|
||||||
import { useFrame, useLoader } from '@react-three/fiber';
|
import { useFrame, useLoader } from '@react-three/fiber';
|
||||||
import { clamp } from 'lodash-es';
|
import { clamp } from 'lodash-es';
|
||||||
@@ -14,17 +13,17 @@ import {
|
|||||||
} from 'three';
|
} from 'three';
|
||||||
import { GLTFLoader } from 'three/examples/jsm/Addons.js';
|
import { GLTFLoader } from 'three/examples/jsm/Addons.js';
|
||||||
import { degToRad } from 'three/src/math/MathUtils.js';
|
import { degToRad } from 'three/src/math/MathUtils.js';
|
||||||
import { awaitableEquipmentDefinitions } from '../../../../../../core/awaitables/equipmentDefinitions';
|
import { awaitableEquipmentDefinitions } from '../../../../../../../core/awaitables/equipmentDefinitions';
|
||||||
import { awaitableModelDefinitions } from '../../../../../../core/awaitables/modelDefinitions';
|
import { awaitableModelDefinitions } from '../../../../../../../core/awaitables/modelDefinitions';
|
||||||
import { awaitableProvisionDefinitions } from '../../../../../../core/awaitables/provisionDefinitions';
|
import { awaitableProvisionDefinitions } from '../../../../../../../core/awaitables/provisionDefinitions';
|
||||||
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits';
|
||||||
import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform';
|
import { modelTransformEvent } from '../../../../../../../core/blitzkit/modelTransform';
|
||||||
import { tankCharacteristics } from '../../../../../../core/blitzkit/tankCharacteristics';
|
import { tankCharacteristics } from '../../../../../../../core/blitzkit/tankCharacteristics';
|
||||||
import { Var } from '../../../../../../core/radix/var';
|
import { Duel } from '../../../../../../../stores/duel';
|
||||||
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';
|
import { TargetCircle } from './components/TargetCircle';
|
||||||
|
|
||||||
const [modelDefinitions, equipmentDefinitions, provisionDefinitions] =
|
const [modelDefinitions, equipmentDefinitions, provisionDefinitions] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@@ -40,17 +39,14 @@ export function SceneProps() {
|
|||||||
const show = TankopediaPersistent.use(
|
const show = TankopediaPersistent.use(
|
||||||
(state) => state.showGrid && !state.showEnvironment,
|
(state) => state.showGrid && !state.showEnvironment,
|
||||||
);
|
);
|
||||||
const targetCircle = useRef<Group>(null);
|
const targetCircleWrapper = useRef<Group>(null);
|
||||||
const targetCircleDots = useRef<HTMLDivElement>(null);
|
const targetCircle = useRef<HTMLDivElement>(null);
|
||||||
const texture = useLoader(TextureLoader, imgur('C28Z8nU'));
|
const material = useRef<MeshStandardMaterial>(null);
|
||||||
|
const playground = useRef<Group>(null);
|
||||||
texture.anisotropy = 2;
|
|
||||||
|
|
||||||
let lastPitch = Duel.use((state) => state.protagonist.pitch);
|
let lastPitch = Duel.use((state) => state.protagonist.pitch);
|
||||||
let lastYaw = Duel.use((state) => state.protagonist.yaw);
|
let lastYaw = Duel.use((state) => state.protagonist.yaw);
|
||||||
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 turret = Duel.use((state) => state.protagonist.turret);
|
const turret = Duel.use((state) => state.protagonist.turret);
|
||||||
const track = Duel.use((state) => state.protagonist.track);
|
const track = Duel.use((state) => state.protagonist.track);
|
||||||
const tank = Duel.use((state) => state.protagonist.tank);
|
const tank = Duel.use((state) => state.protagonist.tank);
|
||||||
@@ -110,7 +106,10 @@ export function SceneProps() {
|
|||||||
},
|
},
|
||||||
{ equipmentDefinitions, provisionDefinitions, tankModelDefinition },
|
{ equipmentDefinitions, provisionDefinitions, tankModelDefinition },
|
||||||
);
|
);
|
||||||
|
|
||||||
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'));
|
||||||
|
texture.anisotropy = 2;
|
||||||
|
|
||||||
useFrame(({ camera }) => {
|
useFrame(({ camera }) => {
|
||||||
if (!material.current) return;
|
if (!material.current) return;
|
||||||
@@ -124,9 +123,9 @@ export function SceneProps() {
|
|||||||
if (
|
if (
|
||||||
display !== TankopediaDisplay.ShootingRange ||
|
display !== TankopediaDisplay.ShootingRange ||
|
||||||
!playground.current ||
|
!playground.current ||
|
||||||
!targetCircle.current ||
|
!targetCircleWrapper.current ||
|
||||||
DEBUG_disable ||
|
DEBUG_disable ||
|
||||||
!targetCircleDots.current
|
!targetCircle.current
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -196,14 +195,13 @@ export function SceneProps() {
|
|||||||
gunTarget = gunIntersections[0].point;
|
gunTarget = gunIntersections[0].point;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetCircle.current.position.copy(gunTarget);
|
targetCircleWrapper.current.position.copy(gunTarget);
|
||||||
|
|
||||||
const distanceToTarget = gunTarget.distanceTo(shellOrigin);
|
const distanceToTarget = gunTarget.distanceTo(shellOrigin);
|
||||||
const dispersionRadius =
|
const dispersionRadius =
|
||||||
characteristics.dispersion * (distanceToTarget / 100);
|
characteristics.dispersion * (distanceToTarget / 100);
|
||||||
const dispersionSize = 2 * dispersionRadius;
|
const dispersionSize = 2 * dispersionRadius;
|
||||||
const targetDistanceFromCamera = gunTarget.distanceTo(camera.position);
|
const targetDistanceFromCamera = gunTarget.distanceTo(camera.position);
|
||||||
document.title = `${targetDistanceFromCamera}`;
|
|
||||||
const angularSize =
|
const angularSize =
|
||||||
2 * Math.atan(dispersionSize / (2 * targetDistanceFromCamera));
|
2 * Math.atan(dispersionSize / (2 * targetDistanceFromCamera));
|
||||||
const verticalScreenSize =
|
const verticalScreenSize =
|
||||||
@@ -212,8 +210,8 @@ export function SceneProps() {
|
|||||||
gl.domElement.clientHeight * (angularSize / verticalScreenSize);
|
gl.domElement.clientHeight * (angularSize / verticalScreenSize);
|
||||||
const targetCircleDotsSize = `${Math.max(38, screenSpaceSize)}px`;
|
const targetCircleDotsSize = `${Math.max(38, screenSpaceSize)}px`;
|
||||||
|
|
||||||
targetCircleDots.current.style.width = targetCircleDotsSize;
|
targetCircle.current.style.width = targetCircleDotsSize;
|
||||||
targetCircleDots.current.style.height = targetCircleDotsSize;
|
targetCircle.current.style.height = targetCircleDotsSize;
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -227,32 +225,9 @@ export function SceneProps() {
|
|||||||
|
|
||||||
{display === TankopediaDisplay.ShootingRange && (
|
{display === TankopediaDisplay.ShootingRange && (
|
||||||
<>
|
<>
|
||||||
<group ref={targetCircle}>
|
<group ref={targetCircleWrapper}>
|
||||||
<Html center occlude={false} zIndexRange={[0, 0]}>
|
<Html center occlude={false} zIndexRange={[0, 0]}>
|
||||||
<Box
|
<TargetCircle ref={targetCircle} />
|
||||||
ref={targetCircleDots}
|
|
||||||
width="10em"
|
|
||||||
height="10em"
|
|
||||||
style={{
|
|
||||||
borderRadius: '50%',
|
|
||||||
border: `0.125rem solid ${Var('green-9')}`,
|
|
||||||
}}
|
|
||||||
position="relative"
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
width="1rem"
|
|
||||||
height="1rem"
|
|
||||||
position="absolute"
|
|
||||||
top="50%"
|
|
||||||
left="50%"
|
|
||||||
style={{
|
|
||||||
backgroundImage: `url(${imgur('kU9Xejd')})`,
|
|
||||||
backgroundSize: 'contain',
|
|
||||||
transform: 'translateX(-50%) scale(90%)',
|
|
||||||
borderRadius: '50%',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Html>
|
</Html>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
Reference in new issue
Block a user