feat: proper ricochet visuals

This commit is contained in:
TrèsAbhi committed 2024-02-29 10:30:48 -06:00
1 parent 7f49245f15
commit bf6991ce06
2 files changed
+52 -27

No files matched your search

+47 -18
View File
@@ -1,4 +1,4 @@
import { Text } from '@radix-ui/themes'; import { Card, Inset, Text } from '@radix-ui/themes';
import { Html } from '@react-three/drei'; import { Html } from '@react-three/drei';
import { Euler, Quaternion, Vector3 } from 'three'; import { Euler, Quaternion, Vector3 } from 'three';
import { J_HAT } from '../../../constants/axis'; import { J_HAT } from '../../../constants/axis';
@@ -22,9 +22,13 @@ import {
// const THICKNESS = 0.05; // const THICKNESS = 0.05;
// const LENGTH = 4; // const LENGTH = 4;
const LENGTH_INFINITY = 4;
export function ShotDisplay() { export function ShotDisplay() {
const shot = useTankopediaTemporary((state) => state.shot); const shot = useTankopediaTemporary((state) => state.shot);
console.log(shot);
return ( return (
<> <>
{shot?.map((layer, index) => { {shot?.map((layer, index) => {
@@ -44,39 +48,36 @@ export function ShotDisplay() {
position={layer.point} position={layer.point}
rotation={shellRotation} rotation={shellRotation}
> >
{shot.length > 1 && (
<Html center> <Html center>
<div <Card
style={{ style={{
width: 12,
height: 12,
borderRadius: '100%',
position: 'relative',
backgroundColor: backgroundColor:
layer.status === 'penetration' layer.status === 'penetration'
? '#00ff00' ? '#00ff0080'
: layer.status === 'blocked' : layer.status === 'blocked'
? '#ff0000' ? '#ff000080'
: '#ffff00', : '#ffff0080',
border: 'none',
}} }}
> >
<Inset>
{shot.length > 1 && (
<Text <Text
style={{ style={{
position: 'absolute', width: '100%',
left: '100%', display: 'block',
top: '50%', textAlign: 'center',
transform: 'translateY(-50%)',
marginLeft: 8,
}} }}
> >
{layer.index + 1} {layer.index + 1}
</Text> </Text>
</div>
</Html>
)} )}
</Inset>
</Card>
</Html>
{(() => { {(() => {
let length = 4; let length = LENGTH_INFINITY;
if (layer.index !== 0) { if (layer.index !== 0) {
const gap = shot[index - 1] as ShotLayerGap; const gap = shot[index - 1] as ShotLayerGap;
@@ -91,6 +92,34 @@ export function ShotDisplay() {
); );
})()} })()}
</group> </group>
{(() => {
if (layer.status !== 'ricochet' || index !== shot.length - 1)
return null;
const ricochetShellNormal = layer.shellNormal
.clone()
.reflect(layer.surfaceNormal)
.multiplyScalar(-1);
const ricochetShellRotation = new Euler().setFromQuaternion(
new Quaternion().setFromAxisAngle(
new Vector3()
.crossVectors(J_HAT, ricochetShellNormal)
.normalize(),
J_HAT.angleTo(ricochetShellNormal),
),
);
return (
<group position={layer.point} rotation={ricochetShellRotation}>
<mesh position={[0, LENGTH_INFINITY / 2, 0]}>
<cylinderGeometry
args={[1 / 64, 1 / 64, LENGTH_INFINITY]}
/>
<meshBasicMaterial color={0xffffff} depthTest={false} />
</mesh>
</group>
);
})()}
</> </>
); );
})} })}
@@ -170,14 +170,6 @@ export function SpacedArmorSceneComponent({
}); });
} }
console.log(
JSON.stringify(
intersections.map((i) => i.object.userData),
null,
2,
),
);
return intersections; return intersections;
} }
@@ -190,7 +182,7 @@ export function SpacedArmorSceneComponent({
let layerIndex = startingIndex; let layerIndex = startingIndex;
let loopIndex = 0; let loopIndex = 0;
if (layerIndex !== 0) { if (layerIndex !== 0 && intersections.length > 0) {
shot.push({ shot.push({
type: null, type: null,
distance: (shot.at(-1) as ShotLayerBase).point.distanceTo( distance: (shot.at(-1) as ShotLayerBase).point.distanceTo(
@@ -260,6 +252,8 @@ export function SpacedArmorSceneComponent({
status: 'ricochet', status: 'ricochet',
}); });
remainingPenetration *= 0.75;
const raycaster = new Raycaster(); const raycaster = new Raycaster();
const newShellNormal = shellNormal const newShellNormal = shellNormal
.clone() .clone()
@@ -300,6 +294,8 @@ export function SpacedArmorSceneComponent({
} }
} }
console.log('setting', shot);
useTankopediaTemporary.setState({ shot }); useTankopediaTemporary.setState({ shot });
}, },
})} })}