diff options
Diffstat (limited to '2026/games_submissions/gbjk/src')
| -rw-r--r-- | 2026/games_submissions/gbjk/src/.gitignore | 24 | ||||
| -rw-r--r-- | 2026/games_submissions/gbjk/src/index.html | 12 | ||||
| -rw-r--r-- | 2026/games_submissions/gbjk/src/package.json | 16 | ||||
| -rw-r--r-- | 2026/games_submissions/gbjk/src/pnpm-lock.yaml | 568 | ||||
| -rw-r--r-- | 2026/games_submissions/gbjk/src/src/main.ts | 33 | ||||
| -rw-r--r-- | 2026/games_submissions/gbjk/src/src/setup.ts | 389 | ||||
| -rw-r--r-- | 2026/games_submissions/gbjk/src/src/style.css | 103 | ||||
| -rw-r--r-- | 2026/games_submissions/gbjk/src/tsconfig.json | 23 | ||||
| -rw-r--r-- | 2026/games_submissions/gbjk/src/vite.config.ts | 9 |
9 files changed, 1177 insertions, 0 deletions
diff --git a/2026/games_submissions/gbjk/src/.gitignore b/2026/games_submissions/gbjk/src/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/2026/games_submissions/gbjk/src/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/2026/games_submissions/gbjk/src/index.html b/2026/games_submissions/gbjk/src/index.html new file mode 100644 index 0000000..c68a552 --- /dev/null +++ b/2026/games_submissions/gbjk/src/index.html @@ -0,0 +1,12 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>tortis</title> + </head> + <body> + <div id="app"></div> + <script type="module" src="/src/main.ts"></script> + </body> +</html> diff --git a/2026/games_submissions/gbjk/src/package.json b/2026/games_submissions/gbjk/src/package.json new file mode 100644 index 0000000..a5e9656 --- /dev/null +++ b/2026/games_submissions/gbjk/src/package.json @@ -0,0 +1,16 @@ +{ + "name": "tortis", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "typescript": "6.0.2", + "vite": "8.0.12", + "vite-plugin-singlefile": "2.3.3" + } +} diff --git a/2026/games_submissions/gbjk/src/pnpm-lock.yaml b/2026/games_submissions/gbjk/src/pnpm-lock.yaml new file mode 100644 index 0000000..1087420 --- /dev/null +++ b/2026/games_submissions/gbjk/src/pnpm-lock.yaml @@ -0,0 +1,568 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + typescript: + specifier: ~6.0.2 + version: 6.0.3 + vite: + specifier: ^8.0.12 + version: 8.0.16 + vite-plugin-singlefile: + specifier: ^2.3.3 + version: 2.3.3(vite@8.0.16) + +packages: + + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + + '@napi-rs/wasm-runtime@1.1.5': + resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@oxc-project/types@0.133.0': + resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + + '@rolldown/binding-android-arm64@1.0.3': + resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.3': + resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.3': + resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.3': + resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.0.3': + resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.3': + resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.0.3': + resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.3': + resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.3': + resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.3': + resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + nanoid@3.3.13: + resolution: {integrity: sha512-sPdqC6ByMVVGvF1ynvvMo0/o+oD1VX7DaHhijt1bFgjvBkHBib4t49GoNDhf2NDta4oeUNlaGbSt5K7qjZ955Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + engines: {node: ^10 || ^12 || >=14} + + rolldown@1.0.3: + resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + vite-plugin-singlefile@2.3.3: + resolution: {integrity: sha512-XVnGH0QzbOa8fxRSsHdCarVN1BSBXNi7uLMQYlrGRN5apdHkk62XQWRJhVever0lnfuyBkwn+kvVChdm/OoOUg==} + engines: {node: '>18.0.0'} + peerDependencies: + rollup: ^4.59.0 + vite: ^5.4.21 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + rollup: + optional: true + + vite@8.0.16: + resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.18 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + +snapshots: + + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.2 + optional: true + + '@oxc-project/types@0.133.0': {} + + '@rolldown/binding-android-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-x64@1.0.3': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.3': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.3': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.3': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.3': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.3': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.3': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@tybys/wasm-util@0.10.2': + dependencies: + tslib: 2.8.1 + optional: true + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + detect-libc@2.1.2: {} + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + fsevents@2.3.3: + optional: true + + is-number@7.0.0: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + nanoid@3.3.13: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.4: {} + + postcss@8.5.15: + dependencies: + nanoid: 3.3.13 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + rolldown@1.0.3: + dependencies: + '@oxc-project/types': 0.133.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.3 + '@rolldown/binding-darwin-arm64': 1.0.3 + '@rolldown/binding-darwin-x64': 1.0.3 + '@rolldown/binding-freebsd-x64': 1.0.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 + '@rolldown/binding-linux-arm64-gnu': 1.0.3 + '@rolldown/binding-linux-arm64-musl': 1.0.3 + '@rolldown/binding-linux-ppc64-gnu': 1.0.3 + '@rolldown/binding-linux-s390x-gnu': 1.0.3 + '@rolldown/binding-linux-x64-gnu': 1.0.3 + '@rolldown/binding-linux-x64-musl': 1.0.3 + '@rolldown/binding-openharmony-arm64': 1.0.3 + '@rolldown/binding-wasm32-wasi': 1.0.3 + '@rolldown/binding-win32-arm64-msvc': 1.0.3 + '@rolldown/binding-win32-x64-msvc': 1.0.3 + + source-map-js@1.2.1: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tslib@2.8.1: + optional: true + + typescript@6.0.3: {} + + vite-plugin-singlefile@2.3.3(vite@8.0.16): + dependencies: + micromatch: 4.0.8 + vite: 8.0.16 + + vite@8.0.16: + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.15 + rolldown: 1.0.3 + tinyglobby: 0.2.17 + optionalDependencies: + fsevents: 2.3.3 diff --git a/2026/games_submissions/gbjk/src/src/main.ts b/2026/games_submissions/gbjk/src/src/main.ts new file mode 100644 index 0000000..8752b31 --- /dev/null +++ b/2026/games_submissions/gbjk/src/src/main.ts @@ -0,0 +1,33 @@ +import { setup } from "./setup"; +import "./style.css"; + +document.querySelector<HTMLDivElement>("#app")!.innerHTML = ` + <div class="layout"> + + <div class="game"> + <div class="title-bar"> + <h1>Tortis</h1> + <p>(4row clear to win)</p> + </div> + + <canvas height="240" width="160" id="main"></canvas> + </div> + + <ul> + <button id="move-left">move left</button> + <button id="rotate-left">rotate left</button> + <button id="move-right">move right</button> + <button id="rotate-right">rotate right</button> + <button id="speed-up">speed up</button> + </ul> + </div> +`; + +setup({ + main: document.querySelector<HTMLCanvasElement>("#main")!, + left: document.querySelector<HTMLButtonElement>("#move-left")!, + right: document.querySelector<HTMLButtonElement>("#move-right")!, + rotateLeft: document.querySelector<HTMLButtonElement>("#rotate-left")!, + rotateRight: document.querySelector<HTMLButtonElement>("#rotate-right")!, + speedUp: document.querySelector<HTMLButtonElement>("#speed-up")!, +}); diff --git a/2026/games_submissions/gbjk/src/src/setup.ts b/2026/games_submissions/gbjk/src/src/setup.ts new file mode 100644 index 0000000..9d0614b --- /dev/null +++ b/2026/games_submissions/gbjk/src/src/setup.ts @@ -0,0 +1,389 @@ +export type Elements = { + main: HTMLCanvasElement; + right: HTMLButtonElement; + left: HTMLButtonElement; + rotateRight: HTMLButtonElement; + rotateLeft: HTMLButtonElement; + speedUp: HTMLButtonElement; +}; + +const WIDTH = 160; +const HEIGHT = 240; + +const GRID_HEIGHT = HEIGHT - 10; +const ROWS = 15; +const COLS = 10; +const GRID_WIDTH = (GRID_HEIGHT / ROWS) * 10; +const GRID_X = 5; +const GRID_Y = 5; +const MARGIN = 2; +const CELL_WIDTH = GRID_HEIGHT / ROWS - MARGIN; +const FALLTIME = 600; +const MIN_FALLTIME = 300; + +let rotation = 0; + +type Block = + | "void" + | "red" + | "green" + | "blue" + | "fallingRed" + | "fallingGreen" + | "fallingBlue"; + +const board: Block[][] = []; + +function resetBoard() { + board.length = 0; + + for (let height = 0; height < ROWS; height++) { + const row: Block[] = []; + for (let width = 0; width < COLS; width++) { + row.push("void"); + } + board.push(row); + } +} + +resetBoard(); + +function random<T>(elements: T[]): T { + return elements[Math.floor(Math.random() * elements.length)]; +} + +let addedShapeNumber = 1; +function addSquares(): boolean { + const color = random(["fallingRed", "fallingGreen", "fallingBlue"] as const); + let w = COLS / 2; + let h = 1; + for (let i = 0; i < 4; i++) { + board[h][w] = color; + + if (i === 3) break; + + let move: "up" | "down" | "left" | "right" | null = null; + let j = 0; + for (; j < 20; j++) { + move = + addedShapeNumber % 6 === 0 + ? "down" + : random(["up", "down", "left", "right"] as const); + + if (move === "up" && (h === 0 || board[h - 1][w] !== "void")) continue; + if (move === "down" && (h === ROWS - 1 || board[h + 1][w] !== "void")) + continue; + + if (move === "left" && (w === 0 || board[h][w - 1] !== "void")) continue; + if (move === "right" && (w === COLS - 1 || board[h][w + 1] !== "void")) + continue; + + break; + } + if (j === 20) { + return false; + } + + switch (move) { + case "up": + h--; + break; + case "down": + h++; + break; + case "left": + w--; + break; + case "right": + w++; + break; + } + } + + addedShapeNumber++; + return true; +} + +function clearFilledRows(): number { + let lastClearedRow = ROWS; + let clearedRows = 0; + + for (let row = ROWS - 1; row >= 0; row--) { + if ( + !board[row].some( + (cell) => + cell === "void" || + cell === "fallingBlue" || + cell === "fallingGreen" || + cell === "fallingRed", + ) + ) { + for (let col = 0; col < COLS; col++) { + board[row][col] = "void"; + } + lastClearedRow = row; + clearedRows++; + } else if (lastClearedRow !== ROWS) { + for (let col = 0; col < COLS; col++) { + switch (board[row][col]) { + case "red": + board[row][col] = "fallingRed"; + break; + case "green": + board[row][col] = "fallingGreen"; + break; + case "blue": + board[row][col] = "fallingBlue"; + break; + } + } + } + } + + return clearedRows; +} + +export function setup(elements: Elements) { + const ctx = elements.main.getContext("2d")!; + + let gameRunning = false; + let animationFrameId: number | null = null; + let lastFrame = 0; + let fallTime = FALLTIME; + + let speedUpPressed = false; + + elements.left.addEventListener("click", () => moveFalling("left")); + elements.right.addEventListener("click", () => moveFalling("right")); + + elements.rotateLeft.addEventListener("click", () => { + if (!gameRunning) return; + + rotation -= 30 * Math.random(); + elements.main.style.transform = `rotate(${rotation}deg)`; + }); + elements.rotateRight.addEventListener("click", () => { + if (!gameRunning) return; + + rotation += 30 * Math.random(); + elements.main.style.transform = `rotate(${rotation}deg)`; + }); + + elements.speedUp.addEventListener( + "mousedown", + () => (speedUpPressed = gameRunning), + ); + elements.speedUp.addEventListener("mouseup", () => (speedUpPressed = false)); + + window.addEventListener("message", (ev: MessageEvent<unknown>) => { + const message = ev.data; + if (!isStartMessage(message)) return; + + startGame(message.difficulty); + }); + + window.parent.postMessage({ op: "ready" }, "*"); + + draw(); + + function isStartMessage( + message: unknown, + ): message is { op: "start"; difficulty: number } { + if (typeof message !== "object" || message === null) return false; + + const candidate = message as { op?: unknown; difficulty?: unknown }; + return ( + candidate.op === "start" && + typeof candidate.difficulty === "number" && + Number.isFinite(candidate.difficulty) + ); + } + + function resetGame(difficulty: number) { + resetBoard(); + addedShapeNumber = 1; + fallTime = Math.max(MIN_FALLTIME, FALLTIME - Math.max(0, difficulty) * 5); + rotation = 0; + elements.main.style.transform = ""; + speedUpPressed = false; + lastFrame = 0; + } + + function startGame(difficulty: number) { + if (animationFrameId !== null) { + cancelAnimationFrame(animationFrameId); + animationFrameId = null; + } + + resetGame(difficulty); + gameRunning = true; + window.parent.postMessage({ op: "started", verb: "catch!" }, "*"); + animationFrameId = requestAnimationFrame(gameLoop); + } + + function finishGame(win: boolean) { + if (!gameRunning) return; + + gameRunning = false; + if (animationFrameId !== null) { + cancelAnimationFrame(animationFrameId); + animationFrameId = null; + } + + window.parent.postMessage({ op: "done", win }, "*"); + resetGame(0); + draw(); + } + + function moveFalling(move: "left" | "right") { + if (!gameRunning) return; + + switch (move) { + case "left": + for (let row = 0; row < ROWS; row++) { + for (let col = 0; col < COLS - 1; col++) { + if (board[row][col] === "void") { + switch (board[row][col + 1]) { + case "fallingRed": + case "fallingGreen": + case "fallingBlue": + board[row][col] = board[row][col + 1]; + board[row][col + 1] = "void"; + } + } + } + } + break; + case "right": + for (let row = 0; row < ROWS; row++) { + for (let col = COLS - 1; col > 0; col--) { + if (board[row][col] === "void") { + switch (board[row][col - 1]) { + case "fallingRed": + case "fallingGreen": + case "fallingBlue": + board[row][col] = board[row][col - 1]; + board[row][col - 1] = "void"; + } + } + } + } + break; + } + } + + function physics(): boolean { + let somethingFell = false; + + for (let row = ROWS - 1; row >= 1; row--) { + for (let col = 0; col < COLS; col++) { + let space = board[row][col]; + let above = board[row - 1][col]; + switch (above) { + case "fallingRed": + case "fallingGreen": + case "fallingBlue": + if (space === "void") { + somethingFell = true; + board[row][col] = board[row - 1][col]; + board[row - 1][col] = "void"; + } else { + switch (above) { + case "fallingRed": + board[row - 1][col] = "red"; + break; + case "fallingGreen": + board[row - 1][col] = "green"; + break; + case "fallingBlue": + board[row - 1][col] = "blue"; + break; + } + } + } + } + } + + for (let col = 0; col < COLS; col++) { + switch (board[ROWS - 1][col]) { + case "fallingRed": + board[ROWS - 1][col] = "red"; + break; + case "fallingGreen": + board[ROWS - 1][col] = "green"; + break; + case "fallingBlue": + board[ROWS - 1][col] = "blue"; + break; + } + } + + return somethingFell; + } + + function draw() { + ctx.clearRect(0, 0, WIDTH, HEIGHT); + + ctx.fillStyle = "black"; + ctx.fillRect(GRID_X, GRID_Y, GRID_WIDTH, GRID_HEIGHT); + + for (let h = 0; h < ROWS; h++) { + for (let w = 0; w < COLS; w++) { + switch (board[h][w]) { + case "void": + ctx.fillStyle = "#2e2e2e"; + break; + case "red": + ctx.fillStyle = "#994444"; + break; + case "green": + ctx.fillStyle = "#449944"; + break; + case "blue": + ctx.fillStyle = "#444499"; + break; + case "fallingRed": + ctx.fillStyle = "#bb3333"; + break; + case "fallingGreen": + ctx.fillStyle = "#33bb33"; + break; + case "fallingBlue": + ctx.fillStyle = "#3333bb"; + break; + } + + const x = GRID_X + MARGIN * 1.5 + w * CELL_WIDTH + (w - 1) * MARGIN; + const y = GRID_Y + MARGIN * 1.5 + h * CELL_WIDTH + (h - 1) * MARGIN; + + ctx.fillRect(x, y, CELL_WIDTH, CELL_WIDTH); + } + } + } + + function gameLoop(time: number) { + animationFrameId = null; + + if (!gameRunning) return; + + if (time - lastFrame > (speedUpPressed ? fallTime / 10 : fallTime)) { + lastFrame = time; + const somethingFell = physics(); + if (!somethingFell) { + const clearedRows = clearFilledRows(); + if (clearedRows >= 4) { + finishGame(true); + return; + } else if (clearedRows === 0) { + if (!addSquares()) { + finishGame(false); + return; + } + } + } + } + + draw(); + animationFrameId = requestAnimationFrame(gameLoop); + } +} diff --git a/2026/games_submissions/gbjk/src/src/style.css b/2026/games_submissions/gbjk/src/src/style.css new file mode 100644 index 0000000..56e07d1 --- /dev/null +++ b/2026/games_submissions/gbjk/src/src/style.css @@ -0,0 +1,103 @@ +* { + box-sizing: border-box; +} + +html, +body, +#app { + min-height: 100%; +} + +body { + margin: 0; + color: darksalmon; + background-color: #2e2e2e; + font-family: monospace; + overflow-x: hidden; +} + +button { + min-width: 0; + font: inherit; + font-size: .4rem; + line-height: 1.1; + padding: .15rem; + color: darksalmon; + background-color: #2e2e2e; + border-color: salmon; + cursor: pointer; + white-space: normal; + overflow-wrap: anywhere; + + z-index: 9999; +} + +button:hover { + background-color: darkslategray; +} + +button:active { + background-color: slategray; +} + +.layout { + margin: auto; + display: flex; + min-height: 100dvh; + width: 100%; + padding: .15rem; + gap: .2rem; + align-items: center; + justify-content: center; + overflow: hidden; +} + +.game { + min-width: 0; +} + +.title-bar { + display: flex; + align-items: baseline; + gap: .25rem; + margin-bottom: .2rem; +} + +h1, +p { + margin: 0; +} + +h1 { + font-size: .6rem; + line-height: 1; +} + +p { + font-size: .4rem; + line-height: 1.1; +} + +canvas { + display: block; + aspect-ratio: 2 / 3; + border-radius: 6px; + border: 1px solid darksalmon; + box-shadow: 0px 0px 4px darksalmon; + height: 80vmin; + width: auto; + + transition: transform 100ms; + margin: auto; +} + +ul { + display: flex; + justify-content: center; + flex-direction: column; + gap: .15rem; + width: min(6rem, 42vw); + margin: 0; + padding: 0; + list-style: none; +} diff --git a/2026/games_submissions/gbjk/src/tsconfig.json b/2026/games_submissions/gbjk/src/tsconfig.json new file mode 100644 index 0000000..1ab38c8 --- /dev/null +++ b/2026/games_submissions/gbjk/src/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "es2023", + "module": "esnext", + "lib": ["ES2023", "DOM"], + "types": ["vite/client"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/2026/games_submissions/gbjk/src/vite.config.ts b/2026/games_submissions/gbjk/src/vite.config.ts new file mode 100644 index 0000000..c9036bd --- /dev/null +++ b/2026/games_submissions/gbjk/src/vite.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vite"; +import { viteSingleFile } from "vite-plugin-singlefile"; + +export default defineConfig({ + plugins: [viteSingleFile()], + build: { + minify: false, + }, +}); |
