mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
feat: elevation
This commit is contained in:
1 parent
e6029157aa
commit
6b7f8049fe
6 files changed
+105
-41
No files matched your search
+4
-3
@@ -1,6 +1,6 @@
|
|||||||
import type { AssaultRanges } from '@blitzkit/core';
|
import type { AssaultRanges } from '@blitzkit/core';
|
||||||
import { literals } from '@blitzkit/i18n';
|
import { literals } from '@blitzkit/i18n';
|
||||||
import { Box, Card, Flex, Text } from '@radix-ui/themes';
|
import { Box, Flex, Text } from '@radix-ui/themes';
|
||||||
import { clamp } from 'three/src/math/MathUtils.js';
|
import { clamp } from 'three/src/math/MathUtils.js';
|
||||||
import {
|
import {
|
||||||
fakeLogSquishyHigh,
|
fakeLogSquishyHigh,
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
import type { TankCharacteristics } from '../../../../../../../core/blitzkit/tankCharacteristics';
|
import type { TankCharacteristics } from '../../../../../../../core/blitzkit/tankCharacteristics';
|
||||||
import { Var } from '../../../../../../../core/radix/var';
|
import { Var } from '../../../../../../../core/radix/var';
|
||||||
import { useLocale } from '../../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||||
|
import { VisualizerCard } from '../VisualizerCard';
|
||||||
import { AssaultCursor } from './components/Cursor';
|
import { AssaultCursor } from './components/Cursor';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -29,7 +30,7 @@ export function AssaultRangesVisualizer({ ranges: _ranges, stats }: Props) {
|
|||||||
const { strings } = useLocale();
|
const { strings } = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card mb="6" variant="classic" style={{ aspectRatio: '1 / 1' }}>
|
<VisualizerCard>
|
||||||
<Flex
|
<Flex
|
||||||
position="absolute"
|
position="absolute"
|
||||||
top="0"
|
top="0"
|
||||||
@@ -152,6 +153,6 @@ export function AssaultRangesVisualizer({ ranges: _ranges, stats }: Props) {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Card>
|
</VisualizerCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
+71
-22
@@ -1,14 +1,14 @@
|
|||||||
import { Card } from '@radix-ui/themes';
|
|
||||||
import { awaitableModelDefinitions } from '../../../../../../../core/awaitables/modelDefinitions';
|
import { awaitableModelDefinitions } from '../../../../../../../core/awaitables/modelDefinitions';
|
||||||
import { DEFAULT_PITCH_TRANSITION } from '../../../../../../../core/blitz/applyPitchYawLimits';
|
import { DEFAULT_PITCH_TRANSITION } from '../../../../../../../core/blitz/applyPitchYawLimits';
|
||||||
import { Duel } from '../../../../../../../stores/duel';
|
import { Duel } from '../../../../../../../stores/duel';
|
||||||
|
import { VisualizerCard } from '../VisualizerCard';
|
||||||
|
|
||||||
const MAX_MAG = 20;
|
const ANGLE_COEFFICIENT = 1 / 10;
|
||||||
|
|
||||||
const modelDefinition = await awaitableModelDefinitions;
|
const modelDefinition = await awaitableModelDefinitions;
|
||||||
|
|
||||||
function mag(x: number) {
|
function mag(x: number) {
|
||||||
return (x / MAX_MAG + 1) / 2;
|
return ((2 / Math.PI) * Math.atan(ANGLE_COEFFICIENT * x) + 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
function c(thetaDeg: number, m = 1) {
|
function c(thetaDeg: number, m = 1) {
|
||||||
@@ -34,18 +34,18 @@ export function GunFlexibilityVisualizer() {
|
|||||||
let d = '';
|
let d = '';
|
||||||
|
|
||||||
// right
|
// right
|
||||||
const ms = mag(p.max);
|
const mo = mag(p.max);
|
||||||
if (y) {
|
if (y) {
|
||||||
d += `M ${c(90 - y.max, ms)}`;
|
d += `M ${c(90 - y.max, mo)}`;
|
||||||
} else if (b) {
|
} else if (b) {
|
||||||
d += `M ${c(-90 + b.range / 2 + t, ms)}`;
|
d += `M ${c(-90 + b.range / 2 + t, mo)}`;
|
||||||
} else {
|
} else {
|
||||||
d += `M ${c(-90 / 2, ms)}`;
|
d += `M ${c(-90 / 2, mo)}`;
|
||||||
}
|
}
|
||||||
if (f) {
|
if (f) {
|
||||||
d += `A ${ms} ${ms} 0 0 0 ${c(90 - f.range / 2 - t, ms)}`;
|
d += `A ${mo} ${mo} 0 0 0 ${c(90 - f.range / 2 - t, mo)}`;
|
||||||
} else {
|
} else {
|
||||||
d += `A ${ms} ${ms} 0 0 0 ${c(90 / 2, ms)}`;
|
d += `A ${mo} ${mo} 0 0 0 ${c(90 / 2, mo)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// front
|
// front
|
||||||
@@ -57,16 +57,16 @@ export function GunFlexibilityVisualizer() {
|
|||||||
|
|
||||||
// left
|
// left
|
||||||
if (f) {
|
if (f) {
|
||||||
d += `L ${c(90 + f.range / 2 + t, ms)}`;
|
d += `L ${c(90 + f.range / 2 + t, mo)}`;
|
||||||
} else {
|
} else {
|
||||||
d += `L ${c(90 / 2, ms)}`;
|
d += `L ${c(90 / 2, mo)}`;
|
||||||
}
|
}
|
||||||
if (y) {
|
if (y) {
|
||||||
d += `A ${ms} ${ms} 0 0 0 ${c(90 - y.min, ms)}`;
|
d += `A ${mo} ${mo} 0 0 0 ${c(90 - y.min, mo)}`;
|
||||||
} else if (b) {
|
} else if (b) {
|
||||||
d += `A ${ms} ${ms} 0 0 0 ${c(-90 - b.range / 2 - t, ms)}`;
|
d += `A ${mo} ${mo} 0 0 0 ${c(-90 - b.range / 2 - t, mo)}`;
|
||||||
} else {
|
} else {
|
||||||
d += `A ${ms} ${ms} 0 0 0 ${c(-90 / 2, ms)}`;
|
d += `A ${mo} ${mo} 0 0 0 ${c(-90 / 2, mo)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// back
|
// back
|
||||||
@@ -78,8 +78,53 @@ export function GunFlexibilityVisualizer() {
|
|||||||
|
|
||||||
d += `Z`;
|
d += `Z`;
|
||||||
|
|
||||||
|
// right
|
||||||
|
const mi = mag(p.min);
|
||||||
|
if (y) {
|
||||||
|
d += `M ${c(90 - y.max, mi)}`;
|
||||||
|
} else if (b) {
|
||||||
|
d += `M ${c(-90 + b.range / 2 + t, mi)}`;
|
||||||
|
} else {
|
||||||
|
d += `M ${c(-90 / 2, mi)}`;
|
||||||
|
}
|
||||||
|
if (f) {
|
||||||
|
d += `A ${mi} ${mi} 0 0 0 ${c(90 - f.range / 2 - t, mi)}`;
|
||||||
|
} else {
|
||||||
|
d += `A ${mi} ${mi} 0 0 0 ${c(90 / 2, mi)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// front
|
||||||
|
if (f) {
|
||||||
|
const m = mag(f.min);
|
||||||
|
d += `L ${c(90 - f.range / 2, m)}`;
|
||||||
|
d += `A ${m} ${m} 0 0 0 ${c(90 + f.range / 2, m)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// left
|
||||||
|
if (f) {
|
||||||
|
d += `L ${c(90 + f.range / 2 + t, mi)}`;
|
||||||
|
} else {
|
||||||
|
d += `L ${c(90 / 2, mi)}`;
|
||||||
|
}
|
||||||
|
if (y) {
|
||||||
|
d += `A ${mi} ${mi} 0 0 0 ${c(90 - y.min, mi)}`;
|
||||||
|
} else if (b) {
|
||||||
|
d += `A ${mi} ${mi} 0 0 0 ${c(-90 - b.range / 2 - t, mi)}`;
|
||||||
|
} else {
|
||||||
|
d += `A ${mi} ${mi} 0 0 0 ${c(-90 / 2, mi)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// back
|
||||||
|
if (!y && b) {
|
||||||
|
const m = mag(b.min);
|
||||||
|
d += `L ${c(-90 - b.range / 2, m)}`;
|
||||||
|
d += `A ${m} ${m} 0 0 0 ${c(-90 + b.range / 2, m)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
d += `Z`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card style={{ aspectRatio: '1 / 1' }} variant="classic">
|
<VisualizerCard>
|
||||||
<svg
|
<svg
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@@ -91,19 +136,23 @@ export function GunFlexibilityVisualizer() {
|
|||||||
viewBox="-1 -1 2 2"
|
viewBox="-1 -1 2 2"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
stroke="var(--gray-11)"
|
fillRule="evenodd"
|
||||||
strokeWidth="0.01px"
|
fill="var(--gray-5)"
|
||||||
fill="var(--gray-9)"
|
stroke="var(--gray-7)"
|
||||||
|
strokeWidth="1px"
|
||||||
|
vectorEffect="non-scaling-stroke"
|
||||||
d={d}
|
d={d}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<path
|
<path
|
||||||
stroke="var(--gray-2)"
|
stroke="var(--gray-10)"
|
||||||
fill="transparent"
|
fill="transparent"
|
||||||
strokeWidth="0.01px"
|
strokeWidth="1px"
|
||||||
strokeDasharray="0.05 0.01"
|
strokeDasharray="0.5rem 0.5rem"
|
||||||
|
vectorEffect="non-scaling-stroke"
|
||||||
d="M 0.5 0 A 0.5 0.5 0 1 1 -0.5 0 A 0.5 0.5 0 1 1 0.5 0 Z"
|
d="M 0.5 0 A 0.5 0.5 0 1 1 -0.5 0 A 0.5 0.5 0 1 1 0.5 0 Z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</Card>
|
</VisualizerCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
+4
-4
@@ -1,10 +1,11 @@
|
|||||||
import { type Datum, type Serie } from '@nivo/line';
|
import { type Datum, type Serie } from '@nivo/line';
|
||||||
import { Box, Card } from '@radix-ui/themes';
|
import { Box } from '@radix-ui/themes';
|
||||||
import { times } from 'lodash-es';
|
import { times } from 'lodash-es';
|
||||||
import { Quicklime, type QuicklimeCallback } from 'quicklime';
|
import { Quicklime, type QuicklimeCallback } from 'quicklime';
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { Var } from '../../../../../../../core/radix/var';
|
import { Var } from '../../../../../../../core/radix/var';
|
||||||
import type { StatsAcceptorProps } from '../TraverseVisualizer';
|
import type { StatsAcceptorProps } from '../TraverseVisualizer';
|
||||||
|
import { VisualizerCard } from '../VisualizerCard';
|
||||||
import { Shell } from './components/Shell';
|
import { Shell } from './components/Shell';
|
||||||
import { Target } from './components/Target';
|
import { Target } from './components/Target';
|
||||||
|
|
||||||
@@ -51,7 +52,6 @@ export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function frame() {
|
function frame() {
|
||||||
|
|
||||||
const now = Date.now() / 1000;
|
const now = Date.now() / 1000;
|
||||||
const dt = now - lastT;
|
const dt = now - lastT;
|
||||||
let reload;
|
let reload;
|
||||||
@@ -130,7 +130,7 @@ export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card variant="classic" mb="6" style={{ aspectRatio: '1 / 1' }}>
|
<VisualizerCard>
|
||||||
<Box position="absolute" top="0" left="0" width="100%" height="100%">
|
<Box position="absolute" top="0" left="0" width="100%" height="100%">
|
||||||
<Target />
|
<Target />
|
||||||
|
|
||||||
@@ -220,6 +220,6 @@ export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
times(stats.shells, (index) => (
|
times(stats.shells, (index) => (
|
||||||
<Shell stats={stats} index={index} key={index} />
|
<Shell stats={stats} index={index} key={index} />
|
||||||
))}
|
))}
|
||||||
</Card>
|
</VisualizerCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
+5
-9
@@ -1,12 +1,13 @@
|
|||||||
import { asset, isExplosive } from '@blitzkit/core';
|
import { asset, isExplosive } from '@blitzkit/core';
|
||||||
import { literals } from '@blitzkit/i18n';
|
import { literals } from '@blitzkit/i18n';
|
||||||
import { Box, Card, Code, Flex, Text } from '@radix-ui/themes';
|
import { Box, Code, Flex, Text } from '@radix-ui/themes';
|
||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import { clamp, degToRad, radToDeg } from 'three/src/math/MathUtils.js';
|
import { clamp, degToRad, radToDeg } from 'three/src/math/MathUtils.js';
|
||||||
import { Var } from '../../../../../../../core/radix/var';
|
import { Var } from '../../../../../../../core/radix/var';
|
||||||
import { useLocale } from '../../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||||
import { Duel } from '../../../../../../../stores/duel';
|
import { Duel } from '../../../../../../../stores/duel';
|
||||||
import type { StatsAcceptorProps } from '../TraverseVisualizer';
|
import type { StatsAcceptorProps } from '../TraverseVisualizer';
|
||||||
|
import { VisualizerCard } from '../VisualizerCard';
|
||||||
import { ShellSwitcher } from './components/ShellSwitcher';
|
import { ShellSwitcher } from './components/ShellSwitcher';
|
||||||
|
|
||||||
export function RicochetVisualizer({ stats }: StatsAcceptorProps) {
|
export function RicochetVisualizer({ stats }: StatsAcceptorProps) {
|
||||||
@@ -26,13 +27,8 @@ export function RicochetVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex direction="column" mb="6" align="center">
|
<Flex direction="column" mb="6" align="center">
|
||||||
<Card
|
<VisualizerCard
|
||||||
variant="classic"
|
style={{ width: '100%' }}
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
aspectRatio: '1 / 1',
|
|
||||||
touchAction: 'none',
|
|
||||||
}}
|
|
||||||
ref={container}
|
ref={container}
|
||||||
onPointerMove={(event) => {
|
onPointerMove={(event) => {
|
||||||
if (!container.current || explodes) return;
|
if (!container.current || explodes) return;
|
||||||
@@ -262,7 +258,7 @@ export function RicochetVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</VisualizerCard>
|
||||||
|
|
||||||
<ShellSwitcher />
|
<ShellSwitcher />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
+4
-3
@@ -1,8 +1,9 @@
|
|||||||
import { literals } from '@blitzkit/i18n';
|
import { literals } from '@blitzkit/i18n';
|
||||||
import { Card, Checkbox, Code, Flex, Tabs, Text } from '@radix-ui/themes';
|
import { Checkbox, Code, Flex, Tabs, Text } from '@radix-ui/themes';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import type { TankCharacteristics } from '../../../../../../../core/blitzkit/tankCharacteristics';
|
import type { TankCharacteristics } from '../../../../../../../core/blitzkit/tankCharacteristics';
|
||||||
import { useLocale } from '../../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||||
|
import { VisualizerCard } from '../VisualizerCard';
|
||||||
|
|
||||||
export interface StatsAcceptorProps {
|
export interface StatsAcceptorProps {
|
||||||
stats: TankCharacteristics;
|
stats: TankCharacteristics;
|
||||||
@@ -58,7 +59,7 @@ export function TraverseVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
}, [terrain, turretSpeedDeg, hullSpeedDeg]);
|
}, [terrain, turretSpeedDeg, hullSpeedDeg]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card variant="classic" style={{ aspectRatio: '1 / 1' }}>
|
<VisualizerCard>
|
||||||
<div
|
<div
|
||||||
ref={hull}
|
ref={hull}
|
||||||
style={{
|
style={{
|
||||||
@@ -188,6 +189,6 @@ export function TraverseVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</VisualizerCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
import { Card, type CardProps } from '@radix-ui/themes';
|
||||||
|
import { forwardRef } from 'react';
|
||||||
|
|
||||||
|
export const VisualizerCard = forwardRef<HTMLDivElement, CardProps>(
|
||||||
|
({ style, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
ref={ref}
|
||||||
|
variant="classic"
|
||||||
|
mt="4"
|
||||||
|
mb="6"
|
||||||
|
style={{ aspectRatio: '1 / 1', ...style }}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
Reference in new issue
Block a user