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
+66 -41

No files matched your search

+61 -32
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> <Card
<div style={{
style={{ backgroundColor:
width: 12, layer.status === 'penetration'
height: 12, ? '#00ff0080'
borderRadius: '100%', : layer.status === 'blocked'
position: 'relative', ? '#ff000080'
backgroundColor: : '#ffff0080',
layer.status === 'penetration' border: 'none',
? '#00ff00' }}
: layer.status === 'blocked' >
? '#ff0000' <Inset>
: '#ffff00', {shot.length > 1 && (
}} <Text
> style={{
<Text width: '100%',
style={{ display: 'block',
position: 'absolute', textAlign: 'center',
left: '100%', }}
top: '50%', >
transform: 'translateY(-50%)', {layer.index + 1}
marginLeft: 8, </Text>
}} )}
> </Inset>
{layer.index + 1} </Card>
</Text> </Html>
</div>
</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 });
}, },
})} })}