Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: maxscore 7로 수정, server game ready 이벤트 #92

Merged
merged 3 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/channels/channels.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { InjectRedis } from '@liaoliaots/nestjs-redis';
import {
BadRequestException,
ImATeapotException,
Injectable,
Logger,
} from '@nestjs/common';
Expand Down
8 changes: 7 additions & 1 deletion src/common/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ export const EVENT_GAME_INVITATION = 'gameInvitation';

export const EVENT_GAME_INVITATION_REPLY = 'gameInvitationReply';

export const EVENT_GAME_READY = 'gameReady';
export const EVENT_SERVER_GAME_READY = 'serverGameReady';

export const EVENT_GAME_START = 'gameStart';

export const EVENT_MATCH_SCORE = 'matchScore';

export const EVENT_MATCH_STATUS = 'matchStatus';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GameStatus, GameType } from '../../common/enum';

export class CreateGameParamDto {
export class CreateInitialGameParamDto {
winnerId: number;
loserId: number;
gameType: GameType;
Expand All @@ -10,21 +10,26 @@ export class CreateGameParamDto {
ballSpeed: number;
racketSize: number;

constructor(player1Id: number, player2Id: number, gameType: GameType) {
constructor(
player1Id: number,
player2Id: number,
gameType: GameType,
gameStatus: GameStatus,
) {
this.winnerId = player1Id;
this.loserId = player2Id;
this.gameType = gameType;
this.winnerScore = 0;
this.loserScore = 0;
this.gameStatus = GameStatus.WAITING;
this.gameStatus = gameStatus;
if (
this.gameType === GameType.SPECIAL_INVITE ||
this.gameType === GameType.SPECIAL_MATCHING
) {
this.ballSpeed = this.getRandomNumber(1, 3);
this.racketSize = this.getRandomNumber(1, 3);
} else {
// Set to 1 for NORMAL
// Set 1 for LADDER and NORMAL
this.ballSpeed = 1;
this.racketSize = 1;
}
Expand Down
4 changes: 0 additions & 4 deletions src/game/dto/delete-invitations-param.dto.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export class GatewaySendInvitationReplyDto {
export class EmitEventInvitationReplyDto {
targetUserId: number;
targetUserChannelSocketId: string;
isAccepted: boolean;
Expand Down
4 changes: 4 additions & 0 deletions src/game/dto/emit-event-match-score-param.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class EmitEventMatchScoreParamDto {
myScore: number;
rivalScore: number;
}
14 changes: 14 additions & 0 deletions src/game/dto/emit-event-match-status.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export class EmitEventMatchStatusDto {
myRacket: {
x: number;
y: number;
};
rivalRacket: {
x: number;
y: number;
};
ball: {
x: number;
y: number;
};
}
5 changes: 5 additions & 0 deletions src/game/dto/emit-event-server-game-ready-param.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class EmitEventServerGameReadyParamDto {
rivalNickname: string;
rivalAvatar: string;
myPosition: string;
}
42 changes: 32 additions & 10 deletions src/game/dto/game.dto.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,55 @@
import { GameStatus } from '../../common/enum';
import { GameStatus, GameType } from '../../common/enum';
import { Game } from '../entities/game.entity';
import { ViewMapDto } from './view-map.dto';

export class GameDto {
private gameId: number;
player1Id: number;
player2Id: number;
playerLeftId: number;
playerRightId: number;
winnerId: number | null;
loserId: number | null;
score1: number;
score2: number;
scoreLeft: number;
scoreRight: number;
gameType: GameType;
gameStatus: GameStatus;
viewMap: ViewMapDto;
readyCnt: number;
gameInterrupted: boolean;

constructor(game: Game) {
constructor(game: Game, readonly maxScore = 7) {
this.setGameId(game.id);
this.player1Id = game.winnerId;
this.player2Id = game.loserId;
this.playerLeftId = game.winnerId;
this.playerRightId = game.loserId;
this.winnerId = null;
this.loserId = null;
this.score1 = game.winnerScore;
this.score2 = game.loserScore;
this.scoreLeft = game.winnerScore;
this.scoreRight = game.loserScore;
this.gameType = game.gameType;
this.gameStatus = game.gameStatus;
this.viewMap = new ViewMapDto(game.ballSpeed, game.racketSize);
this.readyCnt = 0;
this.gameInterrupted = false;
}

getGameId() {
return this.gameId;
}

bothReady() {
return this.readyCnt == 2;
}

isOver(): boolean {
if (
this.scoreLeft === this.maxScore ||
this.scoreRight === this.maxScore
) {
this.gameStatus = GameStatus.FINISHED;
return true;
}
return false;
}

private setGameId(gameId: number) {
this.gameId = gameId;
}
Expand Down
5 changes: 0 additions & 5 deletions src/game/dto/gateway-join-game-room-param.dto.ts

This file was deleted.

204 changes: 186 additions & 18 deletions src/game/dto/view-map.dto.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,211 @@
// ball 변하는 값
type ball = {
export type ball = {
x: number;
y: number;
speed: number;
vx: number;
vy: number;
xVelocity: number; // 속력: 속도 * 방향
yVelocity: number;
accel: number; // 새로운 판마다 증가
};

// racket 변하는 값
type racket = {
export type racket = {
y: number;
size: number;
action: string; // up, down
};

export class UpdateDto {
racketLeft: {
x: number;
y: number;
};
racketRight: {
x: number;
y: number;
};
ball: {
x: number;
y: number;
};
scoreLeft: boolean;
scoreRight: boolean;

isScoreChanged(): boolean {
return this.scoreRight || this.scoreRight;
}
}

export class ViewMapDto {
ball: ball;
racket1: racket;
racket2: racket;
ballSpeed: number;
racketLeft: racket;
racketRight: racket;
racketSize: number;
private updateDto: UpdateDto;

constructor(
ballSpeed: number,
racketSize: number,

// 고정값
private readonly canvasWidth = 1400,
private readonly canvasHeight = 1000,
readonly canvasWidth = 1400,
readonly canvasHeight = 1000,

readonly ballRadius = 2,

private readonly ballRadius = 2,
readonly racketWidth = canvasWidth * 0.1,
readonly racketHeight = canvasHeight * 0.4,
readonly racketLeftX = 0,
readonly racketRightX = canvasWidth - racketWidth,
readonly racketSpeed = 6,

private readonly racketWidth = canvasWidth * 0.1,
private readonly racketHeight = canvasHeight * 0.4,
private readonly racket1X = 0,
private readonly racket2X = canvasWidth - racketWidth,
readonly deltaTime = 1 / 60,
) {
this.updateDto = new UpdateDto();
this.ball.x = canvasWidth / 2;
this.ball.y = canvasHeight / 2;
this.ball.speed = ballSpeed;
this.ballSpeed = ballSpeed;
this.ball.xVelocity =
ballSpeed * (Math.random() < 0.5 ? 0 : 1) === 0 ? 1 : -1;
this.ball.yVelocity =
ballSpeed * (Math.random() < 0.5 ? 0 : 1) === 0 ? 1 : -1;
this.ball.accel = 0;

this.racketLeft.y = canvasHeight / 2 - racketHeight / 2;
this.racketRight.y = canvasHeight / 2 - racketHeight / 2;
this.racketSize = racketSize;
}

async init() {
this.ball.vx = 0;
this.ball.vy = 0;
this.updateDto.scoreLeft = false;
this.updateDto.scoreRight = false;

this.ball.x = this.canvasWidth / 2;
this.ball.y = this.canvasHeight / 2;
this.ball.xVelocity =
this.ballSpeed * (Math.random() < 0.5 ? 0 : 1) === 0 ? 1 : -1;
this.ball.yVelocity =
this.ballSpeed * (Math.random() < 0.5 ? 0 : 1) === 0 ? 1 : -1;

this.ball.accel += 0.2;
this.racketLeft.y = this.canvasHeight / 2 - this.racketHeight / 2;
this.racketRight.y = this.canvasHeight / 2 - this.racketHeight / 2;
}

private async updateBall() {
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;
}

updateRacketLeft(action: string) {
const racket = this.racketLeft;

if (action === 'arrowUp') racket.y -= this.racketSpeed;
else if (action === 'arrowDown') racket.y += this.racketSpeed;

if (racket.y <= 0) racket.y = 0;
if (racket.y + this.racketHeight >= this.canvasHeight)
racket.y = this.canvasHeight - this.racketHeight;
}

updateRacketRight(action: string) {
const racket = this.racketRight;

if (action === 'up') racket.y -= this.racketSpeed;
else if (action === 'down') racket.y += this.racketSpeed;

if (racket.y <= 0) racket.y = 0;
if (racket.y + this.racketHeight >= this.canvasHeight)
racket.y = this.canvasHeight - this.racketHeight;
}

async changes() {
const updateDto = this.updateDto;
const ball = this.ball;
await this.updateBall();

// racket, 천장, 바닥에 부딪히는지
await this.detectCollision();

//score
if (ball.x + this.ballRadius >= this.canvasWidth)
updateDto.scoreRight = true; // right
else if (ball.x - this.ballRadius <= 0) updateDto.scoreLeft = true; // left

// 내보내기
updateDto.racketLeft = {
x: this.racketLeftX,
y: this.racketLeft.y,
};
updateDto.racketRight = {
x: this.racketRightX,
y: this.racketRight.y,
};
updateDto.ball = {
x: this.ball.x,
y: this.ball.y,
};

return updateDto;
}

private async detectCollision() {
const ball = this.ball;
let dx, dy;

// 새로운 방향이 양수면 오른쪽 racket, 음수면 왼쪽 racket이랑 부딪히는지 검사
if (this.ball.vx > 0) {
dx = Math.abs(ball.x - this.getRacketRightCenter().cx);
dy = Math.abs(ball.y - this.getRacketRightCenter().cy);
if (
dx <= this.ballRadius + this.racketWidth / 2 &&
dy <= this.ballRadius + this.racketHeight / 2
)
ball.xVelocity *= -1;
} else if (this.ball.vx < 0) {
dx = Math.abs(ball.x - this.getRacketLeftCenter().cx);
dy = Math.abs(ball.y - this.getRacketLeftCenter().cy);
if (
dx <= this.ballRadius + this.racketWidth / 2 &&
dy <= this.ballRadius + this.racketHeight / 2
)
ball.xVelocity *= -1;
}

// 바닥, 천장
if (
ball.y + this.ballRadius >= this.canvasHeight ||
ball.y - this.ballRadius <= 0
)
ball.yVelocity *= -1;
}

private getRacketLeftCenter() {
return {
cx: this.racketLeftX + this.racketWidth / 2,
cy: this.racketLeft.y + this.racketHeight / 2,
};
}

this.racket1.y = canvasHeight / 2 - racketHeight / 2;
this.racket2.y = canvasHeight / 2 - racketHeight / 2;
this.racket1.size = racketSize;
this.racket2.size = racketSize;
private getRacketRightCenter() {
return {
cx: this.racketRightX + this.racketWidth / 2,
cy: this.racketRight.y + this.racketHeight / 2,
};
}
}
Loading
Loading