diff --git a/frontend/src/pages/pong/broadcastMsg.ts b/frontend/src/pages/pong/broadcastMsg.ts
index ae049a5..2443278 100644
--- a/frontend/src/pages/pong/broadcastMsg.ts
+++ b/frontend/src/pages/pong/broadcastMsg.ts
@@ -9,7 +9,7 @@ import { getUser } from "@app/auth";
* @param msgCommand
*/
export function broadcastMsg (socket: Socket, msgCommand: string[]): void {
- let msgText = msgCommand[1] ?? "";
+ let msgText = msgCommand[1] ?? "";
addPongMessage(msgText);
const user = getUser();
if (user && socket?.connected) {
diff --git a/frontend/src/pages/pong/pong.html b/frontend/src/pages/pong/pong.html
index c46c9cd..0c9d2c3 100644
--- a/frontend/src/pages/pong/pong.html
+++ b/frontend/src/pages/pong/pong.html
@@ -1,25 +1,26 @@
-
-
-
- Pong Box
-
-
-
System: connecting ...
-
-
+
+
+
+
+
+
+ Pong Box
+
+
+
System: connecting ...
+
+
+
-
-
-
-
diff --git a/frontend/src/pages/pong/pong.ts b/frontend/src/pages/pong/pong.ts
index f960665..8a2a40b 100644
--- a/frontend/src/pages/pong/pong.ts
+++ b/frontend/src/pages/pong/pong.ts
@@ -7,6 +7,7 @@ import io, { Socket } from 'socket.io-client';
import { addPongMessage } from './addPongMessage';
import { isLoggedIn } from './isLoggedIn';
import type { ClientMessage, ClientProfil } from './types_front';
+import { isNullish } from "@app/utils";
export const color = {
red: 'color: red;',
@@ -21,7 +22,8 @@ const machineHostName = window.location.hostname;
console.log('connect to login at %chttps://' + machineHostName + ':8888/app/login',color.yellow);
export let __socket: Socket | undefined = undefined;
-document.addEventListener('ft:pageChange', () => {
+
+document.addEventListener('ft:pageChange', () => { // dont regen socket on page change from forward/backward navigation arrows
if (__socket !== undefined)
__socket.close();
__socket = undefined;
@@ -30,9 +32,8 @@ document.addEventListener('ft:pageChange', () => {
export function getSocket(): Socket {
let addressHost = `wss://${machineHostName}:8888`;
- // let addressHost = `wss://localhost:8888`;
- if (__socket === undefined)
+ if (__socket === undefined)
__socket = io(addressHost, {
path: "/api/pong/socket.io/",
secure: false,
@@ -41,19 +42,16 @@ export function getSocket(): Socket {
return __socket;
};
-
function waitSocketConnected(socket: Socket): Promise
{
- return new Promise(resolve => {
- if (socket.connected) return resolve();
- socket.on("connect", () => resolve());
- });
+ return new Promise(resolve => {
+ if (socket.connected) return resolve();
+ socket.on("connect", () => resolve());
+ });
};
-
async function whoami(socket: Socket) {
try {
const chatWindow = document.getElementById("t-chatbox") as HTMLDivElement;
- const loggedIn = isLoggedIn();
const res = await client.guestLogin();
switch (res.kind) {
@@ -80,148 +78,172 @@ async function whoami(socket: Socket) {
}
};
-
-
-
-
-function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn {
-
+function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn {
let socket = getSocket();
- /**
- * on connection plays this part
- */
-
socket.on("connect", async () => {
const systemWindow = document.getElementById('system-box') as HTMLDivElement;
await waitSocketConnected(socket);
console.log("I AM Connected to the server:", socket.id);
- const message = {
- command: "",
- destination: 'system-info',
- type: "chat",
- user: getUser()?.name,
- token: document.cookie ?? "",
- text: " has Just ARRIVED in the chat",
- timestamp: Date.now(),
- SenderWindowID: socket.id,
- };
- socket.emit('message', JSON.stringify(message));
+ // const message = {
+ // command: "",
+ // destination: 'system-info',
+ // type: "chat",
+ // user: getUser()?.name,
+ // token: document.cookie ?? "",
+ // text: " has Just ARRIVED in the chat",
+ // timestamp: Date.now(),
+ // SenderWindowID: socket.id,
+ // };
+ // socket.emit('message', JSON.stringify(message));
const messageElement = document.createElement("div");
- messageElement.textContent = `${message.user}: is connected au server`;
- systemWindow.appendChild(messageElement);
+ // messageElement.textContent = `${message.user}: is connected au server`;
+ messageElement.textContent = `${getUser()?.name ?? "unkown user"}: is connected au server`;
+ systemWindow.appendChild(messageElement);
systemWindow.scrollTop = systemWindow.scrollHeight;
});
-
+ // Queu handler
+ async function joinQueu(socket : Socket) {
+ try {
+ const res = await client.guestLogin();
+
+ switch (res.kind) {
+ case 'success': {
+ let user = await updateUser();
+
+ if (user === null)
+ return showError('Failed to get user: no user ?');
+ socket.emit('queuJoin', user.id);
+ console.log('queu join sent for : ', user.id);
+ break;
+ }
+ case 'failed': {
+ showError(`Failed to Join Game Queu: ${res.msg}`);
+ console.log('Failed to Join Game Queu');
+ }
+ }
+ } catch (err ) {
+ showError(`Failed to Join Game Queu`);
+ console.log('Failed to Join Game Queu');
+ }
+ }
+
+ // keys handler
const keys: Record = {};
document.addEventListener("keydown", (e) => {
keys[e.key.toLowerCase()] = true;
});
-
document.addEventListener("keyup", (e) => {
keys[e.key.toLowerCase()] = false;
});
-
- setInterval(() => {
- if (keys['w']) {
- socket.emit("batmove_Left", "up");
- console.log('north key pressed - emit batmove_Left up');
+ setInterval(() => { // key sender
+ if ((keys['w'] || keys['s']) && !(keys['w'] && keys['s'])) { // exclusive or to filter requests
+ if (keys['w']) {
+ socket.emit("batmove_Left", "up");
+ console.log('north key pressed - emit batmove_Left up');
+ }
+ if (keys['s']) {
+ socket.emit("batmove_Left", "down");
+ console.log('south key pressed - emit batmove_Left down');
+ }
}
- if (keys['s']) {
- socket.emit("batmove_Left", "down");
- console.log('south key pressed - emit batmove_Left down');
+ if ((keys['p'] || keys['l']) && !(keys['p'] && keys['l'])) { // exclusive or to filter requests
+ if (keys['p']) {
+ socket.emit("batmove_Right", "up");
+ console.log('north key pressed - emit batmove_Right up');
+ }
+ if (keys['l']) {
+ socket.emit("batmove_Right", "down");
+ console.log('south key pressed - emit batmove_Right down');
+ }
}
- if (keys['p']) {
- socket.emit("batmove_Right", "up");
- console.log('north key pressed - emit batmove_Right up');
- }
- if (keys['l']) {
- socket.emit("batmove_Right", "down");
- console.log('south key pressed - emit batmove_Right down');
- }
}, 16);
-
-
- // Listen for Left bat updates
- socket.on("batLeft_update", (y: number) => {
- console.log('batLeft_update received y: ', y);
+ // Pong Objects updators
+ socket.on("batLeft_update", (y: number) => {
+ console.log('batLeft_update received y: ', y);
const bat = document.getElementById("batleft") as HTMLDivElement | null;
- if (!bat) {
- console.error("FATAL ERROR: Bat element with ID 'bat-left' not found. Check HTML.");
+ if (!bat) {
+ console.error("FATAL ERROR: Bat element with ID 'bat-left' not found. Check HTML.");
return ;
- }
- if (typeof y === 'number' && !isNaN(y)) {
- bat.style.transform = `translateY(${y}px)`;
- } else {
- console.warn(`Received invalid Y value: ${y}`);
- }
- });
-
- // Listen for Right bat updates
- socket.on("batRight_update", (y: number) => {
- console.log('batRight_update received y: ', y);
- const bat = document.getElementById("batright") as HTMLDivElement | null;
- if (!bat) {
- console.error("FATAL ERROR: Bat element with ID 'bat-Right' not found. Check HTML.");
- return ;
- }
- if (typeof y === 'number' && !isNaN(y)) {
- bat.style.transform = `translateY(${y}px)`;
- } else {
- console.warn(`Received invalid Y value: ${y}`);
- }
- });
-
-
-
-
-
- socket.once('welcome', (data) => {
- console.log('%cWelcome PONG PAGE', color.yellow );
- addPongMessage('socket.once \'Welcome\' called')
+ }
+ if (typeof y === 'number' && !isNaN(y)) {
+ bat.style.transform = `translateY(${y}px)`;
+ } else {
+ console.warn(`Received invalid Y value: ${y}`);
+ }
});
+ socket.on("batRight_update", (y: number) => {
+ console.log('batRight_update received y: ', y);
+ const bat = document.getElementById("batright") as HTMLDivElement | null;
+ if (!bat) {
+ console.error("FATAL ERROR: Bat element with ID 'bat-Right' not found. Check HTML.");
+ return ;
+ }
+ if (typeof y === 'number' && !isNaN(y)) {
+ bat.style.transform = `translateY(${y}px)`;
+ } else {
+ console.warn(`Received invalid Y value: ${y}`);
+ }
+ });
+ socket.on("ballPos_update", (x:number, y : number) => {
+ console.log('ballPos_update recieved: ', x, ' / ', y);
+ const ball = document.getElementById("ball") as HTMLDivElement | null;
+ if (!ball) {
+ console.error("FATAL ERROR: Bat element with ID 'bat-Right' not found. Check HTML.");
+ return ;
+ }
+ if (typeof y !== 'number' || isNaN(y) || typeof x !== 'number' || isNaN(x)) {
+ console.warn(`Received invalid X/Y value: ${x} / ${y}`);
+ return ;
+ }
+ ball.style.transform = `translateY(${y}px)`;
+ ball.style.transform += `translateX(${x}px)`;
+ });
+
+ // socket.once('welcome', (data) => {
+ // console.log('%cWelcome PONG PAGE', color.yellow );
+ // addPongMessage('socket.once \'Welcome\' called')
+ // });
-
- // Listen for messages from the server "MsgObjectServer"
+ // Listen for messages from the server "MsgObjectServer"
socket.on("MsgObjectServer", (data: { message: ClientMessage}) => {
// Display the message in the chat window
const systemWindow = document.getElementById('system-box') as HTMLDivElement;
-
-
const MAX_SYSTEM_MESSAGES = 10;
if (systemWindow && data.message.destination === "system-info") {
- const messageElement = document.createElement("div");
- messageElement.textContent = `${data.message.user}: ${data.message.text}`;
- systemWindow.appendChild(messageElement);
+ const messageElement = document.createElement("div");
+ messageElement.textContent = `${data.message.user}: ${data.message.text}`;
+ systemWindow.appendChild(messageElement);
- // keep only last 10
- while (systemWindow.children.length > MAX_SYSTEM_MESSAGES) {
- systemWindow.removeChild(systemWindow.firstChild!);
- }
- systemWindow.scrollTop = systemWindow.scrollHeight;
+ // keep only last 10
+ while (systemWindow.children.length > MAX_SYSTEM_MESSAGES) {
+ systemWindow.removeChild(systemWindow.firstChild!);
+ }
+ systemWindow.scrollTop = systemWindow.scrollHeight;
}
console.log("Getuser():", getUser());
});
-
-
-
-
- setTitle('Pong Page');
+ setTitle('Pong Game Page');
return {
html: authHtml, postInsert: async (app) => {
const bwhoami = document.getElementById('b-whoami') as HTMLButtonElement;
-
+ const bqueu = document.getElementById('b-joinQueu') as HTMLButtonElement;
+
bwhoami?.addEventListener('click', async () => {
whoami(socket);
});
+ bqueu?.addEventListener('click', async () => {
+ joinQueu(socket);
+ });
+
}
}
};
-addRoute('/pong', handleChat, { bypass_auth: true });
\ No newline at end of file
+addRoute('/pong', pongClient, { bypass_auth: true });
\ No newline at end of file
diff --git a/frontend/src/pages/pong/types_front.ts b/frontend/src/pages/pong/types_front.ts
index 807d071..21ae2d9 100644
--- a/frontend/src/pages/pong/types_front.ts
+++ b/frontend/src/pages/pong/types_front.ts
@@ -6,7 +6,6 @@ export type ClientMessage = {
SenderWindowID: string;
};
-
export type ClientProfil = {
command: string,
destination: string,
diff --git a/frontend/src/pong/pong.css b/frontend/src/pong/pong.css
index 4df8ad0..c22229c 100644
--- a/frontend/src/pong/pong.css
+++ b/frontend/src/pong/pong.css
@@ -100,7 +100,6 @@
justify-center;
}
-
.text-style {
@apply
text-black
@@ -123,7 +122,6 @@
@apply absolute right-4 w-[12px] h-[80px] top-[0px];
}
-
.pong-center-line {
@apply
absolute
diff --git a/src/pong/package.json b/src/pong/package.json
index a3fd0e8..ecc4cab 100644
--- a/src/pong/package.json
+++ b/src/pong/package.json
@@ -30,7 +30,7 @@
"typebox": "^1.0.62"
},
"devDependencies": {
- "@types/node": "^22.19.2",
+ "@types/node": "^22.19.3",
"rollup-plugin-node-externals": "^8.1.2",
"vite": "^7.2.7",
"vite-tsconfig-paths": "^5.1.4"
diff --git a/src/pong/src/app.ts b/src/pong/src/app.ts
index 2bfc2c7..3277db9 100644
--- a/src/pong/src/app.ts
+++ b/src/pong/src/app.ts
@@ -10,6 +10,9 @@ import { broadcast } from './broadcast';
import type { ClientProfil, ClientMessage } from './chat_types';
import { sendInvite } from './sendInvite';
import { setGameLink } from './setGameLink';
+import { emit } from 'process';
+import { Record } from 'typebox/type';
+import { UserId } from '@shared/database/mixin/user';
@@ -80,7 +83,9 @@ declare module 'fastify' {
batmove_Right: (direction: "up" | "down") => void;
batLeft_update: (y:number) => void;
batRight_update: (y:number) => void;
+ ballPos_update: (x:number, y:number) => void;
MsgObjectServer: (data: { message: ClientMessage }) => void;
+ queuJoin: (userID : UserId) => void;
}>;
}
}
@@ -96,66 +101,116 @@ async function onReady(fastify: FastifyInstance) {
}
const SPEED = 20; // bat speed
- const BOTTOM_EDGE = 370; // bottom edge of the field;
- const TOP_EDGE = 0; // top edge of the field
- const START_POS_Y = 178; // bat y in the middle of the field
- let batLeft = START_POS_Y; //shared bat position
- let batRight = START_POS_Y; //shared bat position
-
- fastify.io.on('connection', (socket: Socket) => {
+ const TOP_EDGE = 0; // top edge of the field
+ const BOTTOM_EDGE = 450; // bottom edge of the field;
+ const LEFT_EDGE = 0;
+ const RIGHT_EDGE = 800;
+
+ const MAX_PADDLE_Y = 370; // BOTTOM_EDGE - padle_height
+ const START_POS_Y = 178; // bat y in the middle of the field
+
+ const START_BALLX = 364; //(RIGHT_EDGE / 2) - (ballradius*2 + ballBorder);
+ const START_BALLY = 189; //(BOTTOM_EDGE / 2) - (ballradius*2 + ballBorder);
+ const ACCELERATION_FACTOR = 1.15;
+
+ let batLeft = START_POS_Y; //shared start bat position
+ let batRight = START_POS_Y; //shared start bat position
+
+ let ballPosX = START_BALLX;
+ let ballPosY = START_BALLY;
+ let ballSpeedX = 1;
+ let ballSpeedY = 1;
+
+ let games : Record = {}; // uuid, game uid - if not in game empty string
+
+ fastify.io.on('connection', (socket: Socket) => {
socket.emit("batLeft_update", batLeft);
socket.emit("batRight_update", batRight);
+ socket.emit("ballPos_update", ballPosX, ballPosY);
- socket.on('batmove_Left', (direction: "up" | "down") => {
- if (direction === "up") {
- batLeft -= SPEED;
- console.log('w pressed UP');
- }
- if (direction === "down") {
- console.log('s pressed DOWN');
+ // GAME
+ // paddle handling
+ socket.on('batmove_Left', (direction: "up" | "down") => {
+ if (direction === "up") {
+ batLeft -= SPEED;
+ console.log('w pressed UP');
+ }
+ if (direction === "down") {
+ console.log('s pressed DOWN');
- batLeft += SPEED;
- }
- // position of bat leftplokoplpl
- batLeft = Math.max(TOP_EDGE, Math.min(BOTTOM_EDGE, batLeft));
+ batLeft += SPEED;
+ }
+ // position of bat leftplokoplpl
+ batLeft = Math.max(TOP_EDGE, Math.min(MAX_PADDLE_Y, batLeft));
+ console.log('batLeft_update is called y:',batLeft);
+ socket.emit("batLeft_update", batLeft);
+ });
+ socket.on('batmove_Right', (direction: "up" | "down") => {
+ if (direction === "up") {
+ batRight -= SPEED;
+ console.log('p pressed UP');
+ }
+ if (direction === "down") {
+ console.log('l pressed DOWN');
+ batRight += SPEED;
+ }
+ // position of bat left
+ batRight = Math.max(TOP_EDGE, Math.min(MAX_PADDLE_Y, batRight));
+ console.log('batRight_update is called y:',batRight);
+ socket.emit("batRight_update", batRight);
+ });
+ // ball handling:
+ // TODO 1: l/r bat hit
+ // TODO 2: l/r wall hit : score
+ setInterval(async () => {
+ const new_ballPosX = ballPosX + ballSpeedX;
+ const new_ballPosY = ballPosY + ballSpeedY;
+
+ if (new_ballPosX < 0 || new_ballPosX + 36*2 > RIGHT_EDGE) {
+ ballSpeedX *= -1;
+ ballSpeedX *= ACCELERATION_FACTOR;
+ ballSpeedY *= ACCELERATION_FACTOR;
+ // TODO: score point + ball reset + spd reset
+
+ }
+ if (new_ballPosY < 0 || new_ballPosY + 36*2 > BOTTOM_EDGE) {
+ ballSpeedY *= -1;
+ ballSpeedX *= ACCELERATION_FACTOR;
+ ballSpeedY *= ACCELERATION_FACTOR;
+ }
+ ballSpeedX = Math.max(-10, Math.min(ballSpeedX, 10));
+ ballSpeedY = Math.max(-10, Math.min(ballSpeedY, 10));
+
+ ballPosX += ballSpeedX;
+ ballPosY += ballSpeedY;
+
+ socket.emit("ballPos_update", ballPosX, ballPosY);
+ }, 1024)
- console.log('batLeft_update is called y:',batLeft);
+ // QUEU HANDL
+ socket.on('queuJoin', async (uuid: UserId) => {
+ console.log('queu join recieved for : ', uuid);
+ if (!games.hasOwnProperty(uuid)) {
+ console.log("new user in game search queu");
+ games[uuid] = "";
+ } else if (games.hasOwnProperty(uuid) && games[uuid] == "") {
+ console.log('already searching for game');
+ } else { // (games.hasOwnProperty(uuid) && games[uuid] != "") {
+ console.log('user alredy in game');
+ return ;
+ }
+ // TODO: step2 : sesrch in record<> find guid w/ "" &/ pair them up
+ // TODO: step3 : move game logic to lifecycle of queu'ed game
+ })
- socket.emit("batLeft_update", batLeft);
- });
-
- socket.on('batmove_Right', (direction: "up" | "down") => {
- if (direction === "up") {
- batRight -= SPEED;
- console.log('p pressed UP');
- }
- if (direction === "down") {
- console.log('l pressed DOWN');
-
- batRight += SPEED;
- }
- // position of bat left
- batRight = Math.max(TOP_EDGE, Math.min(BOTTOM_EDGE, batRight));
-
- console.log('batRight_update is called y:',batRight);
-
- socket.emit("batRight_update", batRight);
- });
-
-
-
-
-
-
-
+ // other:
socket.on('message', (message: string) => {
const obj: ClientMessage = JSON.parse(message) as ClientMessage;
clientChat.set(socket.id, { user: obj.user, lastSeen: Date.now() });
socket.emit('welcome', {msg: 'Welcome to the chat! : '});
broadcast(fastify, obj, obj.SenderWindowID);
});
-
socket.on('inviteGame', async (data: string) => {
const clientName: string = clientChat.get(socket.id)?.user || '';
const profilInvite: ClientProfil = JSON.parse(data) || '';
@@ -164,5 +219,6 @@ async function onReady(fastify: FastifyInstance) {
sendInvite(fastify, inviteHtml, profilInvite);
}
});
+
});
}