diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json index 81c900bc9..f94d49d59 100644 --- a/packages/i18n/strings/en.json +++ b/packages/i18n/strings/en.json @@ -853,6 +853,13 @@ }, "tools": { + "guess": { + "name": "Guess the tank", + "button": "Guess away", + "description": "Silhouette mini-game", + "seo_description": "Play a tank guessing game with a silhouette in World of Tanks Blitz" + }, + "tankopedia": { "name": "Tankopedia", "button": "Find tanks", diff --git a/packages/website/public/assets/images/tools/guess.webp b/packages/website/public/assets/images/tools/guess.webp new file mode 100644 index 000000000..3453b25f9 Binary files /dev/null and b/packages/website/public/assets/images/tools/guess.webp differ diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx index 35fa2ff39..2d457af59 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx @@ -33,9 +33,17 @@ const ARCADE_MODE_FOV = 54; interface ControlsProps { naked?: boolean; + autoRotate?: boolean; + zoomable?: boolean; + enableRotate?: boolean; } -export function Controls({ naked }: ControlsProps) { +export function Controls({ + naked, + autoRotate = true, + zoomable = true, + enableRotate = true, +}: ControlsProps) { const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const display = TankopediaEphemeral.use((state) => state.display); const duelStore = Duel.useStore(); @@ -342,12 +350,14 @@ export function Controls({ naked }: ControlsProps) { return ( ); diff --git a/packages/website/src/constants/tools.ts b/packages/website/src/constants/tools.ts index c8e9b87be..b51aeff4c 100644 --- a/packages/website/src/constants/tools.ts +++ b/packages/website/src/constants/tools.ts @@ -117,6 +117,12 @@ export const chartsTool: Tool = { button: { color: 'bronze', }, + branches: ['main', 'dev'], +}; + +export const guessTool: Tool = { + id: 'guess', + button: { color: 'cyan' }, branches: ['main', 'dev', 'opentest', 'preview'], }; @@ -124,6 +130,7 @@ export const TOOLS: Tool[] = [ tankopediaTool, compareTool, performanceTool, + guessTool, // chartsTool, galleryTool, sessionTool, diff --git a/packages/website/src/pages/[...locale]/index.astro b/packages/website/src/pages/[...locale]/index.astro index a15019fc0..8473658aa 100644 --- a/packages/website/src/pages/[...locale]/index.astro +++ b/packages/website/src/pages/[...locale]/index.astro @@ -17,6 +17,7 @@ import { discordTool, embedTool, galleryTool, + guessTool, moreTool, performanceTool, sessionTool, @@ -118,21 +119,22 @@ export const getStaticPaths = (() => { + + + + - - - + + + - - - - + diff --git a/packages/website/src/pages/[...locale]/tools/guess/_index.tsx b/packages/website/src/pages/[...locale]/tools/guess/_index.tsx new file mode 100644 index 000000000..3d8def1f8 --- /dev/null +++ b/packages/website/src/pages/[...locale]/tools/guess/_index.tsx @@ -0,0 +1,92 @@ +import { Box, Flex } from '@radix-ui/themes'; +import { awaitableModelDefinitions } from '../../../../core/awaitables/modelDefinitions'; +import { awaitableProvisionDefinitions } from '../../../../core/awaitables/provisionDefinitions'; +import { awaitableTankDefinitions } from '../../../../core/awaitables/tankDefinitions'; +import { Var } from '../../../../core/radix/var'; +import { Duel } from '../../../../stores/duel'; +import { TankopediaEphemeral } from '../../../../stores/tankopediaEphemeral'; +import { GuessRenderer } from './components/GuessRenderer'; + +const [tankDefinitions, modelDefinitions, provisionDefinitions] = + await Promise.all([ + awaitableTankDefinitions, + awaitableModelDefinitions, + awaitableProvisionDefinitions, + ]); + +const ids = Object.keys(tankDefinitions.tanks); + +export function Page() { + const id = Number(ids[Math.floor(Math.random() * ids.length)]); + const tank = tankDefinitions.tanks[id]; + const model = modelDefinitions.models[id]; + + return ( + + + + + + ); +} + +function Content() { + return ( + + + + + + + + + + + b + + + ); +} diff --git a/packages/website/src/pages/[...locale]/tools/guess/components/GuessRenderer.tsx b/packages/website/src/pages/[...locale]/tools/guess/components/GuessRenderer.tsx new file mode 100644 index 000000000..ee8dfcd81 --- /dev/null +++ b/packages/website/src/pages/[...locale]/tools/guess/components/GuessRenderer.tsx @@ -0,0 +1,56 @@ +import { Canvas, invalidate } from '@react-three/fiber'; +import { useCallback, useEffect, useRef } from 'react'; +import { Fog } from 'three'; +import { Controls } from '../../../../../components/Tankopedia/HeroSection/components/TankSandbox/components/Control'; +import { Lighting } from '../../../../../components/Tankopedia/HeroSection/components/TankSandbox/components/Lighting'; +import { TankModel } from '../../../../../components/Tankopedia/HeroSection/components/TankSandbox/components/TankModel'; +import { Var } from '../../../../../core/radix/var'; +import { TankopediaDisplay } from '../../../../../stores/tankopediaPersistent/constants'; + +const nearConcealed = -40; +const farConcealed = 22; +const nearRevealed = 20; +const farRevealed = 22; +const animationDuration = 1; + +export function GuessRenderer() { + const fog = useRef(new Fog('black', nearConcealed, farConcealed)); + const reveal = useCallback(() => { + const t0 = Date.now() / 1000; + + function frame() { + const t = Date.now() / 1000; + const x = (t - t0) / animationDuration; + const y = Math.sqrt(x); + const near = nearConcealed * (1 - y) + nearRevealed * y; + const far = farConcealed * (1 - y) + farRevealed * y; + + fog.current.near = near; + fog.current.far = far; + + invalidate(); + + if (y < 1) requestAnimationFrame(frame); + } + + requestAnimationFrame(frame); + }, []); + + useEffect(() => { + setTimeout(reveal, 2000); + }, []); + + return ( + + + + + + ); +} diff --git a/packages/website/src/pages/[...locale]/tools/guess/index.astro b/packages/website/src/pages/[...locale]/tools/guess/index.astro new file mode 100644 index 000000000..b53bd7755 --- /dev/null +++ b/packages/website/src/pages/[...locale]/tools/guess/index.astro @@ -0,0 +1,13 @@ +--- +import { PageWrapper } from '../../../../components/PageWrapper'; +import BaseLayout from '../../../../layouts/BaseLayout.astro'; +import { Page } from './_index'; + +export { getStaticPaths } from '../../index.astro'; +--- + + + + + +