feat: animations

This commit is contained in:
tresabhi committed 2025-04-22 00:50:14 -05:00
1 parent 35073c184e
commit 22d794ac65
5 files changed
+290 -126

No files matched your search

+2 -1
View File
@@ -871,7 +871,8 @@
},
"ricochet": {
"max": "Max: %s1°"
"safe": "Safe %s1°",
"unsafe": "Unsafe %s1°"
}
},
+11 -11
View File
@@ -1,14 +1,14 @@
// @ts-check
import partytown from "@astrojs/partytown";
import react from "@astrojs/react";
import sitemap from "@astrojs/sitemap";
import { SUPPORTED_LOCALES } from "@blitzkit/i18n";
import { defineConfig } from "astro/config";
import partytown from '@astrojs/partytown';
import react from '@astrojs/react';
import sitemap from '@astrojs/sitemap';
import { SUPPORTED_LOCALES } from '@blitzkit/i18n';
import { defineConfig } from 'astro/config';
export default defineConfig({
i18n: {
defaultLocale: "en",
defaultLocale: 'en',
locales: [...SUPPORTED_LOCALES],
routing: {
prefixDefaultLocale: false,
@@ -16,17 +16,17 @@ export default defineConfig({
},
devToolbar: { enabled: false },
output: "static",
site: "https://blitzkit.app",
outDir: "../../dist/website",
output: 'static',
site: 'https://blitzkit.app',
outDir: '../../dist/website',
prefetch: true,
integrations: [react(), sitemap(), partytown()],
vite: {
resolve: {
alias: {
".prisma/client/index-browser":
"../../node_modules/.prisma/client/index-browser.js",
'.prisma/client/index-browser':
'../../node_modules/.prisma/client/index-browser.js',
},
},
ssr: {
@@ -1,114 +0,0 @@
import { asset } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { Box, Card, Text } from '@radix-ui/themes';
import { Var } from '../../../../../../core/radix/var';
import { useLocale } from '../../../../../../hooks/useLocale';
import { Duel } from '../../../../../../stores/duel';
import type { VisualizerProps } from './HullTraverseVisualizer';
export function RicochetVisualizer({ stats }: VisualizerProps) {
const ricochet = stats.shellRicochet ?? 90;
const normalization = stats.shellNormalization;
const shell = Duel.use((state) => state.protagonist.shell);
const { strings } = useLocale();
return (
<Card
variant="classic"
style={{
aspectRatio: '2 / 1',
}}
mb="6"
>
<Box
width="100%"
height="calc(100% * 2 / 3)"
position="absolute"
top="0"
left="0"
style={{
backgroundColor: Var('gray-11'),
overflow: 'hidden',
}}
>
<Box
width="100%"
height="100%"
style={{
background: `
conic-gradient(
from -90deg at 25% 100%,
transparent 0deg ${90 - ricochet - normalization}deg,
${Var('jade-a1')} ${90 - ricochet - normalization}deg ${90 - ricochet - normalization}deg,
${Var('jade-11')} ${90 + ricochet}deg,
${Var('amber-9')} ${90 + ricochet}deg ${90 + ricochet + normalization}deg,
${Var('tomato-10')} ${90 + ricochet + normalization}deg,
${Var('tomato-11')} 180deg,
transparent 180deg
)
`,
}}
/>
<Box
position="absolute"
bottom="0"
left="25%"
width="3rem"
height="3rem"
style={{
transform: `translate(-50%, 50%) rotate(${ricochet + normalization}deg)`,
background: `radial-gradient(${Var('gray-a5')}, ${Var('gray-a11')})`,
borderRadius: '50%',
}}
>
<img
src={asset(`icons/shells/${shell.icon}.webp`)}
style={{
width: '2rem',
height: '2rem',
objectFit: 'contain',
transform: 'translate(-50%, -50%) rotate(135deg)',
position: 'absolute',
top: '-10rem',
left: '50%',
}}
/>
</Box>
</Box>
<Box
width="100%"
height="calc(100% / 3)"
position="absolute"
bottom="0"
left="0"
style={{
background: `linear-gradient(${Var('gray-a4')}, ${Var('gray-a1')})`,
}}
>
<Box
width="100%"
height="100%"
style={{
opacity: 2 ** -4,
backgroundImage: `url(/assets/images/tankopedia/visualizers/ricochet/armor-hash.png)`,
}}
/>
<Text
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
}}
color="gray"
>
{literals(strings.website.tools.tankopedia.visualizers.ricochet.max, [
(ricochet + normalization).toFixed(0),
])}
</Text>
</Box>
</Card>
);
}
@@ -0,0 +1,79 @@
@keyframes penetrating-shell-slide {
0% {
margin-top: -9rem;
}
28%,
100% {
margin-top: 8rem;
}
}
@keyframes ricocheting-shell-slide {
0% {
margin-top: -18rem;
}
38% {
margin-top: -18rem;
}
63%,
69% {
margin-top: 0rem;
}
100% {
margin-top: 8rem;
}
}
@keyframes ricocheting-shell-slide-container {
0% {
transform: translateX(-50%) rotate(80deg);
}
63% {
transform: translateX(-50%) rotate(80deg);
}
69% {
transform: translateX(-50%) rotate(100deg);
}
100% {
transform: translateX(-50%) rotate(100deg);
}
}
.ricochet-visualizer-penetrating-shell {
position: absolute;
animation: penetrating-shell-slide 3s infinite;
}
.ricochet-visualizer-ricocheting-shell {
position: absolute;
animation: ricocheting-shell-slide 3s infinite;
}
.ricochet-visualizer-ricocheting-shell-container {
animation: ricocheting-shell-slide-container 3s infinite;
}
@keyframes surface-impact {
0%,
10% {
opacity: 1;
width: 0;
height: 0;
}
15%,
30% {
opacity: 1;
width: 3rem;
height: 3rem;
}
45%,
100% {
opacity: 0;
width: 3rem;
height: 3rem;
}
}
.ricochet-visualizer-surface-impact {
animation: surface-impact 3s infinite;
}
@@ -0,0 +1,198 @@
import { asset } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { Box, Card, Text } from '@radix-ui/themes';
import { Var } from '../../../../../../../core/radix/var';
import { useLocale } from '../../../../../../../hooks/useLocale';
import { Duel } from '../../../../../../../stores/duel';
import type { VisualizerProps } from '../HullTraverseVisualizer';
import './index.css';
export function RicochetVisualizer({ stats }: VisualizerProps) {
const ricochet = stats.shellRicochet ?? 90;
const shell = Duel.use((state) => state.protagonist.shell);
const { strings } = useLocale();
return (
<Card
variant="classic"
style={{
aspectRatio: '2 / 1',
}}
mb="6"
>
<Box
width="100%"
height="calc(100% / 3)"
position="absolute"
bottom="0"
left="0"
style={{
background: `linear-gradient(${Var('gray-a4')}, ${Var('gray-a1')})`,
}}
>
<Box
width="100%"
height="100%"
style={{
opacity: 2 ** -3,
backgroundImage: `url(/assets/images/tankopedia/visualizers/ricochet/armor-hash.png)`,
}}
/>
</Box>
<Box
width="100%"
height="calc(100% * 2 / 3)"
position="absolute"
top="0"
left="0"
style={{
backgroundColor: Var('gray-3'),
}}
>
<Box
width="100%"
height="100%"
style={{
background: `
conic-gradient(
from -90deg at 25% 100%,
transparent ${90 - ricochet}deg,
${Var('jade-a3')} ${90 - ricochet}deg,
${Var('jade-9')} ${90 + ricochet}deg,
${Var('tomato-8')} ${90 + ricochet}deg,
${Var('tomato-a3')} 180deg,
transparent 180deg
)
`,
}}
/>
{/* <Box
width="1px"
height="100%"
position="absolute"
left="25%"
top="0"
style={{
transform: 'translateX(-50%)',
backgroundColor: Var('gray-11'),
}}
/> */}
<Box
width="3px"
height="20rem"
position="absolute"
left="25%"
bottom="0"
style={{
transformOrigin: 'bottom center',
transform: `translateX(-50%) rotate(${ricochet}deg)`,
background: `repeating-linear-gradient(${Var('gray-a4')}, ${Var('gray-12')} 15px, transparent 15px, transparent 30px)`,
}}
/>
<Box
width="3px"
height="20rem"
position="absolute"
left="25%"
bottom="0"
style={{
transformOrigin: 'bottom center',
transform: `translateX(-50%) rotate(-${ricochet}deg)`,
background: `repeating-linear-gradient(${Var('gray-10')}, ${Var('gray-a3')} 15px, transparent 15px, transparent 30px)`,
}}
/>
<Box
className="ricochet-visualizer-surface-impact"
position="absolute"
bottom="0"
left="25%"
style={{
transform: `translate(-50%, 50%) rotate(${ricochet}deg)`,
background: `radial-gradient(${Var('gray-a2')}, ${Var('gray-a9')})`,
borderRadius: '50%',
}}
/>
<Box
width="2rem"
position="absolute"
height="2rem"
left="25%"
bottom="0"
style={{
transformOrigin: 'bottom center',
transform: `translateX(-50%) rotate(${ricochet / 2}deg)`,
}}
>
<img
className="ricochet-visualizer-penetrating-shell"
src={asset(`icons/shells/${shell.icon}.webp`)}
style={{
objectFit: 'contain',
transform: 'rotate(135deg)',
width: '100%',
height: '100%',
}}
/>
</Box>
<Box
className="ricochet-visualizer-ricocheting-shell-container"
width="2rem"
position="absolute"
height="2rem"
left="25%"
bottom="0"
style={{
transformOrigin: 'bottom center',
}}
>
<img
className="ricochet-visualizer-ricocheting-shell"
src={asset(`icons/shells/${shell.icon}.webp`)}
style={{
objectFit: 'contain',
transform: 'translateY(50%) rotate(135deg)',
width: '100%',
height: '100%',
}}
/>
</Box>
<Text
color="gray"
style={{
position: 'absolute',
left: '30%',
bottom: '40%',
transform: 'translateX(-50%)',
}}
>
{literals(
strings.website.tools.tankopedia.visualizers.ricochet.safe,
[(2 * ricochet).toFixed(0)],
)}
</Text>
<Text
color="gray"
style={{
position: 'absolute',
right: '5%',
bottom: '12%',
}}
>
{literals(
strings.website.tools.tankopedia.visualizers.ricochet.unsafe,
[(90 - ricochet).toFixed(0)],
)}
</Text>
</Box>
</Card>
);
}