From babe1abcdd86f67664d3473100a66c905d59c031 Mon Sep 17 00:00:00 2001 From: vvandenb Date: Fri, 3 Mar 2023 11:03:15 +0100 Subject: [PATCH] * More DTOs for pong game * Pong games get deleted properly * Added bounce angles to pong walls --- ...tionDto.ts => GameCreationDtoValidated.ts} | 12 ++-- back/volume/src/pong/dtos/GameInfo.ts | 12 ++++ back/volume/src/pong/dtos/GameUpdate.ts | 7 +++ back/volume/src/pong/dtos/MapDtoValidated.ts | 23 ++++++++ .../volume/src/pong/dtos/PointDtoValidated.ts | 10 ++++ back/volume/src/pong/dtos/RectDtoValidated.ts | 14 +++++ back/volume/src/pong/dtos/StringDto.ts | 3 + .../src/pong/dtos/StringDtoValidated.ts | 7 +++ back/volume/src/pong/game/Ball.ts | 16 +++-- back/volume/src/pong/game/Game.ts | 38 ++++++------ back/volume/src/pong/game/Games.ts | 55 ++++++++++++----- back/volume/src/pong/game/Map.ts | 15 ----- back/volume/src/pong/game/Paddle.ts | 4 +- back/volume/src/pong/game/constants.ts | 32 ++-------- back/volume/src/pong/pong.gateway.ts | 50 +++++++++------- front/volume/src/App.svelte | 8 ++- front/volume/src/components/Chat2.svelte | 24 ++++---- front/volume/src/components/Pong/Game.ts | 10 ++-- .../components/Pong/MapCustomization.svelte | 12 ++-- front/volume/src/components/Pong/Pong.svelte | 59 +++++++++---------- front/volume/src/components/Pong/constants.ts | 32 ++-------- .../src/components/Pong/dtos/GameInfo.ts | 12 ++++ .../src/components/Pong/dtos/GameUpdate.ts | 7 +++ .../src/components/Pong/dtos/StringDto.ts | 3 + 24 files changed, 271 insertions(+), 194 deletions(-) rename back/volume/src/pong/dtos/{GameCreationDto.ts => GameCreationDtoValidated.ts} (65%) create mode 100644 back/volume/src/pong/dtos/GameInfo.ts create mode 100644 back/volume/src/pong/dtos/GameUpdate.ts create mode 100644 back/volume/src/pong/dtos/MapDtoValidated.ts create mode 100644 back/volume/src/pong/dtos/PointDtoValidated.ts create mode 100644 back/volume/src/pong/dtos/RectDtoValidated.ts create mode 100644 back/volume/src/pong/dtos/StringDto.ts create mode 100644 back/volume/src/pong/dtos/StringDtoValidated.ts delete mode 100644 back/volume/src/pong/game/Map.ts create mode 100644 front/volume/src/components/Pong/dtos/GameInfo.ts create mode 100644 front/volume/src/components/Pong/dtos/GameUpdate.ts create mode 100644 front/volume/src/components/Pong/dtos/StringDto.ts diff --git a/back/volume/src/pong/dtos/GameCreationDto.ts b/back/volume/src/pong/dtos/GameCreationDtoValidated.ts similarity index 65% rename from back/volume/src/pong/dtos/GameCreationDto.ts rename to back/volume/src/pong/dtos/GameCreationDtoValidated.ts index a7784ca..ca8c3ae 100644 --- a/back/volume/src/pong/dtos/GameCreationDto.ts +++ b/back/volume/src/pong/dtos/GameCreationDtoValidated.ts @@ -2,24 +2,20 @@ import { Type } from 'class-transformer' import { ArrayMaxSize, ArrayMinSize, - IsDefined, IsNotEmptyObject, - IsObject, IsString, ValidateNested } from 'class-validator' -import { Map } from '../game/Map' +import { MapDtoValidated } from './MapDtoValidated' -export class GameCreationDto { +export class GameCreationDtoValidated { @IsString({ each: true }) @ArrayMaxSize(2) @ArrayMinSize(2) playerNames!: string[] - @IsDefined() - @IsObject() @IsNotEmptyObject() @ValidateNested() - @Type(() => Map) - map!: Map + @Type(() => MapDtoValidated) + map!: MapDtoValidated } diff --git a/back/volume/src/pong/dtos/GameInfo.ts b/back/volume/src/pong/dtos/GameInfo.ts new file mode 100644 index 0000000..ad86391 --- /dev/null +++ b/back/volume/src/pong/dtos/GameInfo.ts @@ -0,0 +1,12 @@ +import { type Point, type Rect } from '../game/utils' + +export class GameInfo { + mapSize!: Point + yourPaddleIndex!: number + gameId!: string + walls!: Rect[] + paddleSize!: Point + playerXOffset!: number + ballSize!: Point + winScore!: number +} diff --git a/back/volume/src/pong/dtos/GameUpdate.ts b/back/volume/src/pong/dtos/GameUpdate.ts new file mode 100644 index 0000000..9eefbea --- /dev/null +++ b/back/volume/src/pong/dtos/GameUpdate.ts @@ -0,0 +1,7 @@ +import { type Point } from '../game/utils' + +export class GameUpdate { + paddlesPositions!: Point[] + ballPosition!: Point + scores!: number[] +} diff --git a/back/volume/src/pong/dtos/MapDtoValidated.ts b/back/volume/src/pong/dtos/MapDtoValidated.ts new file mode 100644 index 0000000..716e883 --- /dev/null +++ b/back/volume/src/pong/dtos/MapDtoValidated.ts @@ -0,0 +1,23 @@ +import { Type } from 'class-transformer' +import { + ArrayMaxSize, + IsArray, + IsDefined, + IsObject, + ValidateNested +} from 'class-validator' +import { PointDtoValidated } from './PointDtoValidated' +import { RectDtoValidated } from './RectDtoValidated' + +export class MapDtoValidated { + @IsObject() + @IsDefined() + @Type(() => PointDtoValidated) + size!: PointDtoValidated + + @IsArray() + @ArrayMaxSize(5) + @ValidateNested({ each: true }) + @Type(() => RectDtoValidated) + walls!: RectDtoValidated[] +} diff --git a/back/volume/src/pong/dtos/PointDtoValidated.ts b/back/volume/src/pong/dtos/PointDtoValidated.ts new file mode 100644 index 0000000..8a8cbf6 --- /dev/null +++ b/back/volume/src/pong/dtos/PointDtoValidated.ts @@ -0,0 +1,10 @@ +import { IsNumber } from 'class-validator' +import { Point } from '../game/utils' + +export class PointDtoValidated extends Point { + @IsNumber() + x!: number + + @IsNumber() + y!: number +} diff --git a/back/volume/src/pong/dtos/RectDtoValidated.ts b/back/volume/src/pong/dtos/RectDtoValidated.ts new file mode 100644 index 0000000..d24a682 --- /dev/null +++ b/back/volume/src/pong/dtos/RectDtoValidated.ts @@ -0,0 +1,14 @@ +import { Type } from 'class-transformer' +import { ValidateNested } from 'class-validator' +import { Rect } from '../game/utils' +import { PointDtoValidated } from './PointDtoValidated' + +export class RectDtoValidated extends Rect { + @ValidateNested() + @Type(() => PointDtoValidated) + center!: PointDtoValidated + + @ValidateNested() + @Type(() => PointDtoValidated) + size!: PointDtoValidated +} diff --git a/back/volume/src/pong/dtos/StringDto.ts b/back/volume/src/pong/dtos/StringDto.ts new file mode 100644 index 0000000..62283b6 --- /dev/null +++ b/back/volume/src/pong/dtos/StringDto.ts @@ -0,0 +1,3 @@ +export class StringDto { + value!: string +} diff --git a/back/volume/src/pong/dtos/StringDtoValidated.ts b/back/volume/src/pong/dtos/StringDtoValidated.ts new file mode 100644 index 0000000..0211e22 --- /dev/null +++ b/back/volume/src/pong/dtos/StringDtoValidated.ts @@ -0,0 +1,7 @@ +import { IsString } from 'class-validator' +import { StringDto } from './StringDto' + +export class StringDtoValidated extends StringDto { + @IsString() + value!: string +} diff --git a/back/volume/src/pong/game/Ball.ts b/back/volume/src/pong/game/Ball.ts index 4e327a0..e47eae3 100644 --- a/back/volume/src/pong/game/Ball.ts +++ b/back/volume/src/pong/game/Ball.ts @@ -1,7 +1,7 @@ -import { gameInfoConstants } from './constants' import { type Paddle } from './Paddle' import { Point, Rect } from './utils' -import { type Map } from './Map' +import { type MapDtoValidated } from '../dtos/MapDtoValidated' +import { DEFAULT_BALL_SIZE } from './constants' export class Ball { rect: Rect @@ -11,7 +11,7 @@ export class Ball { constructor ( spawn: Point, - size: Point = gameInfoConstants.ballSize, + size: Point = DEFAULT_BALL_SIZE, speed: Point = new Point(10, 2) ) { this.rect = new Rect(spawn, size) @@ -24,7 +24,7 @@ export class Ball { return this.indexPlayerScored } - update (canvasRect: Rect, paddles: Paddle[], map: Map): void { + update (canvasRect: Rect, paddles: Paddle[], map: MapDtoValidated): void { if (!canvasRect.contains_x(this.rect)) { this.indexPlayerScored = this.playerScored() } else { @@ -33,7 +33,7 @@ export class Ball { } } - move (canvasRect: Rect, paddles: Paddle[], map: Map): void { + move (canvasRect: Rect, paddles: Paddle[], map: MapDtoValidated): void { for (const paddle of paddles) { if (paddle.rect.collides(this.rect)) { if (this.speed.x < 0) { @@ -49,8 +49,12 @@ export class Ball { for (const wall of map.walls) { if (wall.collides(this.rect)) { + if (this.speed.x < 0) { + this.rect.center.x = wall.center.x + wall.size.x + } else this.rect.center.x = wall.center.x - wall.size.x this.speed.x = this.speed.x * -1 - this.speed.y = this.speed.y * -1 + this.speed.y = + ((this.rect.center.y - wall.center.y) / wall.size.y) * 20 break } } diff --git a/back/volume/src/pong/game/Game.ts b/back/volume/src/pong/game/Game.ts index 9527206..0ee9816 100644 --- a/back/volume/src/pong/game/Game.ts +++ b/back/volume/src/pong/game/Game.ts @@ -3,14 +3,17 @@ import { type WebSocket } from 'ws' import { formatWebsocketData, Point, Rect } from './utils' import { Player } from './Player' import { - type GameInfo, - gameInfoConstants, - type GameUpdate, + DEFAULT_BALL_SIZE, + DEFAULT_PADDLE_SIZE, + DEFAULT_PLAYER_X_OFFSET, + DEFAULT_WIN_SCORE, GAME_EVENTS } from './constants' import { randomUUID } from 'crypto' import { Spectator } from './Spectator' -import { type Map } from './Map' +import { type MapDtoValidated } from '../dtos/MapDtoValidated' +import { type GameUpdate } from '../dtos/GameUpdate' +import { type GameInfo } from '../dtos/GameInfo' const GAME_TICKS = 30 @@ -28,7 +31,7 @@ function gameLoop (game: Game): void { const indexPlayerScored: number = game.ball.getIndexPlayerScored() if (indexPlayerScored !== -1) { game.players[indexPlayerScored].score += 1 - if (game.players[indexPlayerScored].score >= gameInfoConstants.winScore) { + if (game.players[indexPlayerScored].score >= DEFAULT_WIN_SCORE) { console.log(`${game.players[indexPlayerScored].name} won!`) game.stop() } @@ -49,22 +52,25 @@ function gameLoop (game: Game): void { export class Game { id: string timer: NodeJS.Timer | null - map: Map + map: MapDtoValidated ball: Ball players: Player[] = [] spectators: Spectator[] = [] playing: boolean + gameStoppedCallback: (name: string) => void constructor ( sockets: WebSocket[], uuids: string[], names: string[], - map: Map + map: MapDtoValidated, + gameStoppedCallback: (name: string) => void ) { this.id = randomUUID() this.timer = null this.playing = false this.map = map + this.gameStoppedCallback = gameStoppedCallback this.ball = new Ball(new Point(this.map.size.x / 2, this.map.size.y / 2)) for (let i = 0; i < uuids.length; i++) { this.addPlayer(sockets[i], uuids[i], names[i]) @@ -74,11 +80,14 @@ export class Game { getGameInfo (name: string): GameInfo { const yourPaddleIndex = this.players.findIndex((p) => p.name === name) return { - ...gameInfoConstants, mapSize: this.map.size, yourPaddleIndex, gameId: this.id, - walls: this.map.walls + walls: this.map.walls, + paddleSize: DEFAULT_PADDLE_SIZE, + playerXOffset: DEFAULT_PLAYER_X_OFFSET, + ballSize: DEFAULT_BALL_SIZE, + winScore: DEFAULT_WIN_SCORE } } @@ -88,13 +97,10 @@ export class Game { } private addPlayer (socket: WebSocket, uuid: string, name: string): void { - let paddleCoords = new Point( - gameInfoConstants.playerXOffset, - this.map.size.y / 2 - ) + let paddleCoords = new Point(DEFAULT_PLAYER_X_OFFSET, this.map.size.y / 2) if (this.players.length === 1) { paddleCoords = new Point( - this.map.size.x - gameInfoConstants.playerXOffset, + this.map.size.x - DEFAULT_PLAYER_X_OFFSET, this.map.size.y / 2 ) } @@ -130,10 +136,8 @@ export class Game { this.players.forEach((p) => { p.newGame() }) - this.timer = setInterval(gameLoop, 1000 / GAME_TICKS, this) this.broadcastGame(formatWebsocketData(GAME_EVENTS.START_GAME)) - console.log('Started game') this.playing = true return true } @@ -142,11 +146,11 @@ export class Game { stop (): void { if (this.timer !== null) { + this.gameStoppedCallback(this.players[0].name) clearInterval(this.timer) this.timer = null this.players = [] this.playing = false - console.log('Stopped game') } } diff --git a/back/volume/src/pong/game/Games.ts b/back/volume/src/pong/game/Games.ts index 473a04d..da9ab59 100644 --- a/back/volume/src/pong/game/Games.ts +++ b/back/volume/src/pong/game/Games.ts @@ -1,10 +1,15 @@ import { type WebSocket } from 'ws' -import { type GameInfo } from './constants' import { Game } from './Game' import { Point } from './utils' -import { gameInfoConstants } from './constants' -import { type Map as GameMap } from './Map' -import { type GameCreationDto } from '../dtos/GameCreationDto' +import { type MapDtoValidated as GameMap } from '../dtos/MapDtoValidated' +import { type GameCreationDtoValidated } from '../dtos/GameCreationDtoValidated' +import { type GameInfo } from '../dtos/GameInfo' +import { + DEFAULT_BALL_SIZE, + DEFAULT_PADDLE_SIZE, + DEFAULT_PLAYER_X_OFFSET, + DEFAULT_WIN_SCORE +} from './constants' export class Games { private readonly playerNameToGameIndex = new Map() @@ -13,15 +18,27 @@ export class Games { newGame ( sockets: WebSocket[], uuids: string[], - gameCreationDto: GameCreationDto + gameCreationDto: GameCreationDtoValidated ): void { const names: string[] = gameCreationDto.playerNames const map: GameMap = gameCreationDto.map if (!this.isInAGame(names[0]) && !this.isInAGame(names[1])) { - this.games.push(new Game(sockets, uuids, names, map)) + this.games.push( + new Game( + sockets, + uuids, + names, + map, + this.gameStopped.bind(this, names[0]) + ) + ) this.playerNameToGameIndex.set(names[0], this.games.length - 1) this.playerNameToGameIndex.set(names[1], this.games.length - 1) - console.log(`Created game ${names[0]} vs ${names[1]}`) + console.log( + `Created game ${names[0]} vs ${names[1]} (${ + this.games[this.games.length - 1].id + })` + ) } } @@ -39,13 +56,16 @@ export class Games { } } - // stopGame (uuid: string): void { - // // if (this.isInAGame(uuid)) { - // // this.playerGame(uuid).stop() - // // delete this.playerNameToGameIndex[uuid] - // // delete this.games[this.playerNameToGameIndex[uuid]] - // // } - // } + private gameStopped (name: string): void { + const game: Game | null = this.playerGame(name) + if (game !== null) { + this.games.splice(this.games.indexOf(game), 1) + game.players.forEach((player) => { + this.playerNameToGameIndex.delete(player.name) + }) + console.log(`Game stopped: ${game.id}`) + } + } getGameInfo (name: string): GameInfo { const game: Game | null = this.playerGame(name) @@ -53,11 +73,14 @@ export class Games { return game.getGameInfo(name) } return { - ...gameInfoConstants, yourPaddleIndex: 0, gameId: '', mapSize: new Point(0, 0), - walls: [] + walls: [], + paddleSize: DEFAULT_PADDLE_SIZE, + playerXOffset: DEFAULT_PLAYER_X_OFFSET, + ballSize: DEFAULT_BALL_SIZE, + winScore: DEFAULT_WIN_SCORE } } diff --git a/back/volume/src/pong/game/Map.ts b/back/volume/src/pong/game/Map.ts deleted file mode 100644 index 48bece8..0000000 --- a/back/volume/src/pong/game/Map.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Type } from 'class-transformer' -import { ArrayMaxSize, IsArray, IsDefined, IsObject } from 'class-validator' -import { Point, Rect } from './utils' - -export class Map { - @IsObject() - @IsDefined() - @Type(() => Point) - size!: Point - - @IsArray() - @ArrayMaxSize(5) - @Type(() => Rect) - walls!: Rect[] -} diff --git a/back/volume/src/pong/game/Paddle.ts b/back/volume/src/pong/game/Paddle.ts index 4ce379b..324a819 100644 --- a/back/volume/src/pong/game/Paddle.ts +++ b/back/volume/src/pong/game/Paddle.ts @@ -1,4 +1,4 @@ -import { gameInfoConstants } from './constants' +import { DEFAULT_PADDLE_SIZE } from './constants' import { type Point, Rect } from './utils' export class Paddle { @@ -9,7 +9,7 @@ export class Paddle { constructor ( spawn: Point, gameSize: Point, - size: Point = gameInfoConstants.paddleSize + size: Point = DEFAULT_PADDLE_SIZE ) { this.rect = new Rect(spawn, size) this.mapSize = gameSize diff --git a/back/volume/src/pong/game/constants.ts b/back/volume/src/pong/game/constants.ts index c808d9a..fe2a3df 100644 --- a/back/volume/src/pong/game/constants.ts +++ b/back/volume/src/pong/game/constants.ts @@ -1,4 +1,4 @@ -import { Point, type Rect } from './utils' +import { Point } from './utils' export const GAME_EVENTS = { START_GAME: 'START_GAME', @@ -11,28 +11,8 @@ export const GAME_EVENTS = { SPECTATE: 'SPECTATE' } -export interface GameInfo extends GameInfoConstants { - yourPaddleIndex: number - gameId: string - walls: Rect[] -} -export interface GameInfoConstants { - mapSize: Point - paddleSize: Point - playerXOffset: number - ballSize: Point - winScore: number -} -export const gameInfoConstants: GameInfoConstants = { - mapSize: new Point(600, 400), - paddleSize: new Point(6, 50), - playerXOffset: 50, - ballSize: new Point(20, 20), - winScore: 9999 -} - -export interface GameUpdate { - paddlesPositions: Point[] - ballPosition: Point - scores: number[] -} +export const DEFAULT_MAP_SIZE = new Point(600, 400) +export const DEFAULT_PADDLE_SIZE = new Point(6, 50) +export const DEFAULT_BALL_SIZE = new Point(20, 20) +export const DEFAULT_PLAYER_X_OFFSET = 50 +export const DEFAULT_WIN_SCORE = 5 diff --git a/back/volume/src/pong/pong.gateway.ts b/back/volume/src/pong/pong.gateway.ts index 05d2647..3a894dd 100644 --- a/back/volume/src/pong/pong.gateway.ts +++ b/back/volume/src/pong/pong.gateway.ts @@ -9,11 +9,14 @@ import { } from '@nestjs/websockets' import { randomUUID } from 'crypto' import { Games } from './game/Games' -import { formatWebsocketData, Point, Rect } from './game/utils' +import { formatWebsocketData } from './game/utils' import { GAME_EVENTS } from './game/constants' -import { GameCreationDto } from './dtos/GameCreationDto' +import { GameCreationDtoValidated } from './dtos/GameCreationDtoValidated' import { UsePipes, ValidationPipe } from '@nestjs/common' import { type Game } from './game/Game' +import { plainToClass } from 'class-transformer' +import { PointDtoValidated } from './dtos/PointDtoValidated' +import { StringDtoValidated } from './dtos/StringDtoValidated' interface WebSocketWithId extends WebSocket { id: string @@ -44,14 +47,15 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { } } + @UsePipes(new ValidationPipe({ whitelist: true })) @SubscribeMessage(GAME_EVENTS.REGISTER_PLAYER) registerPlayer ( @ConnectedSocket() client: WebSocketWithId, - @MessageBody('playerName') playerName: string - ): void { - this.socketToPlayerName.set(client, playerName) - console.log('Connected ', this.socketToPlayerName.get(client)) + @MessageBody() playerName: StringDtoValidated + ): { event: string, data: StringDtoValidated } { + this.socketToPlayerName.set(client, playerName.value) + return { event: GAME_EVENTS.REGISTER_PLAYER, data: playerName } } @SubscribeMessage(GAME_EVENTS.GET_GAME_INFO) @@ -67,14 +71,19 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { } } + @UsePipes(new ValidationPipe({ whitelist: true })) @SubscribeMessage(GAME_EVENTS.PLAYER_MOVE) movePlayer ( @ConnectedSocket() client: WebSocketWithId, - @MessageBody('position') position: Point + @MessageBody() position: PointDtoValidated ): void { + const realPosition: PointDtoValidated = plainToClass( + PointDtoValidated, + position + ) const name: string | undefined = this.socketToPlayerName.get(client) - this.games.movePlayer(name, position) + this.games.movePlayer(name, realPosition) } @UsePipes(new ValidationPipe({ whitelist: true })) @@ -82,27 +91,27 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { createGame ( @ConnectedSocket() client: WebSocketWithId, - @MessageBody() gameCreationDto: GameCreationDto + @MessageBody() gameCreationDto: GameCreationDtoValidated ): void { - gameCreationDto.map.walls = gameCreationDto.map.walls.map((wall) => { - return new Rect( - new Point(wall.center.x, wall.center.y), - new Point(wall.size.x, wall.size.y) - ) - }) + const realGameCreationDto: GameCreationDtoValidated = plainToClass( + GameCreationDtoValidated, + gameCreationDto + ) if (this.socketToPlayerName.size >= 2) { const player1Socket: WebSocketWithId | undefined = Array.from( this.socketToPlayerName.keys() ).find( (key) => - this.socketToPlayerName.get(key) === gameCreationDto.playerNames[0] + this.socketToPlayerName.get(key) === + realGameCreationDto.playerNames[0] ) const player2Socket: WebSocketWithId | undefined = Array.from( this.socketToPlayerName.keys() ).find( (key) => - this.socketToPlayerName.get(key) === gameCreationDto.playerNames[1] + this.socketToPlayerName.get(key) === + realGameCreationDto.playerNames[1] ) if ( @@ -114,7 +123,7 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { this.games.newGame( [player1Socket, player2Socket], [player1Socket.id, player2Socket.id], - gameCreationDto + realGameCreationDto ) } } @@ -131,15 +140,16 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { } } + @UsePipes(new ValidationPipe({ whitelist: true })) @SubscribeMessage(GAME_EVENTS.SPECTATE) spectate ( @ConnectedSocket() client: WebSocketWithId, - @MessageBody('playerToSpectate') playerToSpectate: string + @MessageBody() playerToSpectate: StringDtoValidated ): void { const name: string | undefined = this.socketToPlayerName.get(client) if (name !== undefined) { - this.games.spectateGame(playerToSpectate, client, client.id, name) + this.games.spectateGame(playerToSpectate.value, client, client.id, name) } } } diff --git a/front/volume/src/App.svelte b/front/volume/src/App.svelte index e670ec4..629c26b 100644 --- a/front/volume/src/App.svelte +++ b/front/volume/src/App.svelte @@ -79,7 +79,13 @@
- + {#if isChatOpen}
(isChatOpen = false)} diff --git a/front/volume/src/components/Chat2.svelte b/front/volume/src/components/Chat2.svelte index 0abfac7..12aec41 100644 --- a/front/volume/src/components/Chat2.svelte +++ b/front/volume/src/components/Chat2.svelte @@ -6,20 +6,16 @@ diff --git a/front/volume/src/components/Pong/Game.ts b/front/volume/src/components/Pong/Game.ts index 8f9e56d..5323b3b 100644 --- a/front/volume/src/components/Pong/Game.ts +++ b/front/volume/src/components/Pong/Game.ts @@ -1,6 +1,7 @@ import { Ball } from "./Ball"; import { GAME_EVENTS } from "./constants"; -import type { GameInfo, GameUpdate } from "./constants"; +import type { GameInfo } from "./dtos/GameInfo"; +import type { GameUpdate } from "./dtos/GameUpdate"; import { Paddle } from "./Paddle"; import { Player } from "./Player"; import { formatWebsocketData, Point, Rect } from "./utils"; @@ -58,11 +59,8 @@ export class Game { if (this.my_paddle) { this.canvas.addEventListener("mousemove", (e) => { this.my_paddle.move(e); - socket.send( - formatWebsocketData(GAME_EVENTS.PLAYER_MOVE, { - position: this.my_paddle.rect.center, - }) - ); + const data: Point = this.my_paddle.rect.center; + socket.send(formatWebsocketData(GAME_EVENTS.PLAYER_MOVE, data)); }); console.log("Game started!"); } diff --git a/front/volume/src/components/Pong/MapCustomization.svelte b/front/volume/src/components/Pong/MapCustomization.svelte index 82a1baf..f1b0f81 100644 --- a/front/volume/src/components/Pong/MapCustomization.svelte +++ b/front/volume/src/components/Pong/MapCustomization.svelte @@ -2,7 +2,7 @@ import { onMount } from "svelte"; import { Point, Rect } from "./utils"; import type { Map } from "./Map"; - import { gameInfoConstants } from "./constants"; + import { DEFAULT_BALL_SIZE } from "./constants"; export let map: Map; let canvas: HTMLCanvasElement; @@ -48,14 +48,12 @@ new Point(e.offsetX, e.offsetY), new Point(wallWidth, wallHeight) ); - const ballSpawn = new Rect( + const ballSpawnArea = new Rect( new Point(map.size.x / 2, map.size.y / 2), - new Point( - gameInfoConstants.ballSize.x * 5, - gameInfoConstants.ballSize.y * 5 - ) + new Point(DEFAULT_BALL_SIZE.x * 5, DEFAULT_BALL_SIZE.y * 5) ); - if (map.walls.length < 5 && !wall.collides(ballSpawn)) map.walls.push(wall); + if (map.walls.length < 5 && !wall.collides(ballSpawnArea)) + map.walls.push(wall); } function removeWall(e: MouseEvent) { diff --git a/front/volume/src/components/Pong/Pong.svelte b/front/volume/src/components/Pong/Pong.svelte index 2cb0d8d..09606c0 100644 --- a/front/volume/src/components/Pong/Pong.svelte +++ b/front/volume/src/components/Pong/Pong.svelte @@ -1,39 +1,36 @@ @@ -130,7 +129,7 @@ {:else} Connecting to game server... {/if} - +
diff --git a/front/volume/src/components/Pong/constants.ts b/front/volume/src/components/Pong/constants.ts index 5bb83c2..546fa84 100644 --- a/front/volume/src/components/Pong/constants.ts +++ b/front/volume/src/components/Pong/constants.ts @@ -1,4 +1,4 @@ -import { Point, Rect } from "./utils"; +import { Point } from "./utils"; export const GAME_EVENTS = { START_GAME: "START_GAME", @@ -11,28 +11,8 @@ export const GAME_EVENTS = { SPECTATE: "SPECTATE", }; -export interface GameInfo extends GameInfoConstants { - yourPaddleIndex: number; - gameId: string; - walls: Rect[]; -} -export interface GameInfoConstants { - mapSize: Point; - paddleSize: Point; - playerXOffset: number; - ballSize: Point; - winScore: number; -} -export const gameInfoConstants: GameInfoConstants = { - mapSize: new Point(600, 400), - paddleSize: new Point(6, 50), - playerXOffset: 50, - ballSize: new Point(20, 20), - winScore: 9999, -}; - -export interface GameUpdate { - paddlesPositions: Point[]; - ballPosition: Point; - scores: number[]; -} +export const DEFAULT_MAP_SIZE = new Point(600, 400); +export const DEFAULT_PADDLE_SIZE = new Point(6, 50); +export const DEFAULT_BALL_SIZE = new Point(20, 20); +export const DEFAULT_PLAYER_X_OFFSET = 50; +export const DEFAULT_WIN_SCORE = 5; diff --git a/front/volume/src/components/Pong/dtos/GameInfo.ts b/front/volume/src/components/Pong/dtos/GameInfo.ts new file mode 100644 index 0000000..657b340 --- /dev/null +++ b/front/volume/src/components/Pong/dtos/GameInfo.ts @@ -0,0 +1,12 @@ +import type { Point, Rect } from "../utils"; + +export class GameInfo { + mapSize!: Point; + yourPaddleIndex!: number; + gameId!: string; + walls!: Rect[]; + paddleSize!: Point; + playerXOffset!: number; + ballSize!: Point; + winScore!: number; +} diff --git a/front/volume/src/components/Pong/dtos/GameUpdate.ts b/front/volume/src/components/Pong/dtos/GameUpdate.ts new file mode 100644 index 0000000..789bf38 --- /dev/null +++ b/front/volume/src/components/Pong/dtos/GameUpdate.ts @@ -0,0 +1,7 @@ +import type { Point } from "../utils"; + +export class GameUpdate { + paddlesPositions!: Point[]; + ballPosition!: Point; + scores!: number[]; +} diff --git a/front/volume/src/components/Pong/dtos/StringDto.ts b/front/volume/src/components/Pong/dtos/StringDto.ts new file mode 100644 index 0000000..1aa81ce --- /dev/null +++ b/front/volume/src/components/Pong/dtos/StringDto.ts @@ -0,0 +1,3 @@ +export class StringDto { + value!: string; +}