From f0c764cc0c83658f44aa45f52299eb8826e4245e Mon Sep 17 00:00:00 2001 From: yosyo Date: Sat, 13 Sep 2025 15:57:43 +0200 Subject: [PATCH] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D=20wip(s?= =?UTF-8?q?rc/front):=20first=20try=20at=20a=20basic=20architecture.=20gam?= =?UTF-8?q?e=20logic=20+=20SPA=20implemented?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flake.nix | 2 +- src/front/index.html | 41 +++-- src/front/main.tsx | 1 - src/front/static/assets/favicon.ico | Bin 0 -> 16141 bytes src/front/static/css/style.css | 5 + src/front/static/ts/main.ts | 69 +++++++ src/front/static/ts/views/Aview.ts | 10 + src/front/static/ts/views/Game.ts | 214 ++++++++++++++++++++++ src/front/static/ts/views/LoginPage.ts | 66 +++++++ src/front/static/ts/views/MainMenu.ts | 22 +++ src/front/static/ts/views/PongMenu.ts | 21 +++ src/front/static/ts/views/RegisterPage.ts | 27 +++ src/front/style.css | 5 - 13 files changed, 459 insertions(+), 24 deletions(-) delete mode 100644 src/front/main.tsx create mode 100644 src/front/static/assets/favicon.ico create mode 100644 src/front/static/css/style.css create mode 100644 src/front/static/ts/main.ts create mode 100644 src/front/static/ts/views/Aview.ts create mode 100644 src/front/static/ts/views/Game.ts create mode 100644 src/front/static/ts/views/LoginPage.ts create mode 100644 src/front/static/ts/views/MainMenu.ts create mode 100644 src/front/static/ts/views/PongMenu.ts create mode 100644 src/front/static/ts/views/RegisterPage.ts delete mode 100644 src/front/style.css diff --git a/flake.nix b/flake.nix index ecdab7e..fb52ec3 100644 --- a/flake.nix +++ b/flake.nix @@ -39,7 +39,7 @@ nodejs_22 pnpm just - foundry + foundry ]; shellHook = '' if [ ! -d node_modules/ ]; then diff --git a/src/front/index.html b/src/front/index.html index e7a3f05..97c4aea 100644 --- a/src/front/index.html +++ b/src/front/index.html @@ -1,21 +1,28 @@ - - - - Vite + Tailwind Test - - - - - -
-

Vite + Tailwind

-

🚀 Looks like it's working!

- -
- + + + + + + Vite + Tailwind Test + + + + + + + + + + +
+
+ + + diff --git a/src/front/main.tsx b/src/front/main.tsx deleted file mode 100644 index 2a2392b..0000000 --- a/src/front/main.tsx +++ /dev/null @@ -1 +0,0 @@ -console.log("test") diff --git a/src/front/static/assets/favicon.ico b/src/front/static/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..18945be5f045a1017b625d28282b42dc3a4a59c7 GIT binary patch literal 16141 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 literal 0 HcmV?d00001 diff --git a/src/front/static/css/style.css b/src/front/static/css/style.css new file mode 100644 index 0000000..0d686fe --- /dev/null +++ b/src/front/static/css/style.css @@ -0,0 +1,5 @@ +@import "tailwindcss"; + +@theme { + --color-accent-500: #f55151; +} diff --git a/src/front/static/ts/main.ts b/src/front/static/ts/main.ts new file mode 100644 index 0000000..676a313 --- /dev/null +++ b/src/front/static/ts/main.ts @@ -0,0 +1,69 @@ +/*import MainMenu from "./views/MainMenu.ts"; +import PongMenu from "./views/PongMenu.ts"; + +import LoginPage from "./views/LoginPage.ts"; +import RegisterPage from "./views/RegisterPage.ts"; + +import Game from "./views/Game.ts";*/ + +const navigationManager = url => { + history.pushState(null, null, url); + router(); +}; + +let view; + +const routes = [ + /*{ path: "/", view: MainMenu }, + + { path: "/pong", view: PongMenu }, + { path: "/pong/solo", view: Game }, + + { path: "/login", view: LoginPage }, + { path: "/register", view: RegisterPage },*/ + { path: "/", view: () => import("./views/MainMenu.ts") }, + + { path: "/pong", view: () => import("./views/PongMenu.ts") }, + { path: "/pong/solo", view: () => import("./views/Game.ts") }, + + { path: "/login", view: () => import("./views/LoginPage.ts") }, + { path: "/register", view: () => import("./views/RegisterPage.ts") }, +]; + +const router = async () => { + + const routesMap = routes.map(route => { + return { route: route, isMatch: location.pathname === route.path }; + }); + + let match = routesMap.find(routeMap => routeMap.isMatch); + + if (!match) + match = { route: routes[0], isMatch: true }; + + if (view) + view.running = false; + + console.log(match); + + const module = await match.route.view(); + view = new module.default(); + + document.querySelector("#app").innerHTML = await view.getHTML(); + view.run(); +}; + +window.addEventListener("popstate", router); + +document.addEventListener("DOMContentLoaded", () => { + + document.body.addEventListener("click", e=> { + if (e.target.matches("[data-link]")) + { + e.preventDefault(); + navigationManager(e.target.href); + } + }); + + router(); +}); diff --git a/src/front/static/ts/views/Aview.ts b/src/front/static/ts/views/Aview.ts new file mode 100644 index 0000000..810d3ab --- /dev/null +++ b/src/front/static/ts/views/Aview.ts @@ -0,0 +1,10 @@ +export default class { + contructor() + { + } + + setTitle(title) { document.title = title; } + + async getHTML() { return ""; } + async run() { } +}; diff --git a/src/front/static/ts/views/Game.ts b/src/front/static/ts/views/Game.ts new file mode 100644 index 0000000..5610676 --- /dev/null +++ b/src/front/static/ts/views/Game.ts @@ -0,0 +1,214 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + running: boolean; + + constructor() + { + super(); + this.setTitle("pog or pong ? :3"); + this.running = true; + } + + async getHTML() { + return ` + +
+ + +
+ `; + } + + async run() { + let start: number = 0; + let elapsed: number; + + let game_playing: boolean = false; + let match_over: boolean = false; + let p1_score: number = 0; + let p2_score: number = 0; + + let countdown: number = 3; + let countdownTimer: number = 0; + + const canvas = document.getElementById("gameCanvas") as HTMLCanvasElement; + const ctx = canvas.getContext("2d"); + + const paddleOffset: number = 15; + const paddleHeight: number = 100; + const paddleWidth: number = 10; + const ballSize: number = 10; + + let leftPaddleY: number = canvas.height / 2 - paddleHeight / 2; + let rightPaddleY: number = canvas.height / 2 - paddleHeight / 2; + let paddleSpeed: number = 727 * 0.69; + let ballX: number = canvas.width / 2; + let ballY: number = canvas.height / 2; + let ballSpeed: number = 200; + let ballSpeedX: number = 300; + let ballSpeedY: number = 10; + + const keys: Record = {}; + + document.addEventListener("keydown", e => { keys[e.key] = true; }); + document.addEventListener("keyup", e => { keys[e.key] = false; }); + + function movePaddles() { + if (keys["w"] && leftPaddleY > 0) + leftPaddleY -= paddleSpeed * elapsed; + if (keys["s"] && leftPaddleY < canvas.height - paddleHeight) + leftPaddleY += paddleSpeed * elapsed; + if (keys["ArrowUp"] && rightPaddleY > 0) + rightPaddleY -= paddleSpeed * elapsed; + if (keys["ArrowDown"] && rightPaddleY < canvas.height - paddleHeight) + rightPaddleY += paddleSpeed * elapsed; + } + + function getBounceVelocity(paddleY) { + const speed = ballSpeed; + const paddleCenterY = paddleY + paddleHeight / 2; + + let n = (ballY - paddleCenterY) / (paddleHeight / 2); + n = Math.max(-1, Math.min(1, n)); + let theta = n * ((75 * Math.PI) / 180); + ballSpeedY = ballSpeed * Math.sin(theta); + } + + function moveBall() { + let length = Math.sqrt(ballSpeedX * ballSpeedX + ballSpeedY * ballSpeedY); + let scale = ballSpeed / length; + ballX += (ballSpeedX * scale) * elapsed; + ballY += (ballSpeedY * scale) * elapsed; + + if (ballY <= 0 || ballY >= canvas.height - ballSize) + ballSpeedY *= -1; + + if (ballX <= paddleWidth + paddleOffset && ballX >= paddleOffset && + ballY > leftPaddleY && ballY < leftPaddleY + paddleHeight) + { + ballSpeedX *= -1; + ballX = paddleWidth + paddleOffset; + getBounceVelocity(leftPaddleY); + ballSpeed += 10; + } + + if (ballX >= canvas.width - paddleWidth - ballSize - paddleOffset && ballX <= canvas.width - ballSize - paddleOffset && + ballY > rightPaddleY && ballY < rightPaddleY + paddleHeight) + { + ballSpeedX *= -1; + ballX = canvas.width - paddleWidth - ballSize - paddleOffset; + getBounceVelocity(rightPaddleY); + ballSpeed += 10; + } + + // scoring + if (ballX < 0 || ballX > canvas.width - ballSize) + { + game_playing = false; + if (ballX < 0) + p2_score++; + else + p1_score++; + + if (p1_score === 3 || p2_score === 3) + match_over = true; + else + { + countdown = 3; + countdownTimer = performance.now(); + } + + ballX = canvas.width / 2; + ballY = canvas.height / 2; + ballSpeed = 200; + ballSpeedX = 300 * ((ballSpeedX > 0) ? 1 : -1); + ballSpeedY = 10; + ballSpeedX = -ballSpeedX; + leftPaddleY = canvas.height / 2 - paddleHeight / 2; + rightPaddleY = canvas.height / 2 - paddleHeight / 2; + } + } + + function draw() { + ctx.fillStyle = "black"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.fillStyle = "white"; + ctx.fillRect(paddleOffset, leftPaddleY, paddleWidth, paddleHeight); + ctx.fillRect(canvas.width - paddleWidth - paddleOffset, rightPaddleY, paddleWidth, paddleHeight); + + ctx.fillStyle = "white"; + if (game_playing) + ctx.fillRect(ballX, ballY, ballSize, ballSize); + + ctx.font = "24px sans-serif"; + ctx.fillText(`${p1_score} - ${p2_score}`, canvas.width / 2 - 20, 30); + + if (match_over) + { + ctx.font = "48px sans-serif"; + const winner = p1_score > p2_score ? "Player 1" : "Player 2"; + ctx.fillText(`${winner} won :D`, canvas.width / 2 - 150, canvas.height / 2 + 22); + document.getElementById("game-buttons").classList.remove("hidden"); + } + } + + function startCountdown() + { + const now = performance.now(); + if (countdown > 0) + { + if (now - countdownTimer >= 500) + { + countdown--; + countdownTimer = now; + } + ctx.font = "48px sans-serif"; + ctx.fillText(countdown.toString(), canvas.width / 2 - 10, canvas.height / 2 + 24); + } + else if (countdown === 0) + { + ctx.font = "48px sans-serif"; + ctx.fillText("Go!", canvas.width / 2 - 30, canvas.height / 2 + 24); + setTimeout(() => { + game_playing = true; + countdown = -1; + }, 500); + } + } + + const gameLoop = (timestamp: number) => { + elapsed = (timestamp - start) / 1000; + start = timestamp; + if (game_playing) + { + movePaddles(); + moveBall(); + } + draw(); + console.log(game_playing); + if (!game_playing) + startCountdown(); + if (this.running) + requestAnimationFrame(gameLoop); + }; + + + document.getElementById("game-retry")?.addEventListener("click", () => { + document.getElementById("game-buttons").classList.add("hidden"); + game_playing = false; + match_over = false; + p1_score = 0; + p2_score = 0; + + countdown = 3; + countdownTimer = performance.now(); + }); + requestAnimationFrame(gameLoop); + } +} diff --git a/src/front/static/ts/views/LoginPage.ts b/src/front/static/ts/views/LoginPage.ts new file mode 100644 index 0000000..bdfc553 --- /dev/null +++ b/src/front/static/ts/views/LoginPage.ts @@ -0,0 +1,66 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + constructor() + { + super(); + this.setTitle("login"); + } + + async getHTML() { + return ` +
+

login

+ + + + + + + + register + +
+ `; + } + + async run() { + const login = async () => { + const username = (document.getElementById("username") as HTMLInputElement).value; + const password = (document.getElementById("password") as HTMLInputElement).value; + + try { + /*const response = await fetch("https://localhost/login", { + method: "POST", + headers: { "Content-Type": "application/json", }, + credentials: "include", + body: JSON.stringify({ user: username, password: password }), + }); + + const data = await response.json();*/ + const data = { "error": "invalid password or smth" }; + const response = { status: 400}; + + + if (response.status === 200) + { + navigationManager("/"); + } + else if (response.status === 400) + { + document.getElementById("login-error-message").innerHTML = "error: " + data.error; + document.getElementById("login-error-message").classList.remove("hidden"); + } + + } + catch (error) + { + document.getElementById("login-error-message").innerHTML = "error: server error, try again later..."; + document.getElementById("login-error-message").classList.remove("hidden"); + } + }; + + document.getElementById("login-button")?.addEventListener("click", login); + } +} diff --git a/src/front/static/ts/views/MainMenu.ts b/src/front/static/ts/views/MainMenu.ts new file mode 100644 index 0000000..9d00ee0 --- /dev/null +++ b/src/front/static/ts/views/MainMenu.ts @@ -0,0 +1,22 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + constructor() + { + super(); + this.setTitle("knl is trans(cendence)"); + } + + async getHTML() { + return ` +
+

knl_meowscendence :D

+

i like pong

+ + Pong + +
+ `; + } +} diff --git a/src/front/static/ts/views/PongMenu.ts b/src/front/static/ts/views/PongMenu.ts new file mode 100644 index 0000000..90dabdd --- /dev/null +++ b/src/front/static/ts/views/PongMenu.ts @@ -0,0 +1,21 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + constructor() + { + super(); + this.setTitle("ponging ur mom"); + } + + async getHTML() { + return ` +
+

pong is funny yay

+ + solo + +
+ `; + } +} diff --git a/src/front/static/ts/views/RegisterPage.ts b/src/front/static/ts/views/RegisterPage.ts new file mode 100644 index 0000000..7e97a62 --- /dev/null +++ b/src/front/static/ts/views/RegisterPage.ts @@ -0,0 +1,27 @@ +import Aview from "./Aview.ts" + +export default class extends Aview { + + constructor() + { + super(); + this.setTitle("ft_trans 🏳️‍⚧️"); + } + + async getHTML() { + return ` +
+

register

+ + + + + + + + i already have an account + +
+ `; + } +} diff --git a/src/front/style.css b/src/front/style.css deleted file mode 100644 index f5645cf..0000000 --- a/src/front/style.css +++ /dev/null @@ -1,5 +0,0 @@ -@import "tailwindcss"; - -/*@tailwind base; -@tailwind components; -@tailwind utilities;*/