feat(pong): detect when the client hasnt sent anything in X secs
This commit is contained in:
parent
613bb31100
commit
8eac0a0d4e
5 changed files with 61 additions and 13 deletions
|
|
@ -194,15 +194,15 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
|
||||||
showError("couldn't find your id in game");
|
showError("couldn't find your id in game");
|
||||||
}); // TODO: notif user of new game w "ready up" btn
|
}); // TODO: notif user of new game w "ready up" btn
|
||||||
|
|
||||||
socket.on("gameEnd", () => {
|
socket.on("gameEnd", (winner) => {
|
||||||
queueBtn.innerHTML = QueueState.Iddle;
|
queueBtn.innerHTML = QueueState.Iddle;
|
||||||
queueBtn.style.color = 'white';
|
queueBtn.style.color = 'white';
|
||||||
|
|
||||||
if (!isNullish(currentGame)) {
|
if (!isNullish(currentGame)) {
|
||||||
let new_div = document.createElement('div');
|
let new_div = document.createElement('div');
|
||||||
let end_txt = "";
|
let end_txt = "";
|
||||||
if ((user.id === currentGame.left.id && currentGame.left.score > currentGame.right.score) ||
|
if ((user.id === currentGame.left.id && winner === 'left') ||
|
||||||
(user.id === currentGame.right.id && currentGame.right.score > currentGame.left.score))
|
(user.id === currentGame.right.id && winner === 'right'))
|
||||||
end_txt = 'won! #yippe';
|
end_txt = 'won! #yippe';
|
||||||
else
|
else
|
||||||
end_txt = 'lost #sadge';
|
end_txt = 'lost #sadge';
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export interface ServerToClient {
|
||||||
updateInformation: (info: UpdateInfo) => void,
|
updateInformation: (info: UpdateInfo) => void,
|
||||||
newGame: (initState: GameUpdate) => void, // <- consider this the gameProc eg not start of game but wait for client to "ready up"
|
newGame: (initState: GameUpdate) => void, // <- consider this the gameProc eg not start of game but wait for client to "ready up"
|
||||||
gameUpdate: (state: GameUpdate) => void,
|
gameUpdate: (state: GameUpdate) => void,
|
||||||
gameEnd: () => void;
|
gameEnd: (winner: 'left' | 'right') => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SSocket = Socket<ClientToServer, ServerToClient>;
|
export type SSocket = Socket<ClientToServer, ServerToClient>;
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,8 @@ function makeAngle(i: number): [number, number, number, number] {
|
||||||
export class Pong {
|
export class Pong {
|
||||||
public gameUpdate: NodeJS.Timeout | null = null;
|
public gameUpdate: NodeJS.Timeout | null = null;
|
||||||
|
|
||||||
|
public static readonly CONCEDED_TIMEOUT: number = 1500;
|
||||||
|
|
||||||
public static readonly BALL_START_ANGLES: number[] = [
|
public static readonly BALL_START_ANGLES: number[] = [
|
||||||
...makeAngle(4),
|
...makeAngle(4),
|
||||||
...makeAngle(6),
|
...makeAngle(6),
|
||||||
|
|
@ -127,6 +129,11 @@ export class Pong {
|
||||||
public score: [number, number] = [0, 0];
|
public score: [number, number] = [0, 0];
|
||||||
public local: boolean = false;
|
public local: boolean = false;
|
||||||
|
|
||||||
|
public rightLastSeen: number = -1;
|
||||||
|
public leftLastSeen: number = -1;
|
||||||
|
|
||||||
|
private cachedWinner: 'left' | 'right' | null = null;
|
||||||
|
|
||||||
public static makeLocal(owner: UserId): Pong {
|
public static makeLocal(owner: UserId): Pong {
|
||||||
const game = new Pong(owner, owner);
|
const game = new Pong(owner, owner);
|
||||||
game.local = true;
|
game.local = true;
|
||||||
|
|
@ -200,7 +207,9 @@ export class Pong {
|
||||||
if (
|
if (
|
||||||
(Math.abs(this.ball.angle) > Math.PI / 2 && side !== 'left') ||
|
(Math.abs(this.ball.angle) > Math.PI / 2 && side !== 'left') ||
|
||||||
(Math.abs(this.ball.angle) < Math.PI / 2 && side !== 'right')
|
(Math.abs(this.ball.angle) < Math.PI / 2 && side !== 'right')
|
||||||
) {return false;}
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// now we check only if the ball is near enought in the y axis to permform the collision
|
// now we check only if the ball is near enought in the y axis to permform the collision
|
||||||
if (
|
if (
|
||||||
|
|
@ -212,7 +221,9 @@ export class Pong {
|
||||||
this.ball.y < paddle.y + paddle.height + this.ball.size
|
this.ball.y < paddle.y + paddle.height + this.ball.size
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
) {return false;}
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// so we know that the y is close enougth to be a bit, so we check the X. are we closer than the ball size ? if yes -> hit
|
// so we know that the y is close enougth to be a bit, so we check the X. are we closer than the ball size ? if yes -> hit
|
||||||
if (
|
if (
|
||||||
|
|
@ -222,14 +233,49 @@ export class Pong {
|
||||||
paddle.width * (side === 'left' ? 1 : 0) -
|
paddle.width * (side === 'left' ? 1 : 0) -
|
||||||
this.ball.x,
|
this.ball.x,
|
||||||
) < this.ball.size
|
) < this.ball.size
|
||||||
) {return true;}
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public updateLastSeen(user: UserId) {
|
||||||
|
if (this.local && this.userLeft === user) {
|
||||||
|
this.leftLastSeen = Date.now();
|
||||||
|
this.rightLastSeen = Date.now();
|
||||||
|
}
|
||||||
|
else if (this.userLeft === user) {
|
||||||
|
this.leftLastSeen = Date.now();
|
||||||
|
}
|
||||||
|
else if (this.userRight === user) {
|
||||||
|
this.rightLastSeen = Date.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public checkWinner(): 'left' | 'right' | null {
|
public checkWinner(): 'left' | 'right' | null {
|
||||||
if (this.score[0] >= 5) return 'left';
|
const checkInner = () => {
|
||||||
if (this.score[1] >= 5) return 'right';
|
if (this.score[0] >= 5) return 'left';
|
||||||
return null;
|
if (this.score[1] >= 5) return 'right';
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.leftLastSeen !== -1 &&
|
||||||
|
Date.now() - this.leftLastSeen > Pong.CONCEDED_TIMEOUT
|
||||||
|
) {
|
||||||
|
return 'right';
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
this.rightLastSeen !== -1 &&
|
||||||
|
Date.now() - this.rightLastSeen > Pong.CONCEDED_TIMEOUT
|
||||||
|
) {
|
||||||
|
return 'left';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
if (this.cachedWinner === null) {
|
||||||
|
this.cachedWinner = checkInner();
|
||||||
|
}
|
||||||
|
return this.cachedWinner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public movePaddle(user: UserId | ('left' | 'right'), dir: 'up' | 'down') {
|
public movePaddle(user: UserId | ('left' | 'right'), dir: 'up' | 'down') {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ export interface ServerToClient {
|
||||||
updateInformation: (info: UpdateInfo) => void,
|
updateInformation: (info: UpdateInfo) => void,
|
||||||
newGame: (initState: GameUpdate) => void,
|
newGame: (initState: GameUpdate) => void,
|
||||||
gameUpdate: (state: GameUpdate) => void,
|
gameUpdate: (state: GameUpdate) => void,
|
||||||
gameEnd: () => void;
|
gameEnd: (winner: 'left' | 'right') => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SSocket = Socket<ClientToServer, ServerToClient>;
|
export type SSocket = Socket<ClientToServer, ServerToClient>;
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,7 @@ class StateI {
|
||||||
if (u.moveRight !== null) { game.movePaddle('right', u.moveRight); }
|
if (u.moveRight !== null) { game.movePaddle('right', u.moveRight); }
|
||||||
}
|
}
|
||||||
else if (u.move !== null) { game.movePaddle(user.id, u.move); }
|
else if (u.move !== null) { game.movePaddle(user.id, u.move); }
|
||||||
|
game.updateLastSeen(user.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -174,14 +175,15 @@ class StateI {
|
||||||
private cleanupGame(gameId: GameId, game: Pong): void {
|
private cleanupGame(gameId: GameId, game: Pong): void {
|
||||||
clearInterval(game.gameUpdate ?? undefined);
|
clearInterval(game.gameUpdate ?? undefined);
|
||||||
this.games.delete(gameId);
|
this.games.delete(gameId);
|
||||||
|
const winner = game.checkWinner() ?? 'left';
|
||||||
let player: PUser | undefined = undefined;
|
let player: PUser | undefined = undefined;
|
||||||
if ((player = this.users.get(game.userLeft)) !== undefined) {
|
if ((player = this.users.get(game.userLeft)) !== undefined) {
|
||||||
player.currentGame = null;
|
player.currentGame = null;
|
||||||
player.socket.emit('gameEnd');
|
player.socket.emit('gameEnd', winner);
|
||||||
}
|
}
|
||||||
if ((player = this.users.get(game.userRight)) !== undefined) {
|
if ((player = this.users.get(game.userRight)) !== undefined) {
|
||||||
player.currentGame = null;
|
player.currentGame = null;
|
||||||
player.socket.emit('gameEnd');
|
player.socket.emit('gameEnd', winner);
|
||||||
}
|
}
|
||||||
const rOutcome = game.checkWinner();
|
const rOutcome = game.checkWinner();
|
||||||
let outcome: PongGameOutcome = 'other';
|
let outcome: PongGameOutcome = 'other';
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue