diff --git a/JEU/jsconfig.json b/JEU/jsconfig.json deleted file mode 100644 index 347bf03f..00000000 --- a/JEU/jsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "module": "ESNext", - "moduleResolution": "Node", - "target": "ES2020", - "strictNullChecks": true, - "strictFunctionTypes": true - }, - "exclude": [ - "node_modules", - "**/node_modules/*" - ] -} \ No newline at end of file diff --git a/JEU/make.sh b/JEU/make.sh deleted file mode 100644 index ebce024a..00000000 --- a/JEU/make.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -npx tsc - -mkdir -p www -cp ./src/client/*.html ./www/ -cp ./src/client/*.css ./www/ - -mkdir -p www/js -cp ./src/client/*.js ./www/js/ - -mkdir -p www/js/class -cp ./src/client/class/*.js ./www/js/class/ - -mkdir -p www/shared_js/ -cp ./src/shared_js/*.js ./www/shared_js/ - -mkdir -p www/shared_js/class -cp ./src/shared_js/class/*.js ./www/shared_js/class/ diff --git a/JEU/memo.txt b/JEU/memo.txt deleted file mode 100644 index 20d493f3..00000000 --- a/JEU/memo.txt +++ /dev/null @@ -1,45 +0,0 @@ -Done: - - Connexion client/serveur via un Websocket - - implémentation basique (authoritative server) - - Matchmaking - - client prediction - - server reconciliation (buffer des inputs côté client + id sur les inputs) - - amélioration collision avec Hugo - - du son (rebonds de la balle, "Oof" de Roblox sur un point) - - init de GameComponents partagé entre serveur et client. - - draw on the canvas "WIN", "LOSE", "MATCHMAKING COMPLETE", ... - - interpolation (mis à jour progressif des mouvements de l'adversaire) - - traitement groupé des inputs clients toutes les x millisecondes - (BUG désynchronisation: revenu à un traitement immédiat en attendant) - - Détruire les GameSession une fois finies. - - mode multi-balles - - mode murs mouvant (la zone de jeu rétréci / agrandi en continu) - - Selection des modes de jeu via HTML - - Selection audio on/off via HTML - -TODO: -- Match Abort si tout les joueurs ne sont pas pret assez vite (~15 secondes) -- mode spectateur -- certaines utilisations de Math.floor() superflu ? Vérifier les appels. - (éventuellement Math.round() ?) -- un autre mode de jeu alternatif ? -- changer les "localhost:8080" dans le code. -- sélection couleur des raquettes (your color/opponent color) dans le profil utilisateur. - Enregistrement dans la DB. - init des couleurs dans GameComponentsClient() basé sur les variables de l'utilsateur connecté. ------------ -idées modes de jeu : - - mode 2 raquettes (un joueur haut/gauche et bas/droite) - - skin patate ??? -- (prediction de l'avancement de la balle basé sur la latence serveur ?) -- d'autres sons (foule qui applaudi/musique de victoire) ------------ -- BUG: Si la balle va très vite, elle peut ignorer la collision avec une raquette ou mur. -la collision est testée seulement après le mouvement. -Pour éviter ce bug il faudrait diviser le mouvement pour faire plusieurs tests de collision successifs. -- BUG mineur: sur un changement de fenêtre, les touches restent enfoncées et il faut les "décoincer" -en réappuyant. Ce n'est pas grave mais peut-on faire mieux ? ----------- -OSEF, rebuts: -- reconnection -- amélioration du protocole, remplacement du JSON (compression. moins de bande passante). diff --git a/JEU/package-lock.json b/JEU/package-lock.json deleted file mode 100644 index 807c07eb..00000000 --- a/JEU/package-lock.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "name": "ft_transcendence", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "dependencies": { - "uuid": "^9.0.0", - "ws": "^8.10.0" - }, - "devDependencies": { - "@types/node": "^18.11.5", - "@types/uuid": "^8.3.4", - "@types/ws": "^8.5.3", - "typescript": "^4.8.4" - } - }, - "node_modules/@types/node": { - "version": "18.11.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.5.tgz", - "integrity": "sha512-3JRwhbjI+cHLAkUorhf8RnqUbFXajvzX4q6fMn5JwkgtuwfYtRQYI3u4V92vI6NJuTsbBQWWh3RZjFsuevyMGQ==", - "dev": true - }, - "node_modules/@types/uuid": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", - "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", - "dev": true - }, - "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/ws": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.10.0.tgz", - "integrity": "sha512-+s49uSmZpvtAsd2h37vIPy1RBusaLawVe8of+GyEPsaJTCMpj/2v8NpeK1SHXjBlQ95lQTmQofOJnFiLoaN3yw==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - }, - "dependencies": { - "@types/node": { - "version": "18.11.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.5.tgz", - "integrity": "sha512-3JRwhbjI+cHLAkUorhf8RnqUbFXajvzX4q6fMn5JwkgtuwfYtRQYI3u4V92vI6NJuTsbBQWWh3RZjFsuevyMGQ==", - "dev": true - }, - "@types/uuid": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", - "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", - "dev": true - }, - "@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true - }, - "uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" - }, - "ws": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.10.0.tgz", - "integrity": "sha512-+s49uSmZpvtAsd2h37vIPy1RBusaLawVe8of+GyEPsaJTCMpj/2v8NpeK1SHXjBlQ95lQTmQofOJnFiLoaN3yw==", - "requires": {} - } - } -} diff --git a/JEU/package.json b/JEU/package.json deleted file mode 100644 index f8f23534..00000000 --- a/JEU/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "module", - "devDependencies": { - "@types/node": "^18.11.5", - "@types/uuid": "^8.3.4", - "@types/ws": "^8.5.3", - "typescript": "^4.8.4" - }, - "dependencies": { - "uuid": "^9.0.0", - "ws": "^8.10.0" - } -} diff --git a/JEU/src/client/audio.ts b/JEU/src/client/audio.ts deleted file mode 100644 index 74c73336..00000000 --- a/JEU/src/client/audio.ts +++ /dev/null @@ -1,16 +0,0 @@ - -import * as c from "./constants.js" - -export const soundPongArr: HTMLAudioElement[] = []; -export const soundRoblox = new Audio("http://localhost:8080/sound/roblox-oof.ogg"); - -export function initAudio(muteFlag: boolean) -{ - for (let i = 0; i <= 32; i++) { - soundPongArr.push(new Audio("http://localhost:8080/sound/pong/"+i+".ogg")); - soundPongArr[i].volume = c.soundPongVolume; - soundPongArr[i].muted = muteFlag; - } - soundRoblox.volume = c.soundRobloxVolume; - soundRoblox.muted = muteFlag; -} diff --git a/JEU/src/client/class/GameArea.ts b/JEU/src/client/class/GameArea.ts deleted file mode 100644 index e6921e4e..00000000 --- a/JEU/src/client/class/GameArea.ts +++ /dev/null @@ -1,38 +0,0 @@ - -import * as c from ".././constants.js" - -class GameArea { - keys: string[] = []; - handleInputInterval: number = 0; - gameLoopInterval: number = 0; - drawLoopInterval: number = 0; - canvas: HTMLCanvasElement; - ctx: CanvasRenderingContext2D; - constructor() { - this.canvas = document.createElement("canvas"); - this.ctx = this.canvas.getContext("2d") as CanvasRenderingContext2D; - this.canvas.width = c.CanvasWidth; - this.canvas.height = c.CanvasWidth / c.CanvasRatio; - let container = document.getElementById("canvas_container"); - if (container) - container.insertBefore(this.canvas, container.childNodes[0]); - } - addKey(key: string) { - key = key.toLowerCase(); - var i = this.keys.indexOf(key); - if (i == -1) - this.keys.push(key); - } - deleteKey(key: string) { - key = key.toLowerCase(); - var i = this.keys.indexOf(key); - if (i != -1) { - this.keys.splice(i, 1); - } - } - clear() { - this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); - } -} - -export {GameArea} diff --git a/JEU/src/client/class/GameComponentsClient.ts b/JEU/src/client/class/GameComponentsClient.ts deleted file mode 100644 index bf90f66f..00000000 --- a/JEU/src/client/class/GameComponentsClient.ts +++ /dev/null @@ -1,114 +0,0 @@ - -import * as c from "../constants.js" -import * as en from "../../shared_js/enums.js" -import { Vector, VectorInteger } from "../../shared_js/class/Vector.js"; -import { TextElem, TextNumericValue } from "./Text.js"; -import { RectangleClient, MovingRectangleClient, RacketClient, BallClient, Line } from "./RectangleClient.js"; -import { GameComponents } from "../../shared_js/class/GameComponents.js"; -import { MovingRectangle } from "../../shared_js/class/Rectangle.js"; - -class GameComponentsExtensionForClient extends GameComponents { - wallTop: RectangleClient | MovingRectangleClient; - wallBottom: RectangleClient | MovingRectangleClient; - playerLeft: RacketClient; - playerRight: RacketClient; - ballsArr: BallClient[]; - constructor(options: en.MatchOptions, ctx: CanvasRenderingContext2D) - { - super(options); - - // Rackets - const basePL = this.playerLeft; - const basePR = this.playerRight; - this.playerLeft = new RacketClient( - basePL.pos, basePL.width, basePL.height, basePL.baseSpeed, - ctx, "white"); - this.playerRight = new RacketClient( - basePR.pos, basePR.width, basePR.height, basePR.baseSpeed, - ctx, "white"); - - // Balls - const newBallsArr: BallClient[] = []; - this.ballsArr.forEach((ball) => { - newBallsArr.push(new BallClient(ball.pos, ball.width, ball.baseSpeed, ball.speedIncrease, - ctx, "white") - ); - }); - this.ballsArr = newBallsArr; - - // Walls - if (options & en.MatchOptions.movingWalls) - { - const baseWT = this.wallTop; - const baseWB = this.wallBottom; - - this.wallTop = new MovingRectangleClient(baseWT.pos, baseWT.width, baseWT.height, baseWT.baseSpeed, - ctx, "grey"); - (this.wallTop).dir.assign(baseWT.dir.x, baseWT.dir.y); - - this.wallBottom = new MovingRectangleClient(baseWB.pos, baseWB.width, baseWB.height, baseWB.baseSpeed, - ctx, "grey"); - (this.wallBottom).dir.assign(baseWB.dir.x, baseWB.dir.y); - } - else - { - const baseWT = this.wallTop; - const baseWB = this.wallBottom; - this.wallTop = new RectangleClient(baseWT.pos, baseWT.width, baseWT.height, - ctx, "grey"); - this.wallBottom = new RectangleClient(baseWB.pos, baseWB.width, baseWB.height, - ctx, "grey"); - } - } -} - - -class GameComponentsClient extends GameComponentsExtensionForClient { - midLine: Line; - scoreLeft: TextNumericValue; - scoreRight: TextNumericValue; - text1: TextElem; - - w_grid_mid: RectangleClient; - w_grid_u1: RectangleClient; - w_grid_d1: RectangleClient; - h_grid_mid: RectangleClient; - h_grid_u1: RectangleClient; - h_grid_d1: RectangleClient; - constructor(options: en.MatchOptions, ctx: CanvasRenderingContext2D) - { - super(options, ctx); - let pos = new VectorInteger; - // Scores - pos.assign(c.w_mid-c.scoreSize*1.6, c.scoreSize*1.5); - this.scoreLeft = new TextNumericValue(pos, c.scoreSize, ctx, "white"); - pos.assign(c.w_mid+c.scoreSize*1.1, c.scoreSize*1.5); - this.scoreRight = new TextNumericValue(pos, c.scoreSize, ctx, "white"); - this.scoreLeft.value = 0; - this.scoreRight.value = 0; - - // Text - pos.assign(0, c.h_mid); - this.text1 = new TextElem(pos, Math.floor(c.w/8), ctx, "white"); - - // Dotted Midline - pos.assign(c.w_mid-c.midLineSize/2, 0+c.wallSize); - this.midLine = new Line(pos, c.midLineSize, c.h-c.wallSize*2, ctx, "white", 15); - - // Grid - pos.assign(0, c.h_mid); - this.w_grid_mid = new RectangleClient(pos, c.w, c.gridSize, ctx, "darkgreen"); - pos.assign(0, c.h/4); - this.w_grid_u1 = new RectangleClient(pos, c.w, c.gridSize, ctx, "darkgreen"); - pos.assign(0, c.h-c.h/4); - this.w_grid_d1 = new RectangleClient(pos, c.w, c.gridSize, ctx, "darkgreen"); - pos.assign(c.w_mid, 0); - this.h_grid_mid = new RectangleClient(pos, c.gridSize, c.h, ctx, "darkgreen"); - pos.assign(c.w/4, 0); - this.h_grid_u1 = new RectangleClient(pos, c.gridSize, c.h, ctx, "darkgreen"); - pos.assign(c.w-c.w/4, 0); - this.h_grid_d1 = new RectangleClient(pos, c.gridSize, c.h, ctx, "darkgreen"); - } -} - -export {GameComponentsClient} diff --git a/JEU/src/client/class/InputHistory.ts b/JEU/src/client/class/InputHistory.ts deleted file mode 100644 index e4d3b8f1..00000000 --- a/JEU/src/client/class/InputHistory.ts +++ /dev/null @@ -1,16 +0,0 @@ - -import * as en from "../../shared_js/enums.js" -import * as ev from "../../shared_js/class/Event.js" - -class InputHistory { - input: en.InputEnum; - id: number; - deltaTime: number; - constructor(inputState: ev.EventInput, deltaTime: number) { - this.input = inputState.input; - this.id = inputState.id; - this.deltaTime = deltaTime; - } -} - -export {InputHistory} diff --git a/JEU/src/client/class/RectangleClient.ts b/JEU/src/client/class/RectangleClient.ts deleted file mode 100644 index 5c251704..00000000 --- a/JEU/src/client/class/RectangleClient.ts +++ /dev/null @@ -1,141 +0,0 @@ - -import { Vector, VectorInteger } from "../../shared_js/class/Vector.js"; -import { Component, GraphicComponent, Moving } from "../../shared_js/class/interface.js"; -import { Rectangle, MovingRectangle, Racket, Ball } from "../../shared_js/class/Rectangle.js"; -import { soundPongArr } from "../audio.js" -import { random } from "../utils.js"; - -function updateRectangle(this: RectangleClient) { - this.ctx.fillStyle = this.color; - this.ctx.fillRect(this.pos.x, this.pos.y, this.width, this.height); -} - -function clearRectangle(this: RectangleClient, pos?: VectorInteger) { - if (pos) - this.ctx.clearRect(pos.x, pos.y, this.width, this.height); - else - this.ctx.clearRect(this.pos.x, this.pos.y, this.width, this.height); -} - -class RectangleClient extends Rectangle implements GraphicComponent { - ctx: CanvasRenderingContext2D; - color: string; - update: () => void; - clear: (pos?: VectorInteger) => void; - constructor(pos: VectorInteger, width: number, height: number, - ctx: CanvasRenderingContext2D, color: string) - { - super(pos, width, height); - this.ctx = ctx; - this.color = color; - this.update = updateRectangle; - this.clear = clearRectangle; - } - // update() { - // this.ctx.fillStyle = this.color; - // this.ctx.fillRect(this.pos.x, this.pos.y, this.width, this.height); - // } - // clear(pos?: VectorInteger) { - // if (pos) - // this.ctx.clearRect(pos.x, pos.y, this.width, this.height); - // else - // this.ctx.clearRect(this.pos.x, this.pos.y, this.width, this.height); - // } -} - -class MovingRectangleClient extends MovingRectangle implements GraphicComponent { - ctx: CanvasRenderingContext2D; - color: string; - update: () => void; - clear: (pos?: VectorInteger) => void; - constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number, - ctx: CanvasRenderingContext2D, color: string) - { - super(pos, width, height, baseSpeed); - this.ctx = ctx; - this.color = color; - this.update = updateRectangle; - this.clear = clearRectangle; - } -} - -class RacketClient extends Racket implements GraphicComponent { - ctx: CanvasRenderingContext2D; - color: string; - update: () => void; - clear: (pos?: VectorInteger) => void; - constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number, - ctx: CanvasRenderingContext2D, color: string) - { - super(pos, width, height, baseSpeed); - this.ctx = ctx; - this.color = color; - this.update = updateRectangle; - this.clear = clearRectangle; - } -} - -class BallClient extends Ball implements GraphicComponent { - ctx: CanvasRenderingContext2D; - color: string; - update: () => void; - clear: (pos?: VectorInteger) => void; - constructor(pos: VectorInteger, size: number, baseSpeed: number, speedIncrease: number, - ctx: CanvasRenderingContext2D, color: string) - { - super(pos, size, baseSpeed, speedIncrease); - this.ctx = ctx; - this.color = color; - this.update = updateRectangle; - this.clear = clearRectangle; - } - bounce(collider?: Rectangle) { - this._bounceAlgo(collider); - soundPongArr[ Math.floor(random(0, soundPongArr.length)) ].play(); - } - /* protected _bounceRacket(collider: Racket) { - this._bounceRacketAlgo(collider); - soundRoblox.play(); - } */ -} - -function updateLine(this: Line) { - this.ctx.fillStyle = this.color; - let pos: VectorInteger = new VectorInteger; - let i = 0; - while (i < this.segmentCount) - { - // for Horizontal Line - // pos.y = this.pos.y; - // pos.x = this.pos.x + this.segmentWidth * i; - pos.x = this.pos.x; - pos.y = this.pos.y + this.segmentHeight * i; - this.ctx.fillRect(pos.x, pos.y, this.segmentWidth, this.segmentHeight); - i += 2; - } -} - -class Line extends RectangleClient { - gapeCount: number = 0; - segmentCount: number; - segmentWidth: number; - segmentHeight: number; - constructor(pos: VectorInteger, width: number, height: number, - ctx: CanvasRenderingContext2D, color: string, gapeCount?: number) - { - super(pos, width, height, ctx, color); - this.update = updateLine; - if (gapeCount) - this.gapeCount = gapeCount; - this.segmentCount = this.gapeCount * 2 + 1; - - this.segmentWidth = this.width; - this.segmentHeight = this.height / this.segmentCount; - - // for Horizontal Line - // this.segmentWidth = this.width / this.segmentCount; - // this.segmentHeight = this.height; - } -} - -export {RectangleClient, MovingRectangleClient, RacketClient, BallClient, Line} diff --git a/JEU/src/client/class/Text.ts b/JEU/src/client/class/Text.ts deleted file mode 100644 index 88111131..00000000 --- a/JEU/src/client/class/Text.ts +++ /dev/null @@ -1,58 +0,0 @@ - -import { Vector, VectorInteger } from "../../shared_js/class/Vector.js"; -import { Component } from "../../shared_js/class/interface.js"; - -// conflict with Text -class TextElem implements Component { - ctx: CanvasRenderingContext2D; - pos: VectorInteger; - color: string; - size: number; - font: string; - text: string = ""; - constructor(pos: VectorInteger, size: number, - ctx: CanvasRenderingContext2D, color: string, font: string = "Bit5x3") - { - // this.pos = Object.assign({}, pos); // create bug, Uncaught TypeError: X is not a function - this.pos = new VectorInteger(pos.x, pos.y); - this.size = size; - this.ctx = ctx; - this.color = color; - this.font = font; - } - update() { - this.ctx.font = this.size + "px" + " " + this.font; - this.ctx.fillStyle = this.color; - this.ctx.fillText(this.text, this.pos.x, this.pos.y); - } - clear() { - // clear no very accurate for Text - // https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics - let textMetric = this.ctx.measureText(this.text); - // console.log("textMetric.width = "+textMetric.width); - // console.log("size = "+this.size); - // console.log("x = "+this.pos.x); - // console.log("y = "+this.pos.y); - this.ctx.clearRect(this.pos.x - 1, this.pos.y-this.size + 1, textMetric.width, this.size); - // +1 and -1 because float imprecision (and Math.floor() with VectorInteger dont work for the moment) - // (or maybe its textMetric imprecision ?) - } -} - -class TextNumericValue extends TextElem { - private _value: number = 0; - constructor(pos: VectorInteger, size: number, - ctx: CanvasRenderingContext2D, color: string, font?: string) - { - super(pos, size, ctx, color, font); - } - get value() { - return this._value; - } - set value(v: number) { - this._value = v; - this.text = v.toString(); - } -} - -export {TextElem, TextNumericValue} diff --git a/JEU/src/client/constants.ts b/JEU/src/client/constants.ts deleted file mode 100644 index 97bae265..00000000 --- a/JEU/src/client/constants.ts +++ /dev/null @@ -1,18 +0,0 @@ - -import { w } from "../shared_js/constants.js" -export * from "../shared_js/constants.js" - -export const midLineSize = Math.floor(w/150); -export const scoreSize = Math.floor(w/16); -export const gridSize = Math.floor(w/500); - -// min interval on Firefox seems to be 15. Chrome can go lower. -export const handleInputIntervalMS = 15; // millisecond -export const sendLoopIntervalMS = 15; // millisecond // unused -export const gameLoopIntervalMS = 15; // millisecond -export const drawLoopIntervalMS = 15; // millisecond - -export const fixedDeltaTime = gameLoopIntervalMS/1000; // second - -export const soundRobloxVolume = 0.3; // between 0 and 1 -export const soundPongVolume = 0.3; // between 0 and 1 diff --git a/JEU/src/client/draw.ts b/JEU/src/client/draw.ts deleted file mode 100644 index 984c2acb..00000000 --- a/JEU/src/client/draw.ts +++ /dev/null @@ -1,51 +0,0 @@ - -import { pong, gc } from "./global.js" -import * as c from "./constants.js" -import * as en from "../shared_js/enums.js" -import { gridDisplay } from "./handleInput.js"; - -function drawLoop() -{ - pong.clear(); - - if (gridDisplay) { - drawGrid(); - } - - drawStatic(); - - gc.text1.update(); - - drawDynamic(); -} - -function drawDynamic() -{ - gc.scoreLeft.update(); - gc.scoreRight.update(); - gc.playerLeft.update(); - gc.playerRight.update(); - gc.ballsArr.forEach((ball) => { - ball.update(); - }); -} - -function drawStatic() -{ - gc.midLine.update(); - gc.wallTop.update(); - gc.wallBottom.update(); -} - -function drawGrid() -{ - gc.w_grid_mid.update(); - gc.w_grid_u1.update(); - gc.w_grid_d1.update(); - - gc.h_grid_mid.update(); - gc.h_grid_u1.update(); - gc.h_grid_d1.update(); -} - -export {drawLoop} diff --git a/JEU/src/client/gameLoop.ts b/JEU/src/client/gameLoop.ts deleted file mode 100644 index 593d1eaa..00000000 --- a/JEU/src/client/gameLoop.ts +++ /dev/null @@ -1,49 +0,0 @@ - -import * as c from "./constants.js"; -import * as en from "../shared_js/enums.js" -import { gc, matchOptions, clientInfo } from "./global.js"; -import { wallsMovements } from "../shared_js/wallsMovement.js"; - -let actual_time: number = Date.now(); -let last_time: number; -let delta_time: number; - -function gameLoop() -{ - /* last_time = actual_time; - actual_time = Date.now(); - delta_time = (actual_time - last_time) / 1000; */ - - delta_time = c.fixedDeltaTime; - // console.log(`delta_gameLoop: ${delta_time}`); - - // interpolation - // console.log(`dir.y: ${clientInfo.opponent.dir.y}, pos.y: ${clientInfo.opponent.pos.y}, opponentNextPos.y: ${clientInfo.opponentNextPos.y}`); - if (clientInfo.opponent.dir.y != 0 ) { - opponentInterpolation(delta_time); - } - - // client prediction - gc.ballsArr.forEach((ball) => { - ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); - }); - - if (matchOptions & en.MatchOptions.movingWalls) { - wallsMovements(delta_time, gc); - } -} - -function opponentInterpolation(delta: number) -{ - // interpolation - clientInfo.opponent.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]); - - if ((clientInfo.opponent.dir.y > 0 && clientInfo.opponent.pos.y > clientInfo.opponentNextPos.y) - || (clientInfo.opponent.dir.y < 0 && clientInfo.opponent.pos.y < clientInfo.opponentNextPos.y)) - { - clientInfo.opponent.dir.y = 0; - clientInfo.opponent.pos.y = clientInfo.opponentNextPos.y; - } -} - -export {gameLoop} diff --git a/JEU/src/client/global.ts b/JEU/src/client/global.ts deleted file mode 100644 index 7d0a7126..00000000 --- a/JEU/src/client/global.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export {pong, gc, matchOptions} from "./pong.js" -export {socket, clientInfo} from "./ws.js" diff --git a/JEU/src/client/handleInput.ts b/JEU/src/client/handleInput.ts deleted file mode 100644 index 164680e1..00000000 --- a/JEU/src/client/handleInput.ts +++ /dev/null @@ -1,110 +0,0 @@ - -import { pong, gc, socket, clientInfo } from "./global.js" -import * as ev from "../shared_js/class/Event.js" -import * as en from "../shared_js/enums.js" -import { InputHistory } from "./class/InputHistory.js" -import * as c from "./constants.js"; - -export let gridDisplay = false; - -let actual_time: number = Date.now(); -let last_time: number; -let delta_time: number; - -const inputState: ev.EventInput = new ev.EventInput(); -const inputHistoryArr: InputHistory[] = []; - -// test -/* export function sendLoop() -{ - socket.send(JSON.stringify(inputState)); -} */ - -function handleInput() -{ - /* last_time = actual_time; - actual_time = Date.now(); - delta_time = (actual_time - last_time) / 1000; */ - - delta_time = c.fixedDeltaTime; - // console.log(`delta_time: ${delta_time}`); - - inputState.id = Date.now(); - inputState.input = en.InputEnum.noInput; - - const keys = pong.keys; - if (keys.length !== 0) - { - if (keys.indexOf("g") != -1) - { - gridDisplay = !gridDisplay; - pong.deleteKey("g"); - } - playerMovements(delta_time, keys); - } - - socket.send(JSON.stringify(inputState)); - // setTimeout(testInputDelay, 100); - inputHistoryArr.push(new InputHistory(inputState, delta_time)); - - // client prediction - if (inputState.input !== en.InputEnum.noInput) { - // TODO: peut-etre le mettre dans game loop ? - // Attention au delta time dans ce cas ! - playerMovePrediction(delta_time, inputState.input); - } -} - -function playerMovements(delta: number, keys: string[]) -{ - if (keys.indexOf("w") !== -1 || keys.indexOf("ArrowUp".toLowerCase()) !== -1) - { - if (keys.indexOf("s") === -1 && keys.indexOf("ArrowDown".toLowerCase()) === -1) { - inputState.input = en.InputEnum.up; - } - } - else if (keys.indexOf("s") !== -1 || keys.indexOf("ArrowDown".toLowerCase()) !== -1) { - inputState.input = en.InputEnum.down; - } -} - -function testInputDelay() { - socket.send(JSON.stringify(inputState)); -} - - -function playerMovePrediction(delta: number, input: en.InputEnum) -{ - // client prediction - const racket = clientInfo.racket; - if (input === en.InputEnum.up) { - racket.dir.y = -1; - } - else if (input === en.InputEnum.down) { - racket.dir.y = 1; - } - racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]); -} - -function repeatInput(lastInputId: number) -{ - // server reconciliation - let i = inputHistoryArr.findIndex((value: InputHistory) => { - if (value.id === lastInputId) { - return true; - } - return false; - }); - - // console.log(`inputHistory total: ${inputHistoryArr.length}` ); - inputHistoryArr.splice(0, i+1); - // console.log(`inputHistory left: ${inputHistoryArr.length}` ); - - inputHistoryArr.forEach((value: InputHistory) => { - if (value.input !== en.InputEnum.noInput) { - playerMovePrediction(value.deltaTime, value.input); - } - }); -} - -export {handleInput, repeatInput} diff --git a/JEU/src/client/pong.css b/JEU/src/client/pong.css deleted file mode 100644 index c481c502..00000000 --- a/JEU/src/client/pong.css +++ /dev/null @@ -1,53 +0,0 @@ - -@font-face { - font-family: "Bit5x3"; - src: url("http://localhost:8080/Bit5x3.woff2") format("woff2"), - url("http://localhost:8080/Bit5x3.woff") format("woff"); - font-weight: normal; - font-style: normal; - font-display: swap; -} -#preload_font { - font-family: "Bit5x3"; - opacity:0; - height:0; - width:0; - display:inline-block; -} -body { - margin: 0; - background-color: #222425; -} -#canvas_container { - text-align: center; - /* border: dashed rgb(245, 245, 245) 5px; */ - /* max-height: 80vh; */ - /* overflow: hidden; */ -} -#div_game_options { - text-align: center; - font-family: "Bit5x3"; - color: rgb(245, 245, 245); - font-size: x-large; -} -#div_game_options fieldset { - max-width: 50vw; - width: auto; - margin: 0 auto; -} -#div_game_options fieldset div { - padding: 10px; -} -#play_pong_button { - font-family: "Bit5x3"; - color: rgb(245, 245, 245); - background-color: #333333; - font-size: x-large; - padding: 10px; -} -canvas { - background-color: #333333; - max-width: 75vw; - /* max-height: 100vh; */ - width: 80%; -} diff --git a/JEU/src/client/pong.html b/JEU/src/client/pong.html deleted file mode 100644 index d23e5590..00000000 --- a/JEU/src/client/pong.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - -
.
- -
-
- game options -
- - -
-
- - -
-
- - - - - -
-
- -
-
-
- -
- -
- - - - - diff --git a/JEU/src/client/pong.ts b/JEU/src/client/pong.ts deleted file mode 100644 index 5c9dcce0..00000000 --- a/JEU/src/client/pong.ts +++ /dev/null @@ -1,99 +0,0 @@ - -initDom(); -function initDom() { - document.getElementById("play_pong_button").addEventListener("click", init); -} - -import * as c from "./constants.js" -import * as en from "../shared_js/enums.js" -import { GameArea } from "./class/GameArea.js"; -import { GameComponentsClient } from "./class/GameComponentsClient.js"; -import { handleInput } from "./handleInput.js"; -// import { sendLoop } from "./handleInput.js"; -import { gameLoop } from "./gameLoop.js" -import { drawLoop } from "./draw.js"; -import { countdown } from "./utils.js"; -import { initWebSocket } from "./ws.js"; -import { initAudio } from "./audio.js"; - - -/* Keys - Racket: W/S OR Up/Down - Grid On-Off: G -*/ - -/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */ -export let pong: GameArea; -export let gc: GameComponentsClient; -export let matchOptions: en.MatchOptions = en.MatchOptions.noOption; - -function init() -{ - console.log("multi_balls:"+(document.getElementById("multi_balls")).checked); - console.log("moving_walls:"+(document.getElementById("moving_walls")).checked); - console.log("sound_on:"+(document.getElementById("sound_on")).checked); - - let soundMutedFlag = false; - if ( (document.getElementById("sound_off")).checked ) { - soundMutedFlag = true; - } - initAudio(soundMutedFlag); - - if ( (document.getElementById("multi_balls")).checked ) { - matchOptions |= en.MatchOptions.multiBalls; - } - if ( (document.getElementById("moving_walls")).checked ) { - matchOptions |= en.MatchOptions.movingWalls; - } - - document.getElementById("div_game_options").hidden = true; - - pong = new GameArea(); - gc = new GameComponentsClient(matchOptions, pong.ctx); - initWebSocket(matchOptions); -} - -function matchmaking() -{ - console.log("Searching an opponent..."); - gc.text1.clear(); - gc.text1.pos.assign(c.w/5, c.h_mid); - gc.text1.text = "Searching..."; - gc.text1.update(); -} - -function matchmakingComplete() -{ - console.log("Match Found !"); - gc.text1.clear(); - gc.text1.pos.assign(c.w/8, c.h_mid); - gc.text1.text = "Match Found !"; - gc.text1.update(); -} - -function startGame() { - gc.text1.pos.assign(c.w_mid, c.h_mid+c.h/4); - countdown(c.matchStartDelay/1000, (count: number) => { - gc.text1.clear(); - gc.text1.text = `${count}`; - gc.text1.update(); - }, resumeGame); -} - -function resumeGame() -{ - gc.text1.text = ""; - window.addEventListener('keydown', function (e) { - pong.addKey(e.key); - }); - window.addEventListener('keyup', function (e) { - pong.deleteKey(e.key); - }); - pong.handleInputInterval = window.setInterval(handleInput, c.handleInputIntervalMS); - // pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS); - pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS); - pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS); -} - - -export {matchmaking, matchmakingComplete, startGame} diff --git a/JEU/src/client/utils.ts b/JEU/src/client/utils.ts deleted file mode 100644 index db971447..00000000 --- a/JEU/src/client/utils.ts +++ /dev/null @@ -1,18 +0,0 @@ - -export * from "../shared_js/utils.js" - -function countdown(count: number, callback?: (count: number) => void, endCallback?: () => void) -{ - console.log("countdown ", count); - if (count > 0) { - if (callback) { - callback(count); - } - setTimeout(countdown, 1000, --count, callback, endCallback); - } - else if (endCallback) { - endCallback(); - } -} - -export {countdown} diff --git a/JEU/src/client/ws.ts b/JEU/src/client/ws.ts deleted file mode 100644 index 60f1ab87..00000000 --- a/JEU/src/client/ws.ts +++ /dev/null @@ -1,182 +0,0 @@ - -import * as c from "./constants.js" -import { gc, matchOptions } from "./global.js" -import * as ev from "../shared_js/class/Event.js" -import * as en from "../shared_js/enums.js" -import { matchmaking, matchmakingComplete, startGame } from "./pong.js"; -import { RacketClient } from "./class/RectangleClient.js"; -import { repeatInput } from "./handleInput.js"; -import { soundRoblox } from "./audio.js" -import { sleep } from "./utils.js"; -import { Vector, VectorInteger } from "../shared_js/class/Vector.js"; - -class ClientInfo { - id = ""; - side: en.PlayerSide; - racket: RacketClient; - opponent: RacketClient; - opponentNextPos: VectorInteger; -} - -const wsPort = 8042; -const wsUrl = "ws://" + document.location.hostname + ":" + wsPort + "/pong"; -export let socket: WebSocket; /* TODO: A way to still use "const" not "let" ? */ -export const clientInfo = new ClientInfo(); - -export function initWebSocket(options: en.MatchOptions) -{ - socket = new WebSocket(wsUrl, "json"); - socket.addEventListener("open", (event) => { - socket.send(JSON.stringify( new ev.ClientAnnounce(en.ClientRole.player, options, clientInfo.id) )); - }); - // socket.addEventListener("message", logListener); // for testing purpose - socket.addEventListener("message", preMatchListener); -} - -function logListener(this: WebSocket, event: MessageEvent) { - console.log("%i: " + event.data, Date.now()); -} - -function preMatchListener(this: WebSocket, event: MessageEvent) -{ - const data: ev.ServerEvent = JSON.parse(event.data); - switch (data.type) { - case en.EventTypes.assignId: - clientInfo.id = (data).id; - break; - case en.EventTypes.matchmakingInProgress: - matchmaking(); - break; - case en.EventTypes.matchmakingComplete: - clientInfo.side = (data).side; - if (clientInfo.side === en.PlayerSide.left) - { - clientInfo.racket = gc.playerLeft; - clientInfo.opponent = gc.playerRight; - } - else if (clientInfo.side === en.PlayerSide.right) - { - clientInfo.racket = gc.playerRight; - clientInfo.opponent = gc.playerLeft; - } - clientInfo.opponentNextPos = new VectorInteger(clientInfo.opponent.pos.x, clientInfo.opponent.pos.y); - clientInfo.racket.color = "darkgreen"; // for testing purpose - socket.send(JSON.stringify( new ev.ClientEvent(en.EventTypes.clientPlayerReady) )); // TODO: set an interval/timeout to resend until matchStart response (in case of network problem) - matchmakingComplete(); - break; - case en.EventTypes.matchStart: - socket.removeEventListener("message", preMatchListener); - socket.addEventListener("message", inGameListener); - startGame(); - break; - } -} - -function inGameListener(event: MessageEvent) -{ - const data: ev.ServerEvent = JSON.parse(event.data); - switch (data.type) { - case en.EventTypes.gameUpdate: - // setTimeout(gameUpdate, 500, data as ev.EventGameUpdate); // artificial latency for testing purpose - gameUpdate(data as ev.EventGameUpdate); - break; - case en.EventTypes.scoreUpdate: - scoreUpdate(data as ev.EventScoreUpdate); - break; - case en.EventTypes.matchEnd: - matchEnd(data as ev.EventMatchEnd); - break; - } -} - -function gameUpdate(data: ev.EventGameUpdate) -{ - console.log("gameUpdate"); - - if (matchOptions & en.MatchOptions.movingWalls) { - gc.wallTop.pos.y = data.wallTop.y; - gc.wallBottom.pos.y = data.wallBottom.y; - } - - data.ballsArr.forEach((ball, i) => { - gc.ballsArr[i].pos.assign(ball.x, ball.y); - gc.ballsArr[i].dir.assign(ball.dirX, ball.dirY); - gc.ballsArr[i].speed = ball.speed; - }); - /* // Equivalent to - gc.ballsArr.forEach((ball, i) => { - ball.pos.assign(data.ballsArr[i].x, data.ballsArr[i].y); - ball.dir.assign(data.ballsArr[i].dirX, data.ballsArr[i].dirY); - ball.speed = data.ballsArr[i].speed; - }); */ - - const predictionPos = new VectorInteger(clientInfo.racket.pos.x, clientInfo.racket.pos.y); // debug - - if (clientInfo.side === en.PlayerSide.left) { - clientInfo.racket.pos.assign(clientInfo.racket.pos.x, data.playerLeft.y); - } - else if (clientInfo.side === en.PlayerSide.right) { - clientInfo.racket.pos.assign(clientInfo.racket.pos.x, data.playerRight.y); - } - - // interpolation - clientInfo.opponent.pos.assign(clientInfo.opponentNextPos.x, clientInfo.opponentNextPos.y); - if (clientInfo.side === en.PlayerSide.left) { - clientInfo.opponentNextPos.assign(clientInfo.opponent.pos.x, data.playerRight.y); - } - else if (clientInfo.side === en.PlayerSide.right) { - clientInfo.opponentNextPos.assign(clientInfo.opponent.pos.x, data.playerLeft.y); - } - - clientInfo.opponent.dir = new Vector( - clientInfo.opponentNextPos.x - clientInfo.opponent.pos.x, - clientInfo.opponentNextPos.y - clientInfo.opponent.pos.y - ); - - if (Math.abs(clientInfo.opponent.dir.x) + Math.abs(clientInfo.opponent.dir.y) !== 0) { - clientInfo.opponent.dir = clientInfo.opponent.dir.normalized(); - } - - // server reconciliation - repeatInput(data.lastInputId); - - // debug - if (clientInfo.racket.pos.y > predictionPos.y + 1 - || clientInfo.racket.pos.y < predictionPos.y - 1) - { - console.log( - `Reconciliation error: - server y: ${data.playerLeft.y} - reconciliation y: ${clientInfo.racket.pos.y} - prediction y: ${predictionPos.y}` - ); - } -} - -function scoreUpdate(data: ev.EventScoreUpdate) -{ - // console.log("scoreUpdate"); - if (clientInfo.side === en.PlayerSide.left && data.scoreRight > gc.scoreRight.value) { - soundRoblox.play(); - } - else if (clientInfo.side === en.PlayerSide.right && data.scoreLeft > gc.scoreLeft.value) { - soundRoblox.play(); - } - gc.scoreLeft.value = data.scoreLeft; - gc.scoreRight.value = data.scoreRight; -} - -function matchEnd(data: ev.EventMatchEnd) -{ - if (data.winner === clientInfo.side) { - gc.text1.pos.assign(c.w*0.415, c.h_mid); - gc.text1.text = "WIN"; - } - else { - gc.text1.pos.assign(c.w*0.383, c.h_mid); - gc.text1.text = "LOSE"; - } - // matchEnded = true; -} - -// export let matchEnded = false; diff --git a/JEU/src/server/class/Client.ts b/JEU/src/server/class/Client.ts deleted file mode 100644 index fbdd8fd3..00000000 --- a/JEU/src/server/class/Client.ts +++ /dev/null @@ -1,36 +0,0 @@ - -import { WebSocket } from "../wsServer.js"; -import { Racket } from "../../shared_js/class/Rectangle.js"; -import { GameSession } from "./GameSession.js"; -import * as ev from "../../shared_js/class/Event.js" -import * as en from "../../shared_js/enums.js" - -class Client { - socket: WebSocket; - id: string; // Pas indispensable si "socket" a une copie de "id" - isAlive: boolean = true; - gameSession: GameSession = null; - matchOptions: en.MatchOptions = 0; - constructor(socket: WebSocket, id: string) { - this.socket = socket; - this.id = id; - } -} - -class ClientPlayer extends Client { - inputBuffer: ev.EventInput = new ev.EventInput(); - lastInputId: number = 0; - racket: Racket; - constructor(socket: WebSocket, id: string, racket: Racket) { - super(socket, id); - this.racket = racket; - } -} - -class ClientSpectator extends Client { // Wip, unused - constructor(socket: WebSocket, id: string) { - super(socket, id); - } -} - -export {Client, ClientPlayer, ClientSpectator} diff --git a/JEU/src/server/class/GameComponentsServer.ts b/JEU/src/server/class/GameComponentsServer.ts deleted file mode 100644 index d8f2c044..00000000 --- a/JEU/src/server/class/GameComponentsServer.ts +++ /dev/null @@ -1,15 +0,0 @@ - -import * as c from "../constants.js" -import * as en from "../../shared_js/enums.js" -import { GameComponents } from "../../shared_js/class/GameComponents.js"; - -class GameComponentsServer extends GameComponents { - scoreLeft: number = 0; - scoreRight: number = 0; - constructor(options: en.MatchOptions) - { - super(options); - } -} - -export {GameComponentsServer} diff --git a/JEU/src/server/class/GameSession.ts b/JEU/src/server/class/GameSession.ts deleted file mode 100644 index 93cc544a..00000000 --- a/JEU/src/server/class/GameSession.ts +++ /dev/null @@ -1,188 +0,0 @@ - -import * as en from "../../shared_js/enums.js" -import * as ev from "../../shared_js/class/Event.js" -import * as c from "../constants.js" -import { ClientPlayer } from "./Client"; -import { GameComponentsServer } from "./GameComponentsServer.js"; -import { clientInputListener } from "../wsServer.js"; -import { random } from "../utils.js"; -import { Ball } from "../../shared_js/class/Rectangle.js"; -import { wallsMovements } from "../../shared_js/wallsMovement.js"; - -/* - Arg "s: GameSession" replace "this: GameSession" for use with setTimeout(), - because "this" is equal to "this: Timeout" -*/ -class GameSession { - id: string; // url ? - playersMap: Map = new Map(); - unreadyPlayersMap: Map = new Map(); - gameLoopInterval: NodeJS.Timer | number = 0; - clientsUpdateInterval: NodeJS.Timer | number = 0; - components: GameComponentsServer; - matchOptions: en.MatchOptions; - matchEnded: boolean = false; - - actual_time: number; - last_time: number; - delta_time: number; - - constructor(id: string, matchOptions: en.MatchOptions) { - this.id = id; - this.matchOptions = matchOptions; - this.components = new GameComponentsServer(this.matchOptions); - } - start() { - const gc = this.components; - setTimeout(this.resume, c.matchStartDelay, this); - - let timeout = c.matchStartDelay + c.newRoundDelay; - gc.ballsArr.forEach((ball) => { - setTimeout(this._newRound, timeout, this, ball); - timeout += c.newRoundDelay*0.5; - }); - } - resume(s: GameSession) { - s.playersMap.forEach( (client) => { - client.socket.on("message", clientInputListener); - }); - - s.actual_time = Date.now(); - s.gameLoopInterval = setInterval(s._gameLoop, c.serverGameLoopIntervalMS, s); - s.clientsUpdateInterval = setInterval(s._clientsUpdate, c.clientsUpdateIntervalMS, s); - } - pause(s: GameSession) { - s.playersMap.forEach( (client) => { - client.socket.off("message", clientInputListener); - }); - - clearInterval(s.gameLoopInterval); - clearInterval(s.clientsUpdateInterval); - } - instantInputDebug(client: ClientPlayer) { - this._handleInput(c.fixedDeltaTime, client); - } - private _handleInput(delta: number, client: ClientPlayer) { - // if (client.inputBuffer === null) {return;} - const gc = this.components; - const input = client.inputBuffer.input; - - if (input === en.InputEnum.up) { - client.racket.dir.y = -1; - } - else if (input === en.InputEnum.down) { - client.racket.dir.y = 1; - } - - if (input !== en.InputEnum.noInput) { - client.racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]); - } - - client.lastInputId = client.inputBuffer.id; - // client.inputBuffer = null; - } - private _gameLoop(s: GameSession) { - /* s.last_time = s.actual_time; - s.actual_time = Date.now(); - s.delta_time = (s.actual_time - s.last_time) / 1000; */ - s.delta_time = c.fixedDeltaTime; - - // WIP, replaced by instantInputDebug() to prevent desynchro - /* s.playersMap.forEach( (client) => { - s._handleInput(s.delta_time, client); - }); */ - - const gc = s.components; - gc.ballsArr.forEach((ball) => { - s._ballMovement(s.delta_time, ball); - }); - - if (s.matchOptions & en.MatchOptions.movingWalls) { - wallsMovements(s.delta_time, gc); - } - } - private _ballMovement(delta: number, ball: Ball) { - const gc = this.components; - if (ball.ballInPlay) - { - ball.moveAndBounce(delta, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); - if (ball.pos.x > c.w - || ball.pos.x < 0 - ball.width) - { - ball.ballInPlay = false; - if (this.matchEnded) { - return; - } - - if (ball.pos.x > c.w) { ++gc.scoreLeft; } - else if (ball.pos.x < 0 - ball.width) { ++gc.scoreRight; } - - this.playersMap.forEach( (client) => { - client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); - }); - setTimeout(this._newRound, c.newRoundDelay, this, ball); - } - } - } - private _clientsUpdate(s: GameSession) { - const gc = s.components; - const update = new ev.EventGameUpdate(); - update.playerLeft.y = gc.playerLeft.pos.y; - update.playerRight.y = gc.playerRight.pos.y; - gc.ballsArr.forEach((ball) => { - update.ballsArr.push({ - x: ball.pos.x, - y: ball.pos.y, - dirX: ball.dir.x, - dirY: ball.dir.y, - speed: ball.speed - }); - }); - if (s.matchOptions & en.MatchOptions.movingWalls) { - update.wallTop.y = gc.wallTop.pos.y; - update.wallBottom.y = gc.wallBottom.pos.y; - } - - s.playersMap.forEach( (client) => { - update.lastInputId = client.lastInputId; - client.socket.send(JSON.stringify(update)); - }); - } - private _newRound(s: GameSession, ball: Ball) { - const gc = s.components; - // https://fr.wikipedia.org/wiki/Tennis_de_table#Nombre_de_manches - if (gc.scoreLeft >= 11 || gc.scoreRight >= 11) - // if (gc.scoreLeft >= 2 || gc.scoreRight >= 2) // WIP: for testing - { - if (Math.abs(gc.scoreLeft - gc.scoreRight) >= 2) - { - s._matchEnd(s); - return; - } - } - ball.pos.x = c.w_mid; - ball.pos.y = random(c.h*0.3, c.h*0.7); - ball.speed = ball.baseSpeed; - ball.ballInPlay = true; - } - private _matchEnd(s: GameSession) { - s.matchEnded = true; - const gc = s.components; - - let eventEnd: ev.EventMatchEnd; - if (gc.scoreLeft > gc.scoreRight) { - eventEnd = new ev.EventMatchEnd(en.PlayerSide.left); - console.log("Player Left WIN"); - } - else { - eventEnd = new ev.EventMatchEnd(en.PlayerSide.right); - console.log("Player Right WIN"); - } - - s.playersMap.forEach( (client) => { - client.socket.send(JSON.stringify(eventEnd)); - }); - } -} - -export {GameSession} diff --git a/JEU/src/server/constants.ts b/JEU/src/server/constants.ts deleted file mode 100644 index bd5f8e9e..00000000 --- a/JEU/src/server/constants.ts +++ /dev/null @@ -1,9 +0,0 @@ - -export * from "../shared_js/constants.js" - -// 15ms == 1000/66.666 -export const serverGameLoopIntervalMS = 15; // millisecond -export const fixedDeltaTime = serverGameLoopIntervalMS/1000; // second - -// 33.333ms == 1000/30 -export const clientsUpdateIntervalMS = 1000/30; // millisecond diff --git a/JEU/src/server/server.ts b/JEU/src/server/server.ts deleted file mode 100644 index 20801d7f..00000000 --- a/JEU/src/server/server.ts +++ /dev/null @@ -1,41 +0,0 @@ - -import http from "http"; -import url from "url"; -import fs from "fs"; -import path from "path"; - -import {wsServer} from "./wsServer.js"; wsServer; // no-op, just for loading - -const hostname = "localhost"; -const port = 8080; -const root = "../../www/"; - -const server = http.createServer((req, res) => { - // let q = new URL(req.url, `http://${req.getHeaders().host}`) - let q = url.parse(req.url, true); - let filename = root + q.pathname; - fs.readFile(filename, (err, data) => { - if (err) { - res.writeHead(404, {"Content-Type": "text/html"}); - return res.end("404 Not Found"); - } - if (path.extname(filename) === ".html") { - res.writeHead(200, {"Content-Type": "text/html"}); - } - else if (path.extname(filename) === ".js") { - res.writeHead(200, {"Content-Type": "application/javascript"}); - } - else if (path.extname(filename) === ".mp3") { - res.writeHead(200, {"Content-Type": "audio/mpeg"}); - } - else if (path.extname(filename) === ".ogg") { - res.writeHead(200, {"Content-Type": "audio/ogg"}); - } - res.write(data); - return res.end(); - }); -}); - -server.listen(port, hostname, () => { - console.log(`Pong running at http://${hostname}:${port}/pong.html`); -}); diff --git a/JEU/src/server/utils.ts b/JEU/src/server/utils.ts deleted file mode 100644 index 0c939b8c..00000000 --- a/JEU/src/server/utils.ts +++ /dev/null @@ -1,8 +0,0 @@ - -export * from "../shared_js/utils.js" - -function shortId(id: string): string { - return id.substring(0, id.indexOf("-")); -} - -export {shortId} diff --git a/JEU/src/server/wsServer.ts b/JEU/src/server/wsServer.ts deleted file mode 100644 index a82df62d..00000000 --- a/JEU/src/server/wsServer.ts +++ /dev/null @@ -1,238 +0,0 @@ - -import { WebSocketServer, WebSocket as BaseLibWebSocket } from "ws"; - -export class WebSocket extends BaseLibWebSocket { - id?: string; -} - -import { IncomingMessage } from "http"; -import { v4 as uuidv4 } from 'uuid'; - -import * as en from "../shared_js/enums.js" -import * as ev from "../shared_js/class/Event.js" -import { Client, ClientPlayer } from "./class/Client.js" -import { GameSession } from "./class/GameSession.js" -import { shortId } from "./utils.js"; - -// pas indispensable d'avoir un autre port si le WebSocket est relié à un serveur http préexistant ? -const wsPort = 8042; -export const wsServer = new WebSocketServer({port: wsPort, path: "/pong"}); - -const clientsMap: Map = new Map; // socket.id/Client -const matchmakingPlayersMap: Map = new Map; // socket.id/ClientPlayer (duplicates with clientsMap) -const gameSessionsMap: Map = new Map; // GameSession.id(url)/GameSession - -wsServer.on("connection", connectionListener); -wsServer.on("error", errorListener); -wsServer.on("close", closeListener); - - -function connectionListener(socket: WebSocket, request: IncomingMessage) -{ - const id = uuidv4(); - const client = new Client(socket, id); - clientsMap.set(id, client); - socket.id = id; - - socket.on("pong", function heartbeat() { - client.isAlive = true; - // console.log(`client ${shortId(client.id)} is alive`); - }); - - socket.on("message", function log(data: string) { - try { - const event: ev.ClientEvent = JSON.parse(data); - if (event.type === en.EventTypes.clientInput) { - return; - } - } - catch (e) {} - console.log("data: " + data); - }); - - socket.once("message", clientAnnounceListener); -} - - -function clientAnnounceListener(this: WebSocket, data: string) -{ - try { - const msg : ev.ClientAnnounce = JSON.parse(data); - if (msg.type === en.EventTypes.clientAnnounce) - { - // TODO: reconnection with msg.clientId ? - // TODO: spectator/player distinction with msg.role ? - // msg.role is probably not a good idea. - // something like a different route could be better - // "/pong" to play, "/ID_OF_A_GAMESESSION" to spectate - - const player = clientsMap.get(this.id) as ClientPlayer; - player.matchOptions = msg.matchOptions; - this.send(JSON.stringify( new ev.EventAssignId(this.id) )); - this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) )); - matchmaking(player); - } - else { - console.log("Invalid ClientAnnounce"); - } - return; - } - catch (e) { - console.log("Invalid JSON (clientAnnounceListener)"); - } - this.once("message", clientAnnounceListener); -} - - -function matchmaking(player: ClientPlayer) -{ - const minPlayersNumber = 2; - const maxPlayersNumber = 2; - const matchOptions = player.matchOptions; - matchmakingPlayersMap.set(player.id, player); - - const compatiblePlayers: ClientPlayer[] = []; - for (const [id, client] of matchmakingPlayersMap) - { - if (client.matchOptions === matchOptions) - { - compatiblePlayers.push(client); - if (compatiblePlayers.length === maxPlayersNumber) { - break; - } - } - } - - if (compatiblePlayers.length < minPlayersNumber) { - return; - } - - const id = uuidv4(); - const gameSession = new GameSession(id, matchOptions); - gameSessionsMap.set(id, gameSession); - - compatiblePlayers.forEach((client) => { - matchmakingPlayersMap.delete(client.id); - client.gameSession = gameSession; - gameSession.playersMap.set(client.id, client); - gameSession.unreadyPlayersMap.set(client.id, client); - }); - - // WIP: Not pretty, hardcoded two players. - // Could be done in gameSession maybe ? - compatiblePlayers[0].racket = gameSession.components.playerRight; - compatiblePlayers[1].racket = gameSession.components.playerLeft; - - compatiblePlayers.forEach((client) => { - client.socket.once("message", playerReadyConfirmationListener); - }); - - compatiblePlayers[0].socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.right) )); - compatiblePlayers[1].socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.left) )); -} - - -function playerReadyConfirmationListener(this: WebSocket, data: string) -{ - try { - const msg : ev.ClientEvent = JSON.parse(data); - if (msg.type === en.EventTypes.clientPlayerReady) - { - const client = clientsMap.get(this.id); - const gameSession = client.gameSession; - gameSession.unreadyPlayersMap.delete(this.id); - if (gameSession.unreadyPlayersMap.size === 0) { - gameSession.playersMap.forEach( (client) => { - client.socket.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) )); - }); - gameSession.start(); - } - } - else { - console.log("Invalid playerReadyConfirmation"); - } - return; - } - catch (e) { - console.log("Invalid JSON (playerReadyConfirmationListener)"); - } - this.once("message", playerReadyConfirmationListener); -} - - -export function clientInputListener(this: WebSocket, data: string) -{ - try { - // const input: ev.ClientEvent = JSON.parse(data); - const input: ev.EventInput = JSON.parse(data); - if (input.type === en.EventTypes.clientInput) - { - const client = clientsMap.get(this.id) as ClientPlayer; - client.inputBuffer = input; - client.gameSession.instantInputDebug(client); // wip - } - else { - console.log("Invalid clientInput"); - } - } - catch (e) { - console.log("Invalid JSON (clientInputListener)"); - } -} - -//////////// -//////////// - -const pingInterval = setInterval( () => { - let deleteLog = ""; - clientsMap.forEach( (client, key, map) => { - if (!client.isAlive) { - clientTerminate(client, key, map); - deleteLog += ` ${shortId(key)} |`; - } - else { - client.isAlive = false; - client.socket.ping(); - } - }); - - if (deleteLog) { - console.log(`Disconnected:${deleteLog}`); - } - console.log("gameSessionMap size: " + gameSessionsMap.size); - console.log("clientsMap size: " + clientsMap.size); - console.log("matchmakingPlayersMap size: " + matchmakingPlayersMap.size); - console.log(""); -}, 4200); - - -function clientTerminate(client: Client, key: string, map: Map) -{ - client.socket.terminate(); - if (client.gameSession) - { - client.gameSession.playersMap.delete(key); - if (client.gameSession.playersMap.size === 0) - { - clearInterval(client.gameSession.clientsUpdateInterval); - clearInterval(client.gameSession.gameLoopInterval); - gameSessionsMap.delete(client.gameSession.id); - } - } - map.delete(key); - if (matchmakingPlayersMap.has(key)) { - matchmakingPlayersMap.delete(key); - } -} - - -function closeListener() -{ - clearInterval(pingInterval); -} - - -function errorListener(error: Error) -{ - console.log("Error: " + JSON.stringify(error)); -} diff --git a/JEU/src/shared_js/class/Event.ts b/JEU/src/shared_js/class/Event.ts deleted file mode 100644 index 3f0d440a..00000000 --- a/JEU/src/shared_js/class/Event.ts +++ /dev/null @@ -1,107 +0,0 @@ - -import * as en from "../enums.js" - -/* From Server */ -class ServerEvent { - type: en.EventTypes; - constructor(type: en.EventTypes = 0) { - this.type = type; - } -} - -class EventAssignId extends ServerEvent { - id: string; - constructor(id: string) { - super(en.EventTypes.assignId); - this.id = id; - } -} - -class EventMatchmakingComplete extends ServerEvent { - side: en.PlayerSide; - constructor(side: en.PlayerSide) { - super(en.EventTypes.matchmakingComplete); - this.side = side; - } -} - -class EventGameUpdate extends ServerEvent { - playerLeft = { - y: 0 - }; - playerRight = { - y: 0 - }; - ballsArr: { - x: number, - y: number, - dirX: number, - dirY: number, - speed: number - }[] = []; - wallTop? = { - y: 0 - }; - wallBottom? = { - y: 0 - }; - lastInputId = 0; - constructor() { // TODO: constructor that take GameComponentsServer maybe ? - super(en.EventTypes.gameUpdate); - } -} - -class EventScoreUpdate extends ServerEvent { - scoreLeft: number; - scoreRight: number; - constructor(scoreLeft: number, scoreRight: number) { - super(en.EventTypes.scoreUpdate); - this.scoreLeft = scoreLeft; - this.scoreRight = scoreRight; - } -} - -class EventMatchEnd extends ServerEvent { - winner: en.PlayerSide; - constructor(winner: en.PlayerSide) { - super(en.EventTypes.matchEnd); - this.winner = winner; - } -} - - -/* From Client */ -class ClientEvent { - type: en.EventTypes; // readonly ? - constructor(type: en.EventTypes = 0) { - this.type = type; - } -} - -class ClientAnnounce extends ClientEvent { - role: en.ClientRole; - clientId: string; - matchOptions: en.MatchOptions; - constructor(role: en.ClientRole, matchOptions: en.MatchOptions, clientId: string = "") { - super(en.EventTypes.clientAnnounce); - this.role = role; - this.clientId = clientId; - this.matchOptions = matchOptions; - } -} - -class EventInput extends ClientEvent { - input: en.InputEnum; - id: number; - constructor(input: en.InputEnum = en.InputEnum.noInput, id: number = 0) { - super(en.EventTypes.clientInput); - this.input = input; - this.id = id; - } -} - -export { - ServerEvent, EventAssignId, EventMatchmakingComplete, - EventGameUpdate, EventScoreUpdate, EventMatchEnd, - ClientEvent, ClientAnnounce, EventInput -} diff --git a/JEU/src/shared_js/class/GameComponents.ts b/JEU/src/shared_js/class/GameComponents.ts deleted file mode 100644 index 10e60932..00000000 --- a/JEU/src/shared_js/class/GameComponents.ts +++ /dev/null @@ -1,65 +0,0 @@ - -import * as c from "../constants.js" -import * as en from "../../shared_js/enums.js" -import { VectorInteger } from "./Vector.js"; -import { Rectangle, MovingRectangle, Racket, Ball } from "./Rectangle.js"; -import { random } from "../utils.js"; - -class GameComponents { - wallTop: Rectangle | MovingRectangle; - wallBottom: Rectangle | MovingRectangle; - playerLeft: Racket; - playerRight: Racket; - ballsArr: Ball[] = []; - constructor(options: en.MatchOptions) - { - const pos = new VectorInteger; - - // Rackets - pos.assign(0+c.pw, c.h_mid-c.ph/2); - this.playerLeft = new Racket(pos, c.pw, c.ph, c.racketSpeed); - pos.assign(c.w-c.pw-c.pw, c.h_mid-c.ph/2); - this.playerRight = new Racket(pos, c.pw, c.ph, c.racketSpeed); - - // Balls - let ballsCount = 1; - if (options & en.MatchOptions.multiBalls) { - ballsCount = c.multiBallsCount; - } - pos.assign(-c.ballSize, -c.ballSize); // ball out =) - while (this.ballsArr.length < ballsCount) { - this.ballsArr.push(new Ball(pos, c.ballSize, c.ballSpeed, c.ballSpeedIncrease)) - } - this.ballsArr.forEach((ball) => { - ball.dir.x = 1; - if (random() > 0.5) { - ball.dir.x *= -1; - } - - ball.dir.y = random(0, 0.2); - if (random() > 0.5) { - ball.dir.y *= -1; - } - - ball.dir = ball.dir.normalized(); - }); - - // Walls - if (options & en.MatchOptions.movingWalls) { - pos.assign(0, 0); - this.wallTop = new MovingRectangle(pos, c.w, c.wallSize, c.movingWallSpeed); - (this.wallTop).dir.y = -1; - pos.assign(0, c.h-c.wallSize); - this.wallBottom = new MovingRectangle(pos, c.w, c.wallSize, c.movingWallSpeed); - (this.wallBottom).dir.y = 1; - } - else { - pos.assign(0, 0); - this.wallTop = new Rectangle(pos, c.w, c.wallSize); - pos.assign(0, c.h-c.wallSize); - this.wallBottom = new Rectangle(pos, c.w, c.wallSize); - } - } -} - -export {GameComponents} diff --git a/JEU/src/shared_js/class/Rectangle.ts b/JEU/src/shared_js/class/Rectangle.ts deleted file mode 100644 index fff71dc9..00000000 --- a/JEU/src/shared_js/class/Rectangle.ts +++ /dev/null @@ -1,144 +0,0 @@ - -import { Vector, VectorInteger } from "./Vector.js"; -import { Component, Moving } from "./interface.js"; -import * as c from "../constants.js" - -class Rectangle implements Component { - pos: VectorInteger; - width: number; - height: number; - constructor(pos: VectorInteger, width: number, height: number) { - this.pos = new VectorInteger(pos.x, pos.y); - this.width = width; - this.height = height; - } - collision(collider: Rectangle): boolean { - const thisLeft = this.pos.x; - const thisRight = this.pos.x + this.width; - const thisTop = this.pos.y; - const thisBottom = this.pos.y + this.height; - const colliderLeft = collider.pos.x; - const colliderRight = collider.pos.x + collider.width; - const colliderTop = collider.pos.y; - const colliderBottom = collider.pos.y + collider.height; - if ((thisBottom < colliderTop) - || (thisTop > colliderBottom) - || (thisRight < colliderLeft) - || (thisLeft > colliderRight)) { - return false; - } - else { - return true; - } - } -} - -class MovingRectangle extends Rectangle implements Moving { - dir: Vector = new Vector(0,0); - speed: number; - readonly baseSpeed: number; - constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number) { - super(pos, width, height); - this.baseSpeed = baseSpeed; - this.speed = baseSpeed; - } - move(delta: number) { // Math.floor WIP until VectorInteger debug - // console.log(`delta: ${delta}, speed: ${this.speed}, speed*delta: ${this.speed * delta}`); - // this.pos.x += Math.floor(this.dir.x * this.speed * delta); - // this.pos.y += Math.floor(this.dir.y * this.speed * delta); - this.pos.x += this.dir.x * this.speed * delta; - this.pos.y += this.dir.y * this.speed * delta; - } - moveAndCollide(delta: number, colliderArr: Rectangle[]) { - this._moveAndCollideAlgo(delta, colliderArr); - } - protected _moveAndCollideAlgo(delta: number, colliderArr: Rectangle[]) { - let oldPos = new VectorInteger(this.pos.x, this.pos.y); - this.move(delta); - if (colliderArr.some(this.collision, this)) { - this.pos = oldPos; - } - } -} - -class Racket extends MovingRectangle { - constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number) { - super(pos, width, height, baseSpeed); - } - moveAndCollide(delta: number, colliderArr: Rectangle[]) { - // let oldPos = new VectorInteger(this.pos.x, this.pos.y); // debug - this._moveAndCollideAlgo(delta, colliderArr); - // console.log(`y change: ${this.pos.y - oldPos.y}`); - } -} - -class Ball extends MovingRectangle { - readonly speedIncrease: number; - ballInPlay: boolean = false; - constructor(pos: VectorInteger, size: number, baseSpeed: number, speedIncrease: number) { - super(pos, size, size, baseSpeed); - this.speedIncrease = speedIncrease; - } - bounce(collider?: Rectangle) { - this._bounceAlgo(collider); - } - protected _bounceAlgo(collider?: Rectangle) { - /* Could be more generic, but testing only Racket is enough, - because in Pong collider can only be Racket or Wall. */ - if (collider instanceof Racket) { - this._bounceRacket(collider); - } - else { - this._bounceWall(); - } - } - moveAndBounce(delta: number, colliderArr: Rectangle[]) { - this.move(delta); - let i = colliderArr.findIndex(this.collision, this); - if (i != -1) - { - this.bounce(colliderArr[i]); - this.move(delta); - } - } - protected _bounceWall() { // Should be enough for Wall - this.dir.y = this.dir.y * -1; - } - protected _bounceRacket(racket: Racket) { - this._bounceRacketAlgo(racket); - } - protected _bounceRacketAlgo(racket: Racket) { - this.speed += this.speedIncrease; - - let x = this.dir.x * -1; - - const angleFactorDegree = 60; - const angleFactor = angleFactorDegree / 90; - const racketHalf = racket.height/2; - const ballMid = this.pos.y + this.height/2; - const racketMid = racket.pos.y + racketHalf; - - let impact = ballMid - racketMid; - const horizontalMargin = racketHalf * 0.15; - if (impact < horizontalMargin && impact > -horizontalMargin) { - impact = 0; - } - else if (impact > 0) { - impact = impact - horizontalMargin; - } - else if (impact < 0) { - impact = impact + horizontalMargin; - } - - let y = impact / (racketHalf - horizontalMargin) * angleFactor; - - this.dir.assign(x, y); - // Normalize Vector (for consistency in speed independent of direction) - if (c.normalizedSpeed) { - this.dir = this.dir.normalized(); - } - // console.log(`x: ${this.dir.x}, y: ${this.dir.y}`); - } -} - -export {Rectangle, MovingRectangle, Racket, Ball} diff --git a/JEU/src/shared_js/class/Vector.ts b/JEU/src/shared_js/class/Vector.ts deleted file mode 100644 index 025bca36..00000000 --- a/JEU/src/shared_js/class/Vector.ts +++ /dev/null @@ -1,49 +0,0 @@ - -class Vector { - x: number; - y: number; - constructor(x: number = 0, y: number = 0) { - this.x = x; - this.y = y; - } - assign(x: number, y: number) { - this.x = x; - this.y = y; - } - normalized() : Vector { - const normalizationFactor = Math.abs(this.x) + Math.abs(this.y); - return new Vector(this.x/normalizationFactor, this.y/normalizationFactor); - } -} - -class VectorInteger extends Vector { - // PLACEHOLDER - // VectorInteger with set/get dont work (No draw on the screen). Why ? -} - -/* -class VectorInteger { - // private _x: number = 0; - // private _y: number = 0; - // constructor(x: number = 0, y: number = 0) { - // this._x = x; - // this._y = y; - // } - // get x(): number { - // return this._x; - // } - // set x(v: number) { - // // this._x = Math.floor(v); - // this._x = v; - // } - // get y(): number { - // return this._y; - // } - // set y(v: number) { - // // this._y = Math.floor(v); - // this._y = v; - // } -} -*/ - -export {Vector, VectorInteger} diff --git a/JEU/src/shared_js/class/interface.ts b/JEU/src/shared_js/class/interface.ts deleted file mode 100644 index 39753de1..00000000 --- a/JEU/src/shared_js/class/interface.ts +++ /dev/null @@ -1,21 +0,0 @@ - -import { Vector, VectorInteger } from "./Vector.js"; - -interface Component { - pos: VectorInteger; -} - -interface GraphicComponent extends Component { - ctx: CanvasRenderingContext2D; - color: string; - update: () => void; - clear: (pos?: VectorInteger) => void; -} - -interface Moving { - dir: Vector; - speed: number; // pixel per second - move(delta: number): void; -} - -export {Component, GraphicComponent, Moving} diff --git a/JEU/src/shared_js/constants.ts b/JEU/src/shared_js/constants.ts deleted file mode 100644 index ae3320e5..00000000 --- a/JEU/src/shared_js/constants.ts +++ /dev/null @@ -1,26 +0,0 @@ - -export const CanvasWidth = 1500; -export const CanvasRatio = 1.66666; -/* ratio 5/3 (1.66) */ - -export const w = CanvasWidth; -export const h = CanvasWidth / CanvasRatio; -export const w_mid = Math.floor(w/2); -export const h_mid = Math.floor(h/2); -export const pw = Math.floor(w*0.017); -export const ph = pw*6; -export const ballSize = pw; -export const wallSize = Math.floor(w*0.01); -export const racketSpeed = Math.floor(w*0.66); // pixel per second -export const ballSpeed = Math.floor(w*0.66); // pixel per second -export const ballSpeedIncrease = Math.floor(ballSpeed*0.05); // pixel per second - -export const normalizedSpeed = false; // for consistency in speed independent of direction - -export const matchStartDelay = 3000; // millisecond -export const newRoundDelay = 1500; // millisecond - -// Game Variantes -export const multiBallsCount = 3; -export const movingWallPosMax = Math.floor(w*0.12); -export const movingWallSpeed = Math.floor(w*0.08); diff --git a/JEU/src/shared_js/enums.ts b/JEU/src/shared_js/enums.ts deleted file mode 100644 index dfba2aa3..00000000 --- a/JEU/src/shared_js/enums.ts +++ /dev/null @@ -1,47 +0,0 @@ - -enum EventTypes { - // Class Implemented - gameUpdate = 1, - scoreUpdate, - matchEnd, - assignId, - matchmakingComplete, - - // Generic - matchmakingInProgress, - matchStart, - matchNewRound, // unused - matchPause, // unused - matchResume, // unused - - // Client - clientAnnounce, - clientPlayerReady, - clientInput, - -} - -enum InputEnum { - noInput = 0, - up = 1, - down, -} - -enum PlayerSide { - left = 1, - right -} - -enum ClientRole { - player = 1, - spectator -} - -enum MatchOptions { - // binary flags, can be mixed - noOption = 0b0, - multiBalls = 1 << 0, - movingWalls = 1 << 1 -} - -export {EventTypes, InputEnum, PlayerSide, ClientRole, MatchOptions} diff --git a/JEU/src/shared_js/utils.ts b/JEU/src/shared_js/utils.ts deleted file mode 100644 index e8f7bca3..00000000 --- a/JEU/src/shared_js/utils.ts +++ /dev/null @@ -1,27 +0,0 @@ - -import { MovingRectangle } from "./class/Rectangle.js"; - -function random(min: number = 0, max: number = 1) { - return Math.random() * (max - min) + min; -} - -function sleep (ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -function clamp(n: number, min: number, max: number) : number -{ - if (n < min) - n = min; - else if (n > max) - n = max; - return (n); -} - -// Typescript hack, unused -function assertMovingRectangle(value: unknown): asserts value is MovingRectangle { - // if (value !== MovingRectangle) throw new Error("Not a MovingRectangle"); - return; -} - -export {random, sleep, clamp, assertMovingRectangle} diff --git a/JEU/src/shared_js/wallsMovement.ts b/JEU/src/shared_js/wallsMovement.ts deleted file mode 100644 index dbf3f558..00000000 --- a/JEU/src/shared_js/wallsMovement.ts +++ /dev/null @@ -1,20 +0,0 @@ - -import * as c from "./constants.js"; -import { MovingRectangle } from "../shared_js/class/Rectangle.js"; -import { GameComponents } from "./class/GameComponents.js"; - -function wallsMovements(delta: number, gc: GameComponents) -{ - const wallTop = gc.wallTop; - const wallBottom = gc.wallBottom; - if (wallTop.pos.y <= 0 || wallTop.pos.y >= c.movingWallPosMax) { - wallTop.dir.y *= -1; - } - if (wallBottom.pos.y >= c.h-c.wallSize || wallBottom.pos.y <= c.h-c.movingWallPosMax) { - wallBottom.dir.y *= -1; - } - wallTop.moveAndCollide(delta, [gc.playerLeft, gc.playerRight]); - wallBottom.moveAndCollide(delta, [gc.playerLeft, gc.playerRight]); -} - -export {wallsMovements} diff --git a/JEU/tsconfig.json b/JEU/tsconfig.json deleted file mode 100644 index 988126ba..00000000 --- a/JEU/tsconfig.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "include": ["src"], -// "exclude": ["node_modules"], - "compilerOptions": { - // "outDir": "./build", - // "types": ["node"], /* Specify type package names to be included without being referenced in a source file. */ - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.gc. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.gc. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - // "module": "commonjs", /* Specify what module code is generated. */ - "module": "ES6", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - "strictNullChecks": false, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } -} diff --git a/JEU/www/Bit5x3.woff b/JEU/www/Bit5x3.woff deleted file mode 100644 index 72c8b293..00000000 Binary files a/JEU/www/Bit5x3.woff and /dev/null differ diff --git a/JEU/www/Bit5x3.woff2 b/JEU/www/Bit5x3.woff2 deleted file mode 100644 index 27d538bf..00000000 Binary files a/JEU/www/Bit5x3.woff2 and /dev/null differ diff --git a/JEU/www/favicon.ico b/JEU/www/favicon.ico deleted file mode 100644 index b7e7e5ca..00000000 Binary files a/JEU/www/favicon.ico and /dev/null differ diff --git a/JEU/www/sound/pong/0.ogg b/JEU/www/sound/pong/0.ogg deleted file mode 100644 index 93d05409..00000000 Binary files a/JEU/www/sound/pong/0.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/1.ogg b/JEU/www/sound/pong/1.ogg deleted file mode 100644 index 3a268b34..00000000 Binary files a/JEU/www/sound/pong/1.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/10.ogg b/JEU/www/sound/pong/10.ogg deleted file mode 100644 index 855ad78b..00000000 Binary files a/JEU/www/sound/pong/10.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/11.ogg b/JEU/www/sound/pong/11.ogg deleted file mode 100644 index 655917b5..00000000 Binary files a/JEU/www/sound/pong/11.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/12.ogg b/JEU/www/sound/pong/12.ogg deleted file mode 100644 index 11336a76..00000000 Binary files a/JEU/www/sound/pong/12.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/13.ogg b/JEU/www/sound/pong/13.ogg deleted file mode 100644 index 71cfead6..00000000 Binary files a/JEU/www/sound/pong/13.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/14.ogg b/JEU/www/sound/pong/14.ogg deleted file mode 100644 index 066fff69..00000000 Binary files a/JEU/www/sound/pong/14.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/15.ogg b/JEU/www/sound/pong/15.ogg deleted file mode 100644 index 011f139c..00000000 Binary files a/JEU/www/sound/pong/15.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/16.ogg b/JEU/www/sound/pong/16.ogg deleted file mode 100644 index 7e852275..00000000 Binary files a/JEU/www/sound/pong/16.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/17.ogg b/JEU/www/sound/pong/17.ogg deleted file mode 100644 index 9860139d..00000000 Binary files a/JEU/www/sound/pong/17.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/18.ogg b/JEU/www/sound/pong/18.ogg deleted file mode 100644 index 6ad25391..00000000 Binary files a/JEU/www/sound/pong/18.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/19.ogg b/JEU/www/sound/pong/19.ogg deleted file mode 100644 index f6fc42d6..00000000 Binary files a/JEU/www/sound/pong/19.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/2.ogg b/JEU/www/sound/pong/2.ogg deleted file mode 100644 index 0f09bb30..00000000 Binary files a/JEU/www/sound/pong/2.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/20.ogg b/JEU/www/sound/pong/20.ogg deleted file mode 100644 index 11ac780e..00000000 Binary files a/JEU/www/sound/pong/20.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/21.ogg b/JEU/www/sound/pong/21.ogg deleted file mode 100644 index 7c724dd4..00000000 Binary files a/JEU/www/sound/pong/21.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/22.ogg b/JEU/www/sound/pong/22.ogg deleted file mode 100644 index b2ca9758..00000000 Binary files a/JEU/www/sound/pong/22.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/23.ogg b/JEU/www/sound/pong/23.ogg deleted file mode 100644 index f57724b9..00000000 Binary files a/JEU/www/sound/pong/23.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/24.ogg b/JEU/www/sound/pong/24.ogg deleted file mode 100644 index 90093efc..00000000 Binary files a/JEU/www/sound/pong/24.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/25.ogg b/JEU/www/sound/pong/25.ogg deleted file mode 100644 index 27dfe8eb..00000000 Binary files a/JEU/www/sound/pong/25.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/26.ogg b/JEU/www/sound/pong/26.ogg deleted file mode 100644 index 80cb60fa..00000000 Binary files a/JEU/www/sound/pong/26.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/27.ogg b/JEU/www/sound/pong/27.ogg deleted file mode 100644 index 13332de6..00000000 Binary files a/JEU/www/sound/pong/27.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/28.ogg b/JEU/www/sound/pong/28.ogg deleted file mode 100644 index 29615795..00000000 Binary files a/JEU/www/sound/pong/28.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/29.ogg b/JEU/www/sound/pong/29.ogg deleted file mode 100644 index 41f95343..00000000 Binary files a/JEU/www/sound/pong/29.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/3.ogg b/JEU/www/sound/pong/3.ogg deleted file mode 100644 index 12448222..00000000 Binary files a/JEU/www/sound/pong/3.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/30.ogg b/JEU/www/sound/pong/30.ogg deleted file mode 100644 index bd4e4ffd..00000000 Binary files a/JEU/www/sound/pong/30.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/31.ogg b/JEU/www/sound/pong/31.ogg deleted file mode 100644 index 4447b52a..00000000 Binary files a/JEU/www/sound/pong/31.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/32.ogg b/JEU/www/sound/pong/32.ogg deleted file mode 100644 index a58240a1..00000000 Binary files a/JEU/www/sound/pong/32.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/4.ogg b/JEU/www/sound/pong/4.ogg deleted file mode 100644 index 688b1f81..00000000 Binary files a/JEU/www/sound/pong/4.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/5.ogg b/JEU/www/sound/pong/5.ogg deleted file mode 100644 index d2163268..00000000 Binary files a/JEU/www/sound/pong/5.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/6.ogg b/JEU/www/sound/pong/6.ogg deleted file mode 100644 index 34bdd117..00000000 Binary files a/JEU/www/sound/pong/6.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/7.ogg b/JEU/www/sound/pong/7.ogg deleted file mode 100644 index 9c9c994f..00000000 Binary files a/JEU/www/sound/pong/7.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/8.ogg b/JEU/www/sound/pong/8.ogg deleted file mode 100644 index 0f9acf99..00000000 Binary files a/JEU/www/sound/pong/8.ogg and /dev/null differ diff --git a/JEU/www/sound/pong/9.ogg b/JEU/www/sound/pong/9.ogg deleted file mode 100644 index 15d82091..00000000 Binary files a/JEU/www/sound/pong/9.ogg and /dev/null differ diff --git a/JEU/www/sound/roblox-oof.ogg b/JEU/www/sound/roblox-oof.ogg deleted file mode 100644 index 689946ed..00000000 Binary files a/JEU/www/sound/roblox-oof.ogg and /dev/null differ diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index da5fa458..00000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "group_transcendence", - "lockfileVersion": 2, - "requires": true, - "packages": {} -}