diff --git a/memo.txt b/memo.txt
index 20d493f3..56b3d9f1 100644
--- a/memo.txt
+++ b/memo.txt
@@ -1,45 +1,48 @@
-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é.
+ - lors d'un newRound() verifier si tout les joueurs sont encore en ligne et stopper le match sinon
+ (victoire si encore un joueur en ligne, annulation du match si aucun joueur en ligne)
+ - 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.
+
+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
+ - Match Abort si tout les joueurs n'ont pas répondus assez vite (5 secondes)
+
-----------
-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 ?
+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.
+ - 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).
+ - 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)
+ - reconnection
+ - amélioration du protocole, remplacement du JSON (compression. moins de bande passante).
+ - 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é.
diff --git a/src/client/pong.css b/src/client/pong.css
index c481c502..14533592 100644
--- a/src/client/pong.css
+++ b/src/client/pong.css
@@ -7,13 +7,6 @@
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;
@@ -24,7 +17,14 @@ body {
/* max-height: 80vh; */
/* overflow: hidden; */
}
+#div_game_instructions {
+ text-align: center;
+ font-family: "Bit5x3";
+ color: rgb(245, 245, 245);
+ font-size: large;
+}
#div_game_options {
+ margin-top: 20px;
text-align: center;
font-family: "Bit5x3";
color: rgb(245, 245, 245);
diff --git a/src/client/pong.html b/src/client/pong.html
index d23e5590..30f2e781 100644
--- a/src/client/pong.html
+++ b/src/client/pong.html
@@ -6,30 +6,35 @@
- .
-
+
+
+
--- keys ---
+
move up: 'w' or 'up arrow'
+
move down: 's' OR 'down arrow'
+
grid on/off: 'g'
diff --git a/src/client/pong.ts b/src/client/pong.ts
index 5c9dcce0..29eb657f 100644
--- a/src/client/pong.ts
+++ b/src/client/pong.ts
@@ -17,11 +17,6 @@ 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;
@@ -46,7 +41,8 @@ function init()
matchOptions |= en.MatchOptions.movingWalls;
}
- document.getElementById("div_game_options").hidden = true;
+ document.getElementById("div_game_options").remove();
+ document.getElementById("div_game_instructions").remove();
pong = new GameArea();
gc = new GameComponentsClient(matchOptions, pong.ctx);
@@ -55,32 +51,52 @@ function init()
function matchmaking()
{
- console.log("Searching an opponent...");
+ const text = "searching...";
+ console.log(text);
gc.text1.clear();
- gc.text1.pos.assign(c.w/5, c.h_mid);
- gc.text1.text = "Searching...";
+ gc.text1.pos.assign(c.w*0.2, c.h*0.5);
+ gc.text1.text = text;
gc.text1.update();
}
function matchmakingComplete()
{
- console.log("Match Found !");
+ const text = "match found !";
+ console.log(text);
gc.text1.clear();
- gc.text1.pos.assign(c.w/8, c.h_mid);
- gc.text1.text = "Match Found !";
+ gc.text1.pos.assign(c.w*0.15, c.h*0.5);
+ gc.text1.text = text;
gc.text1.update();
}
-function startGame() {
- gc.text1.pos.assign(c.w_mid, c.h_mid+c.h/4);
+function matchAbort()
+{
+ const text = "match abort";
+ console.log(text);
+ gc.text1.clear();
+ gc.text1.pos.assign(c.w*0.15, c.h*0.5);
+ gc.text1.text = text;
+ gc.text1.update();
+
+ gc.text1.pos.assign(c.w*0.44, c.h*0.6);
+ gc.text1.text = "sorry =(";
+ const oriSize = gc.text1.size;
+ gc.text1.size = gc.text1.size*0.2;
+ gc.text1.update();
+ gc.text1.size = oriSize;
+}
+
+function matchStart()
+{
+ gc.text1.pos.assign(c.w*0.5, c.h*0.75);
countdown(c.matchStartDelay/1000, (count: number) => {
gc.text1.clear();
gc.text1.text = `${count}`;
gc.text1.update();
- }, resumeGame);
+ }, matchResume);
}
-function resumeGame()
+function matchResume()
{
gc.text1.text = "";
window.addEventListener('keydown', function (e) {
@@ -96,4 +112,4 @@ function resumeGame()
}
-export {matchmaking, matchmakingComplete, startGame}
+export {matchmaking, matchmakingComplete, matchAbort, matchStart}
diff --git a/src/client/ws.ts b/src/client/ws.ts
index 60f1ab87..a8396b1c 100644
--- a/src/client/ws.ts
+++ b/src/client/ws.ts
@@ -3,7 +3,7 @@ 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 { matchmaking, matchmakingComplete, matchAbort, matchStart } from "./pong.js";
import { RacketClient } from "./class/RectangleClient.js";
import { repeatInput } from "./handleInput.js";
import { soundRoblox } from "./audio.js"
@@ -67,7 +67,11 @@ function preMatchListener(this: WebSocket, event: MessageEvent)
case en.EventTypes.matchStart:
socket.removeEventListener("message", preMatchListener);
socket.addEventListener("message", inGameListener);
- startGame();
+ matchStart();
+ break;
+ case en.EventTypes.matchAbort:
+ socket.removeEventListener("message", preMatchListener);
+ matchAbort();
break;
}
}
diff --git a/src/server/wsServer.ts b/src/server/wsServer.ts
index a82df62d..73604b67 100644
--- a/src/server/wsServer.ts
+++ b/src/server/wsServer.ts
@@ -129,6 +129,18 @@ function matchmaking(player: ClientPlayer)
compatiblePlayers[0].socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.right) ));
compatiblePlayers[1].socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.left) ));
+
+ setTimeout(function abortMatch() {
+ if (gameSession.unreadyPlayersMap.size !== 0)
+ {
+ gameSessionsMap.delete(gameSession.id);
+ gameSession.playersMap.forEach((client) => {
+ client.socket.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchAbort) ));
+ client.gameSession = null;
+ clientTerminate(client);
+ });
+ }
+ }, 5000);
}
@@ -185,10 +197,10 @@ export function clientInputListener(this: WebSocket, data: string)
const pingInterval = setInterval( () => {
let deleteLog = "";
- clientsMap.forEach( (client, key, map) => {
+ clientsMap.forEach( (client) => {
if (!client.isAlive) {
- clientTerminate(client, key, map);
- deleteLog += ` ${shortId(key)} |`;
+ clientTerminate(client);
+ deleteLog += ` ${shortId(client.id)} |`;
}
else {
client.isAlive = false;
@@ -206,12 +218,12 @@ const pingInterval = setInterval( () => {
}, 4200);
-function clientTerminate(client: Client, key: string, map: Map)
+function clientTerminate(client: Client)
{
client.socket.terminate();
if (client.gameSession)
{
- client.gameSession.playersMap.delete(key);
+ client.gameSession.playersMap.delete(client.id);
if (client.gameSession.playersMap.size === 0)
{
clearInterval(client.gameSession.clientsUpdateInterval);
@@ -219,9 +231,9 @@ function clientTerminate(client: Client, key: string, map: Map)
gameSessionsMap.delete(client.gameSession.id);
}
}
- map.delete(key);
- if (matchmakingPlayersMap.has(key)) {
- matchmakingPlayersMap.delete(key);
+ clientsMap.delete(client.id);
+ if (matchmakingPlayersMap.has(client.id)) {
+ matchmakingPlayersMap.delete(client.id);
}
}
diff --git a/src/shared_js/enums.ts b/src/shared_js/enums.ts
index dfba2aa3..33368ff8 100644
--- a/src/shared_js/enums.ts
+++ b/src/shared_js/enums.ts
@@ -10,6 +10,7 @@ enum EventTypes {
// Generic
matchmakingInProgress,
matchStart,
+ matchAbort,
matchNewRound, // unused
matchPause, // unused
matchResume, // unused