diff --git a/build/build.ts b/build/build.ts index 6303b59..34ff402 100644 --- a/build/build.ts +++ b/build/build.ts @@ -18,7 +18,7 @@ while (!await isGame(game)) { choices: (await getGames()).map(value => ({ value })), }); } - +console.log(`Building ${game}...`); const html = await buildHTML(game, { production: true }); if (!html) { @@ -28,6 +28,7 @@ const filePath = path.resolve(outDir, `${game}.html`); await Bun.write(filePath, html); if (publish) { + console.log(`Publishing ${game}...`); const result = await $`scp "${filePath}" "${publish}${game}.html"`; if (result.exitCode === 0) { console.log(`Build successful: ${process.env.PUBLISH_URL}${game}.html`); diff --git a/src/games/tapple/assets/beep.ogg b/src/games/tapple/assets/beep.ogg new file mode 100644 index 0000000..7122494 Binary files /dev/null and b/src/games/tapple/assets/beep.ogg differ diff --git a/src/games/tapple/assets/style.css b/src/games/tapple/assets/style.css new file mode 100644 index 0000000..6447649 --- /dev/null +++ b/src/games/tapple/assets/style.css @@ -0,0 +1,40 @@ +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; + overflow: hidden; + width: 100dvw; + height: 100dvh; + font-size: 24px; + user-select: none; +} + +main { + width: 100dvw; + height: 100dvh; + padding: 1rem; + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 0.5rem; + + button { + font-size: 10vmin; + cursor: pointer; + width: 100%; + height: 100%; + + &[disabled] { + pointer-events: none; + } + } +} + +body > button { + width: 100dvw; + height: 100dvh; + font-size: 80vmin; +} \ No newline at end of file diff --git a/src/games/tapple/assets/tick.ogg b/src/games/tapple/assets/tick.ogg new file mode 100644 index 0000000..4601f5c Binary files /dev/null and b/src/games/tapple/assets/tick.ogg differ diff --git a/src/games/tapple/components/App.tsx b/src/games/tapple/components/App.tsx new file mode 100644 index 0000000..f07c766 --- /dev/null +++ b/src/games/tapple/components/App.tsx @@ -0,0 +1,52 @@ +import { useEffect, useState } from "preact/hooks"; +import tick from '../assets/tick.ogg'; +import beep from '../assets/beep.ogg'; + +const LETTERS = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЭЮЯ'.split(''); + +export const App = () => { + const [init, setInit] = useState(false); + const [usedLetters, setUsedLetters] = useState([]); + const [isOver, setOver] = useState(false); + + useEffect(() => { + let timeout = 0; + + if (usedLetters.length) { + tick.pause(); + tick.currentTime = 0; + tick.loop = true; + tick.play(); + + timeout = window.setTimeout(() => { + tick.pause(); + beep.play(); + setOver(true); + window.clearTimeout(timeout); + }, 10_000); + } + + return () => { + window.clearTimeout(timeout); + }; + }, [usedLetters]); + + if (!init) { + return ; + } + + return <> +
+ {LETTERS.map(l => ( + + ))} +
+ ; +}; diff --git a/src/games/tapple/index.tsx b/src/games/tapple/index.tsx new file mode 100644 index 0000000..aff66a9 --- /dev/null +++ b/src/games/tapple/index.tsx @@ -0,0 +1,11 @@ +import { render } from "preact"; +import { App } from "./components/App"; + +import './assets/style.css'; + +export default function main() { + render( + , + document.body + ); +} \ No newline at end of file