mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: proper ricochet visuals
This commit is contained in:
1 parent
7f49245f15
commit
bf6991ce06
2 files changed
+66
-41
No files matched your search
@@ -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 });
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
|
|||||||
Reference in new issue
Block a user