From f3f98108172f6538f114cbafc0c6b49c98804e11 Mon Sep 17 00:00:00 2001 From: jiyun Date: Thu, 28 Dec 2023 14:52:34 +0900 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20disconnect=20=EC=A0=9C=EB=8C=80?= =?UTF-8?q?=EB=A1=9C=20=EC=95=88=ED=95=B4=EC=A3=BC=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/game/game.gateway.ts | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/game/game.gateway.ts b/src/game/game.gateway.ts index 4f988b3..f45859e 100644 --- a/src/game/game.gateway.ts +++ b/src/game/game.gateway.ts @@ -73,7 +73,17 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { async handleConnection(@ConnectedSocket() client: Socket) { const user = await this.authService.getUserFromSocket(client); if (!user || !client.id) return client.disconnect(); - else if (user.gameSocketId) client.disconnect(); + else if (user.gameSocketId) { + console.log('game socket 갈아끼운다 ~?!'); + const socket = this.userIdToClient.get(user.id); + if (socket) socket?.disconnect(); + else { + await this.usersRepository.update(user.id, { + gameSocketId: null, + status: UserStatus.ONLINE, + }); + } + } console.log(`${user.id} is connected to game socket {${client.id}}`); @@ -112,11 +122,28 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { await this.gameEnd(gameDto); } else { this.gameIdToGameDto.delete(gameId); - this.userIdToGameId.delete(user.id); + // 상대도 disconnect 하고 socket 매핑도 지워주기 + if (user.id === gameDto.playerLeftId) { + const socket = this.userIdToClient.get( + gameDto.playerRightId, + ); + socket?.disconnect(); + this.userIdToGameId.delete(gameDto.playerRightId); + this.userIdToClient.delete(gameDto.playerRightId); + } else { + const socket = this.userIdToClient.get( + gameDto.playerLeftId, + ); + socket?.disconnect(); + this.userIdToGameId.delete(gameDto.playerLeftId); + this.userIdToClient.delete(gameDto.playerLeftId); + } } } + this.userIdToGameId.delete(user.id); } this.userIdToClient.delete(user.id); + this.sendError(client, 200, `${client.id} 가 정상적으로 나간다 !`); } @SubscribeMessage('gameRequest') @@ -140,11 +167,13 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { where: { id: data.gameId }, }); if (!game) { - console.log(`해당 game이 없어서 disconnect 된다`); + console.log(`해당 game ${data.gameId} 이 없어서 disconnect 된다`); return client.disconnect(); } if (game.gameStatus !== GameStatus.WAITING) { - console.log(`해당 game이 WAITING 상태가 아니어서 disconnect 된다`); + console.log( + `해당 game ${data.gameId} 이 WAITING 상태가 아니어서 disconnect 된다`, + ); return client.disconnect(); } @@ -415,6 +444,9 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { this.userIdToGameId.delete(gameDto.playerRightId); // gameDto 지워주기 this.gameIdToGameDto.delete(gameDto.getGameId()); + + playerSockets.left?.disconnect(); + playerSockets.right?.disconnect(); } private async updateLadderData(winner: User, loser: User) { From 9b40c5c9c3df609d7c9c6ba6658ab769f49600eb Mon Sep 17 00:00:00 2001 From: jiyun Date: Thu, 28 Dec 2023 16:19:42 +0900 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20=EB=94=94=EC=8A=A4=EC=BB=A4=EB=84=A5?= =?UTF-8?q?=ED=8A=B8=EB=8A=94=20=EC=84=9C=EB=B2=84=EA=B0=80=20=EB=8B=A4=20?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/emit-event-match-end-param.dto.ts | 2 ++ src/game/dto/game.dto.ts | 19 ++++++++++++------- src/game/game.gateway.ts | 6 ++++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/game/dto/emit-event-match-end-param.dto.ts b/src/game/dto/emit-event-match-end-param.dto.ts index 4d742e4..0f9930d 100644 --- a/src/game/dto/emit-event-match-end-param.dto.ts +++ b/src/game/dto/emit-event-match-end-param.dto.ts @@ -2,6 +2,8 @@ import { GameType } from '../../common/enum'; export class EmitEventMatchEndParamDto { gameType: GameType; + rivalName: string; + rivalAvatar: string; rivalScore: number | null; myScore: number | null; isWin: boolean | null; diff --git a/src/game/dto/game.dto.ts b/src/game/dto/game.dto.ts index a810e6a..aa53092 100644 --- a/src/game/dto/game.dto.ts +++ b/src/game/dto/game.dto.ts @@ -60,19 +60,24 @@ export class GameDto { async setResult() { if (this.gameType === GameType.NONE) { + this.scoreLeft = this.scoreRight = 0; this.winnerId = this.playerLeftId; - this.winnerScore = 0; + this.winnerScore = this.loserScore = 0; this.loserId = this.playerRightId; this.loserScore = 0; return; } if (this.loserId) { - this.loserScore = 0; - this.winnerScore = this.maxScore; - this.winnerId = - this.loserId === this.playerLeftId - ? this.playerRightId - : this.playerLeftId; + const isLoserLeft = this.loserId === this.playerLeftId; + if (isLoserLeft) { + this.scoreLeft = this.loserScore = 0; + this.scoreRight = this.winnerScore = this.maxScore; + this.winnerId = this.playerRightId; + } else { + this.scoreRight = this.loserScore = 0; + this.scoreLeft = this.winnerScore = this.maxScore; + this.winnerId = this.playerLeftId; + } } else { if (this.scoreLeft === this.maxScore) { this.winnerScore = this.scoreLeft; diff --git a/src/game/game.gateway.ts b/src/game/game.gateway.ts index f45859e..f0d4442 100644 --- a/src/game/game.gateway.ts +++ b/src/game/game.gateway.ts @@ -716,6 +716,8 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { ) { const leftMatchEndParamDtos: EmitEventMatchEndParamDto = { gameType: gameDto.gameType, + rivalName: right.nickname, + rivalAvatar: right.avatar, rivalScore: gameDto.scoreRight, myScore: gameDto.scoreLeft, isWin: gameDto.scoreLeft > gameDto.scoreRight, @@ -726,6 +728,8 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { }; const rightMatchEndParamDtos: EmitEventMatchEndParamDto = { gameType: gameDto.gameType, + rivalName: left.nickname, + rivalAvatar: left.avatar, rivalScore: gameDto.scoreLeft, myScore: gameDto.scoreRight, isWin: gameDto.scoreRight > gameDto.scoreLeft, @@ -739,6 +743,7 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { console.log( `${playerSockets.left.id}에 matchEnd 이벤트 보낸다 !!!`, ); + console.log(`내용은: ${JSON.stringify(leftMatchEndParamDtos)}`); this.server .to(playerSockets.left.id) .emit(EVENT_MATCH_END, leftMatchEndParamDtos); @@ -747,6 +752,7 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { console.log( `${playerSockets.right.id}에 matchEnd 이벤트 보낸다 !!!`, ); + console.log(`내용은: ${JSON.stringify(rightMatchEndParamDtos)}`); this.server .to(playerSockets.right.id) .emit(EVENT_MATCH_END, rightMatchEndParamDtos); From dfe05d40dc6798c1ec73b76674c2221b36fae9b3 Mon Sep 17 00:00:00 2001 From: jiyun Date: Thu, 28 Dec 2023 21:58:35 +0900 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20disconnect=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20=EC=AA=BC=EA=B0=9C=EC=84=9C=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/game/dto/game.dto.ts | 46 +++--- src/game/dto/view-map.dto.ts | 40 +++-- src/game/game.gateway.ts | 295 +++++++++++++++++++++++++---------- 3 files changed, 266 insertions(+), 115 deletions(-) diff --git a/src/game/dto/game.dto.ts b/src/game/dto/game.dto.ts index aa53092..a63d1fb 100644 --- a/src/game/dto/game.dto.ts +++ b/src/game/dto/game.dto.ts @@ -16,7 +16,7 @@ export class GameDto { gameStatus: GameStatus; viewMap: ViewMapDto; readyCnt: number; - gameInterrupted: boolean; + interrupted: boolean; constructor(game: Game, readonly maxScore = 7) { this.setGameId(game.id); @@ -32,7 +32,7 @@ export class GameDto { this.gameStatus = game.gameStatus; this.viewMap = new ViewMapDto(game.ballSpeed, game.racketSize); this.readyCnt = 0; - this.gameInterrupted = false; + this.interrupted = false; } getGameId() { @@ -58,15 +58,22 @@ export class GameDto { await this.viewMap.initObjects(); } - async setResult() { - if (this.gameType === GameType.NONE) { - this.scoreLeft = this.scoreRight = 0; + async setGameOver() { + if (this.scoreLeft === this.maxScore) { + this.winnerScore = this.scoreLeft; this.winnerId = this.playerLeftId; - this.winnerScore = this.loserScore = 0; + this.loserScore = this.scoreRight; this.loserId = this.playerRightId; - this.loserScore = 0; - return; + } else if (this.scoreRight === this.maxScore) { + this.winnerScore = this.scoreRight; + this.winnerId = this.playerRightId; + this.loserScore = this.scoreLeft; + this.loserId = this.playerLeftId; } + } + + async setGameInterrupted() { + // 게임 중에 비정상 종료돼서 몰수패 처리 if (this.loserId) { const isLoserLeft = this.loserId === this.playerLeftId; if (isLoserLeft) { @@ -78,21 +85,20 @@ export class GameDto { this.scoreLeft = this.winnerScore = this.maxScore; this.winnerId = this.playerLeftId; } - } else { - if (this.scoreLeft === this.maxScore) { - this.winnerScore = this.scoreLeft; - this.winnerId = this.playerLeftId; - this.loserScore = this.scoreRight; - this.loserId = this.playerRightId; - } else if (this.scoreRight === this.maxScore) { - this.winnerScore = this.scoreRight; - this.winnerId = this.playerRightId; - this.loserScore = this.scoreLeft; - this.loserId = this.playerLeftId; - } } } + async setNone() { + // 게임 시작 전 비정상 종료돼서 게임 자체를 무효 처리 + this.scoreLeft = this.scoreRight = 0; + this.winnerId = this.playerLeftId; + this.winnerScore = this.loserScore = 0; + this.loserId = this.playerRightId; + this.loserScore = 0; + this.gameType = GameType.NONE; + this.gameStatus = GameStatus.FINISHED; + } + private setGameId(gameId: number) { this.gameId = gameId; } diff --git a/src/game/dto/view-map.dto.ts b/src/game/dto/view-map.dto.ts index 7c61928..c4f64d2 100644 --- a/src/game/dto/view-map.dto.ts +++ b/src/game/dto/view-map.dto.ts @@ -126,21 +126,17 @@ export class ViewMapDto { this.racketRight.y = this.canvasHeight / 2 - this.racketHeight / 2; } - private async updateBall() { + private async calculateNextBallLocation() { const ball = this.ball; const dt = this.deltaTime; - // 공의 위치 업데이트 - const x = ball.x + ball.xVelocity * dt + ball.accel * dt * dt * 0.5; - const y = ball.y + ball.yVelocity * dt + ball.accel * dt * dt * 0.5; - // 공의 속력 업데이트 - // ball.xVelocity += ball.accel * dt * (ball.xVelocity > 0 ? 1 : -1); - // ball.yVelocity += ball.accel * dt * (ball.yVelocity > 0 ? 1 : -1); - - this.ball.vx = x - ball.x; - this.ball.vy = y - ball.y; - this.ball.x = x; - this.ball.y = y; + // 공의 위치 변화량 계산 + this.ball.vx = + ball.xVelocity * dt + + (ball.xVelocity < 0 ? ball.accel * -1 : ball.accel) * dt * dt * 0.5; + this.ball.vy = + ball.yVelocity * dt + + (ball.yVelocity < 0 ? ball.accel * -1 : ball.accel) * dt * dt * 0.5; } updateRacketLeft(action: KEYNAME) { @@ -174,10 +170,22 @@ export class ViewMapDto { async changes() { const updateDto = this.updateDto; const ball = this.ball; - await this.updateBall(); - - // racket, 천장, 바닥에 부딪히는지 - await this.detectCollision(); + await this.calculateNextBallLocation(); + + const xChange = this.ballRadius; + const piece = ball.vx / xChange; + const xRemain = ball.vx % xChange; + const yChange = xChange * (ball.vy / ball.vx); + const yRemain = ball.vy % yChange; + + for (let i = 0; i < piece; i++) { + ball.x += xChange * (ball.xVelocity > 0 ? 1 : -1); + ball.y += yChange * (ball.yVelocity > 0 ? 1 : -1); + this.detectCollision(); + } + ball.x += xRemain * (ball.xVelocity > 0 ? 1 : -1); + ball.y += yRemain * (ball.yVelocity > 0 ? 1 : -1); + this.detectCollision(); //score if (ball.x + this.ballRadius >= this.canvasWidth) diff --git a/src/game/game.gateway.ts b/src/game/game.gateway.ts index f0d4442..305d68a 100644 --- a/src/game/game.gateway.ts +++ b/src/game/game.gateway.ts @@ -76,7 +76,7 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { else if (user.gameSocketId) { console.log('game socket 갈아끼운다 ~?!'); const socket = this.userIdToClient.get(user.id); - if (socket) socket?.disconnect(); + if (socket) socket.disconnect(); else { await this.usersRepository.update(user.id, { gameSocketId: null, @@ -85,7 +85,9 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { } } - console.log(`${user.id} is connected to game socket {${client.id}}`); + console.log( + `${user.id}, ${user.nickname} is connected to game socket {${client.id}}`, + ); // 연결된 게임소켓 id를 저장한다. await this.usersRepository.update(user.id, { @@ -95,10 +97,13 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { } async handleDisconnect(@ConnectedSocket() client: Socket) { + // 끊기고 실행되는 로직. . const user = await this.authService.getUserFromSocket(client); if (!user || client.id !== user.gameSocketId) return; - console.log(`${user.id} is disconnected to game socket {${client.id}}`); + console.log( + `${user.id}, ${user.nickname} is disconnected to game socket {${client.id}}`, + ); await this.usersRepository.update(user.id, { gameSocketId: null, @@ -109,38 +114,78 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { if (gameId) { const gameDto = this.gameIdToGameDto.get(gameId); if (gameDto) { - if (gameDto.gameStatus === GameStatus.WAITING) { - gameDto.gameType = GameType.NONE; - await this.gameEnd(gameDto); - await this.gameRepository.softDelete(gameDto.getGameId()); - } else if (gameDto.gameStatus === GameStatus.PLAYING) { - if (!gameDto.gameInterrupted) { - gameDto.gameInterrupted = true; - gameDto.loserId = user.id; - this.userIdToGameId.delete(user.id); + if ( + gameDto.gameStatus === GameStatus.PLAYING && + !gameDto.interrupted + ) { + gameDto.interrupted = true; + gameDto.loserId = user.id; + } else if (gameDto.gameStatus === GameStatus.WAITING) { + await gameDto.setNone(); + const playerSockets = await this.getPlayerSockets(gameDto); + /* game update */ + const updateGameResultParamDto: UpdateGameResultParamDto = { + winnerId: gameDto.winnerId as number, + loserId: gameDto.loserId as number, + winnerScore: gameDto.winnerScore, + loserScore: gameDto.loserScore, + gameType: gameDto.gameType, + gameStatus: GameStatus.FINISHED, + }; + + await this.gameRepository.update( + gameDto.getGameId(), + updateGameResultParamDto, + ); + + const left = await this.usersRepository.findOne({ + where: { id: gameDto.playerLeftId }, + }); + const right = await this.usersRepository.findOne({ + where: { id: gameDto.playerRightId }, + }); + if (!left || !right) { + return this.sendErrorAll( + playerSockets, + 400, + `player 의 데이터를 찾지 못했습니다`, + ); } - await this.gameEnd(gameDto); - } else { - this.gameIdToGameDto.delete(gameId); - // 상대도 disconnect 하고 socket 매핑도 지워주기 - if (user.id === gameDto.playerLeftId) { - const socket = this.userIdToClient.get( - gameDto.playerRightId, + /* emit */ + this.sendMatchEnd(playerSockets, gameDto, left, right); + /* game 지우기 */ + await this.gameRepository.softDelete(gameDto.getGameId()); + /* disconnect */ + // gameDto 유저들 지워주기 + this.userIdToGameId.delete(gameDto.playerLeftId); + console.log( + `${gameDto.playerLeftId} 를 userId-gameId 맵에서 지웁니다 ?!!`, + ); + this.userIdToGameId.delete(gameDto.playerRightId); + console.log( + `${gameDto.playerRightId} 를 userId-gameId 맵에서 지웁니다 ?!!`, + ); + /* gameDto 지워주기 */ + this.gameIdToGameDto.delete(gameDto.getGameId()); + console.log( + `${gameDto.getGameId()} 를 gameId-gameDto 맵에서 지웁니다 ?!!`, + ); + + if (playerSockets.left) { + console.log( + `${playerSockets.left} 를 gameId-gameDto 맵에서 지웁니다 ?!!`, ); - socket?.disconnect(); - this.userIdToGameId.delete(gameDto.playerRightId); - this.userIdToClient.delete(gameDto.playerRightId); - } else { - const socket = this.userIdToClient.get( - gameDto.playerLeftId, + playerSockets.left.disconnect(); + } else console.log(`playerSockets.left가 없음`); + playerSockets.right?.disconnect(); + if (playerSockets.right) { + console.log( + `${playerSockets.right} 를 gameId-gameDto 맵에서 지웁니다 ?!!`, ); - socket?.disconnect(); - this.userIdToGameId.delete(gameDto.playerLeftId); - this.userIdToClient.delete(gameDto.playerLeftId); - } + playerSockets.right.disconnect(); + } else console.log(`playerSockets.right가 없음`); } } - this.userIdToGameId.delete(user.id); } this.userIdToClient.delete(user.id); this.sendError(client, 200, `${client.id} 가 정상적으로 나간다 !`); @@ -266,19 +311,18 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { if (!gameDto) { return this.sendError(client, 400, `유효하지 않은 게임입니다`); } + const playerSockets = await this.getPlayerSockets(gameDto); + if (!playerSockets.left || !playerSockets.right) { + return this.sendError( + client, + 400, + `두 플레이어의 게임 소켓이 모두 필요합니다. 게임 불가`, + ); + } gameDto.readyCnt++; console.log(`ready count: ${gameDto.readyCnt}`); if (gameDto.bothReady()) { - // 유효성 검사 - const playerSockets = this.getPlayerSockets(gameDto); - if (!playerSockets.left || !playerSockets.right) { - return this.sendError( - client, - 400, - `두 플레이어의 게임 소켓이 모두 필요합니다. 게임 불가`, - ); - } console.log(`It's ready!`); gameDto.gameStatus = GameStatus.PLAYING; @@ -293,7 +337,7 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { } else return; // TODO: game restart 될 때도 3초 지연 ? how - this.gameLoop(gameDto); + await this.gameLoop(gameDto); } // 테스트에만 쓰임 @@ -318,16 +362,16 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { await gameDto.testSetScore(data.scoreLeft, data.scoreRight); } - gameLoop(gameDto: GameDto) { + async gameLoop(gameDto: GameDto) { console.log('Game Loop started!'); - let playerSockets = this.getPlayerSockets(gameDto); - if (!playerSockets.left || !playerSockets.right) { - return this.sendErrorAll( - playerSockets, - 400, - `두 플레이어의 게임 소켓이 모두 필요합니다. 게임 불가`, - ); - } + let playerSockets = await this.getPlayerSockets(gameDto); + // if (!playerSockets.left || !playerSockets.right) { + // return this.sendErrorAll( + // playerSockets, + // 400, + // `두 플레이어의 게임 소켓이 모두 필요합니다. 게임 불가`, + // ); + // } let cnt = 0; const intervalId: NodeJS.Timeout = setInterval(async () => { @@ -365,8 +409,8 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { clearInterval(intervalId); await this.gameEnd(gameDto); return; - } else if (!gameDto.gameInterrupted) { - playerSockets = this.getPlayerSockets(gameDto); + } else if (!gameDto.interrupted) { + playerSockets = await this.getPlayerSockets(gameDto); if (playerSockets.left && playerSockets.right) { // await this.delay(1000 * 3); // 안먹어요 await gameDto.restart(); @@ -376,30 +420,91 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { } // check interrupted by disconnected user - if (gameDto.gameInterrupted) { + if (gameDto.interrupted) { console.log('으악 게임이 강제로 중단됐다'); clearInterval(intervalId); - playerSockets = this.getPlayerSockets(gameDto); + await this.gameInterrupted(gameDto); + } + }, 1000 / 60); + } + + async gameInterrupted(gameDto: GameDto) { + const playerSockets = await this.getPlayerSockets(gameDto); + + await gameDto.setGameInterrupted(); + + if (gameDto.interrupted) { + /* game update */ + const updateGameResultParamDto: UpdateGameResultParamDto = { + winnerId: gameDto.winnerId as number, + loserId: gameDto.loserId as number, + winnerScore: gameDto.winnerScore, + loserScore: gameDto.loserScore, + gameType: gameDto.gameType, + gameStatus: GameStatus.FINISHED, + }; + + await this.gameRepository.update( + gameDto.getGameId(), + updateGameResultParamDto, + ); + /* user update */ + const left = await this.usersRepository.findOne({ + where: { id: gameDto.playerLeftId }, + }); + const right = await this.usersRepository.findOne({ + where: { id: gameDto.playerRightId }, + }); + if (!left || !right) { return this.sendErrorAll( playerSockets, 400, - `비정상 종료된 게임입니다`, + `player 의 데이터를 찾지 못했습니다`, ); } - }, 1000 / 60); + if (gameDto.gameType === GameType.LADDER) { + const winner = gameDto.winnerId === left.id ? left : right; + const loser = gameDto.loserId === left.id ? left : right; + await this.updateLadderData(winner, loser); + } + /* emit */ + this.sendMatchEnd(playerSockets, gameDto, left, right); + /* disconnect */ + // gameDto 유저들 지워주기 + this.userIdToGameId.delete(gameDto.playerLeftId); + console.log( + `${gameDto.playerLeftId} 를 userId-gameId 맵에서 지웁니다 ?!!`, + ); + this.userIdToGameId.delete(gameDto.playerRightId); + console.log( + `${gameDto.playerRightId} 를 userId-gameId 맵에서 지웁니다 ?!!`, + ); + // gameDto 지워주기 + this.gameIdToGameDto.delete(gameDto.getGameId()); + console.log( + `${gameDto.getGameId()} 를 gameId-gameDto 맵에서 지웁니다 ?!!`, + ); + + if (playerSockets.left) { + console.log( + `${playerSockets.left} 를 gameId-gameDto 맵에서 지웁니다 ?!!`, + ); + playerSockets.left.disconnect(); + } else console.log(`playerSockets.left가 없음`); + playerSockets.right?.disconnect(); + if (playerSockets.right) { + console.log( + `${playerSockets.right} 를 gameId-gameDto 맵에서 지웁니다 ?!!`, + ); + playerSockets.right.disconnect(); + } else console.log(`playerSockets.right가 없음`); + } } async gameEnd(gameDto: GameDto) { - const game = await this.gameRepository.findOne({ - where: { id: gameDto.getGameId() }, - }); - if (!game) { - console.log('game이 이미 없는데'); - } - console.log(`game type: ${game?.gameType}`); - const playerSockets = this.getPlayerSockets(gameDto); + const playerSockets = await this.getPlayerSockets(gameDto); - await gameDto.setResult(); + await gameDto.setGameOver(); // game DB 업데이트 const updateGameResultParamDto: UpdateGameResultParamDto = { @@ -441,12 +546,31 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { // gameDto 유저들 지워주기 this.userIdToGameId.delete(gameDto.playerLeftId); + console.log( + `${gameDto.playerLeftId} 를 userId-gameId 맵에서 지웁니다 ?!!`, + ); this.userIdToGameId.delete(gameDto.playerRightId); + console.log( + `${gameDto.playerRightId} 를 userId-gameId 맵에서 지웁니다 ?!!`, + ); // gameDto 지워주기 this.gameIdToGameDto.delete(gameDto.getGameId()); + console.log( + `${gameDto.getGameId()} 를 gameId-gameDto 맵에서 지웁니다 ?!!`, + ); playerSockets.left?.disconnect(); + if (playerSockets.left) + console.log( + `${playerSockets.left} 를 gameId-gameDto 맵에서 지웁니다 ?!!`, + ); + else console.log(`playerSockets.left가 없음`); playerSockets.right?.disconnect(); + if (playerSockets.right) + console.log( + `${playerSockets.right} 를 gameId-gameDto 맵에서 지웁니다 ?!!`, + ); + else console.log(`playerSockets.right가 없음`); } private async updateLadderData(winner: User, loser: User) { @@ -496,7 +620,7 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { return 1.0 / (1.0 + Math.pow(10, (rating1 - rating2) / 400)); } - private getPlayerSockets(gameDto: GameDto) { + private async getPlayerSockets(gameDto: GameDto) { const sockets = { left: null as Socket | null, right: null as Socket | null, @@ -505,10 +629,23 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { const playerRightId = gameDto.playerRightId; const playerLeftSocket = this.userIdToClient.get(playerLeftId); + if ( + playerLeftSocket && + (await this.isSocketConnected(playerLeftSocket)) + ) { + sockets.left = playerLeftSocket; + } else { + sockets.left = null; + } const playerRightSocket = this.userIdToClient.get(playerRightId); - - sockets.left = playerLeftSocket ? playerLeftSocket : null; - sockets.right = playerRightSocket ? playerRightSocket : null; + if ( + playerRightSocket && + (await this.isSocketConnected(playerRightSocket)) + ) { + sockets.right = playerRightSocket; + } else { + sockets.right = null; + } return sockets; } @@ -532,7 +669,7 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { if (!gameDto) { return null; } else { - if (gameDto.gameInterrupted) return null; + if (gameDto.interrupted) return null; } return gameDto; @@ -740,22 +877,22 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { }; if (playerSockets.left) { - console.log( - `${playerSockets.left.id}에 matchEnd 이벤트 보낸다 !!!`, - ); - console.log(`내용은: ${JSON.stringify(leftMatchEndParamDtos)}`); this.server .to(playerSockets.left.id) .emit(EVENT_MATCH_END, leftMatchEndParamDtos); - } - if (playerSockets.right) { console.log( - `${playerSockets.right.id}에 matchEnd 이벤트 보낸다 !!!`, + `${playerSockets.left.id}에 matchEnd 이벤트 보냈다 !!!`, ); - console.log(`내용은: ${JSON.stringify(rightMatchEndParamDtos)}`); + console.log(`내용은: ${JSON.stringify(leftMatchEndParamDtos)}`); + } + if (playerSockets.right) { this.server .to(playerSockets.right.id) .emit(EVENT_MATCH_END, rightMatchEndParamDtos); + console.log( + `${playerSockets.right.id}에 matchEnd 이벤트 보냈다 !!!`, + ); + console.log(`내용은: ${JSON.stringify(rightMatchEndParamDtos)}`); } } @@ -764,7 +901,7 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { statusCode: statusCode, message: message, }); - console.log(`${client.id}가 ${message} 이유로 di로sconnect 된다`); + console.log(`${client.id}가 ${message} 이유로 disconnect 된다`); client.disconnect(); } @@ -792,7 +929,7 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { message: message, }); console.log( - `${clients.right.id}가 error message: [${message}] 로 disconnect 된다`, + `${clients.right.id}가 가 ${message} 이유로 disconnect 된다`, ); clients.right.disconnect(); } From 7b77d580b6f56eb466addeb0f53f4c25338ae1c6 Mon Sep 17 00:00:00 2001 From: jiyun Date: Thu, 28 Dec 2023 22:19:26 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20=EC=AA=BC=EA=B0=9C=EC=84=9C=20?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/game/dto/view-map.dto.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/game/dto/view-map.dto.ts b/src/game/dto/view-map.dto.ts index c4f64d2..e5de3f9 100644 --- a/src/game/dto/view-map.dto.ts +++ b/src/game/dto/view-map.dto.ts @@ -173,19 +173,21 @@ export class ViewMapDto { await this.calculateNextBallLocation(); const xChange = this.ballRadius; - const piece = ball.vx / xChange; - const xRemain = ball.vx % xChange; - const yChange = xChange * (ball.vy / ball.vx); - const yRemain = ball.vy % yChange; + const piece = Math.abs(ball.vx / xChange); + const xRemain = Math.abs(ball.vx % xChange); + const yChange = Math.abs(xChange * (ball.vy / ball.vx)); + const yRemain = Math.abs(ball.vy % yChange); - for (let i = 0; i < piece; i++) { + console.log(`piece: ${piece}`); + for (let i = 0; i < Math.floor(piece); i++) { ball.x += xChange * (ball.xVelocity > 0 ? 1 : -1); ball.y += yChange * (ball.yVelocity > 0 ? 1 : -1); - this.detectCollision(); + await this.detectCollision(); } ball.x += xRemain * (ball.xVelocity > 0 ? 1 : -1); ball.y += yRemain * (ball.yVelocity > 0 ? 1 : -1); - this.detectCollision(); + console.log(`yVelocity: ${ball.yVelocity}`); + await this.detectCollision(); //score if (ball.x + this.ballRadius >= this.canvasWidth) @@ -264,6 +266,7 @@ export class ViewMapDto { } } + console.log(`this ball.y: ${ball.y}`); // 바닥, 천장 if ( ball.y + this.ballRadius >= this.canvasHeight || From 80bfda9e8a391f29d5f617cadaf4dd128bce3d78 Mon Sep 17 00:00:00 2001 From: jiyun Date: Fri, 29 Dec 2023 05:06:04 +0900 Subject: [PATCH 5/6] =?UTF-8?q?fix:=20=EC=B6=A9=EB=8F=8C=EC=8B=9C=20?= =?UTF-8?q?=EC=95=88=EB=9A=AB=EA=B3=A0=20=EB=B0=A9=ED=96=A5=20=EC=A0=84?= =?UTF-8?q?=ED=99=98=20=EC=9E=98=20=EB=90=98=EB=8A=94=EB=93=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.service.ts | 2 +- src/game/dto/view-map.dto.ts | 59 +++++++++++++++++++++--------------- src/game/game.gateway.ts | 2 -- src/users/ranks.service.ts | 4 +-- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/app.service.ts b/src/app.service.ts index 3229830..3745106 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -8,7 +8,7 @@ export class AppService { // push data to redis using zadd async updateRanking(score: number, id: number) { - Logger.log(`Redis updateRanking: ${score}, ${id}`) + // Logger.log(`Redis updateRanking: ${score}, ${id}`); await this.redis.zadd('rankings', score, id); } } diff --git a/src/game/dto/view-map.dto.ts b/src/game/dto/view-map.dto.ts index e5de3f9..a1049e6 100644 --- a/src/game/dto/view-map.dto.ts +++ b/src/game/dto/view-map.dto.ts @@ -131,10 +131,10 @@ export class ViewMapDto { const dt = this.deltaTime; // 공의 위치 변화량 계산 - this.ball.vx = + ball.vx = ball.xVelocity * dt + (ball.xVelocity < 0 ? ball.accel * -1 : ball.accel) * dt * dt * 0.5; - this.ball.vy = + ball.vy = ball.yVelocity * dt + (ball.yVelocity < 0 ? ball.accel * -1 : ball.accel) * dt * dt * 0.5; } @@ -178,16 +178,22 @@ export class ViewMapDto { const yChange = Math.abs(xChange * (ball.vy / ball.vx)); const yRemain = Math.abs(ball.vy % yChange); - console.log(`piece: ${piece}`); for (let i = 0; i < Math.floor(piece); i++) { ball.x += xChange * (ball.xVelocity > 0 ? 1 : -1); ball.y += yChange * (ball.yVelocity > 0 ? 1 : -1); + console.log(`\nbefore piece ball.x: ${ball.x}`); + console.log(`before piece xVelocity: ${ball.xVelocity}`); await this.detectCollision(); + console.log(`after piece ball.x: ${ball.x}`); + console.log(`after piece xVelocity: ${ball.xVelocity}`); } ball.x += xRemain * (ball.xVelocity > 0 ? 1 : -1); ball.y += yRemain * (ball.yVelocity > 0 ? 1 : -1); - console.log(`yVelocity: ${ball.yVelocity}`); + console.log(`before remain ball.x: ${ball.x}`); + console.log(`before remain xVelocity: ${ball.xVelocity}`); await this.detectCollision(); + console.log(`after remain ball.x: ${ball.x}`); + console.log(`after remain xVelocity: ${ball.xVelocity}`); //score if (ball.x + this.ballRadius >= this.canvasWidth) @@ -221,22 +227,24 @@ export class ViewMapDto { dy = Math.abs(ball.y - this.getRacketRightCenter().cy); if ( dx <= this.ballRadius + this.racketWidth / 2 && - dy <= this.ballRadius + this.racketHeight / 2 + dy <= this.ballRadius + this.racketHeight / 2 && + ball.xVelocity > 0 ) { ball.xVelocity *= -1; - console.log('\nbefore speed: ', Math.abs(ball.xVelocity)); + // console.log('\nbefore speed: ', Math.abs(ball.xVelocity)); ball.xVelocity += ball.accel * 2 * this.deltaTime * (ball.xVelocity > 0 ? 1 : -1); - console.log( - 'collision right -> ', - ball.accel * - 2 * - this.deltaTime * - (ball.xVelocity > 0 ? 1 : -1), - ); + + // console.log( + // 'collision right -> ', + // ball.accel * + // 2 * + // this.deltaTime * + // (ball.xVelocity > 0 ? 1 : -1), + // ); console.log('accel, deltaTime: ', ball.accel, this.deltaTime); console.log('after speed: ', Math.abs(ball.xVelocity)); } @@ -245,32 +253,33 @@ export class ViewMapDto { dy = Math.abs(ball.y - this.getRacketLeftCenter().cy); if ( dx <= this.ballRadius + this.racketWidth / 2 && - dy <= this.ballRadius + this.racketHeight / 2 + dy <= this.ballRadius + this.racketHeight / 2 && + ball.xVelocity < 0 ) { ball.xVelocity *= -1; - console.log('\nbefore speed: ', Math.abs(ball.xVelocity)); + // console.log('\nbefore speed: ', Math.abs(ball.xVelocity)); ball.xVelocity += ball.accel * 2 * this.deltaTime * (ball.xVelocity > 0 ? 1 : -1); - console.log( - 'collision left -> ', - ball.accel * - 2 * - this.deltaTime * - (ball.xVelocity > 0 ? 1 : -1), - ); + // console.log( + // 'collision left -> ', + // ball.accel * + // 2 * + // this.deltaTime * + // (ball.xVelocity > 0 ? 1 : -1), + // ); console.log('accel, deltaTime: ', ball.accel, this.deltaTime); console.log('after speed: ', Math.abs(ball.xVelocity)); } } - console.log(`this ball.y: ${ball.y}`); // 바닥, 천장 if ( - ball.y + this.ballRadius >= this.canvasHeight || - ball.y - this.ballRadius < 0 + (ball.y + this.ballRadius >= this.canvasHeight && + ball.yVelocity > 0) || + (ball.y - this.ballRadius < 0 && ball.yVelocity < 0) ) ball.yVelocity *= -1; } diff --git a/src/game/game.gateway.ts b/src/game/game.gateway.ts index 305d68a..a7189fa 100644 --- a/src/game/game.gateway.ts +++ b/src/game/game.gateway.ts @@ -883,7 +883,6 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { console.log( `${playerSockets.left.id}에 matchEnd 이벤트 보냈다 !!!`, ); - console.log(`내용은: ${JSON.stringify(leftMatchEndParamDtos)}`); } if (playerSockets.right) { this.server @@ -892,7 +891,6 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect { console.log( `${playerSockets.right.id}에 matchEnd 이벤트 보냈다 !!!`, ); - console.log(`내용은: ${JSON.stringify(rightMatchEndParamDtos)}`); } } diff --git a/src/users/ranks.service.ts b/src/users/ranks.service.ts index 4b0a4cc..9bdd368 100644 --- a/src/users/ranks.service.ts +++ b/src/users/ranks.service.ts @@ -41,9 +41,9 @@ export class RanksService { // user중 nickname이 없는 유저는 랭킹에 올라가지 않는다. { where: { nickname: Not(IsNull()) } }, ); - console.log(users); + // console.log(users); for (const user of users) { - Logger.log(`updateRanking: ${user.ladderScore}, ${user.id}`); + // Logger.log(`updateRanking: ${user.ladderScore}, ${user.id}`); await this.AppService.updateRanking(user.ladderScore, user.id); } } From 3d7473fc088fece1484c3d3f05314561a29c2438 Mon Sep 17 00:00:00 2001 From: jiyun Date: Fri, 29 Dec 2023 05:07:20 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20=EC=A3=BC=EC=84=9D=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/game/dto/view-map.dto.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/game/dto/view-map.dto.ts b/src/game/dto/view-map.dto.ts index a1049e6..8f69221 100644 --- a/src/game/dto/view-map.dto.ts +++ b/src/game/dto/view-map.dto.ts @@ -181,19 +181,19 @@ export class ViewMapDto { for (let i = 0; i < Math.floor(piece); i++) { ball.x += xChange * (ball.xVelocity > 0 ? 1 : -1); ball.y += yChange * (ball.yVelocity > 0 ? 1 : -1); - console.log(`\nbefore piece ball.x: ${ball.x}`); - console.log(`before piece xVelocity: ${ball.xVelocity}`); + // console.log(`\nbefore piece ball.x: ${ball.x}`); + // console.log(`before piece xVelocity: ${ball.xVelocity}`); await this.detectCollision(); - console.log(`after piece ball.x: ${ball.x}`); - console.log(`after piece xVelocity: ${ball.xVelocity}`); + // console.log(`after piece ball.x: ${ball.x}`); + // console.log(`after piece xVelocity: ${ball.xVelocity}`); } ball.x += xRemain * (ball.xVelocity > 0 ? 1 : -1); ball.y += yRemain * (ball.yVelocity > 0 ? 1 : -1); - console.log(`before remain ball.x: ${ball.x}`); - console.log(`before remain xVelocity: ${ball.xVelocity}`); + // console.log(`before remain ball.x: ${ball.x}`); + // console.log(`before remain xVelocity: ${ball.xVelocity}`); await this.detectCollision(); - console.log(`after remain ball.x: ${ball.x}`); - console.log(`after remain xVelocity: ${ball.xVelocity}`); + // console.log(`after remain ball.x: ${ball.x}`); + // console.log(`after remain xVelocity: ${ball.xVelocity}`); //score if (ball.x + this.ballRadius >= this.canvasWidth)