From c8c3111ed4d2ac5bd8c0db79abe6aff410a74f9f Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Thu, 1 Dec 2022 15:55:40 +0100 Subject: [PATCH] WIP multiBalls (need refactoring) --- src/client/class/GameComponentsClient.ts | 16 +++- src/client/constants.ts | 2 +- src/client/draw.ts | 7 ++ src/client/gameLoop.ts | 6 ++ src/client/pong.ts | 2 +- src/client/ws.ts | 11 +++ src/server/class/GameComponentsServer.ts | 6 +- src/server/class/GameSession.ts | 98 +++++++++++++++--------- src/shared_js/class/Event.ts | 14 ++++ src/shared_js/class/GameComponents.ts | 14 +++- src/shared_js/class/Rectangle.ts | 1 + 11 files changed, 132 insertions(+), 45 deletions(-) diff --git a/src/client/class/GameComponentsClient.ts b/src/client/class/GameComponentsClient.ts index c5046ee3..047e3589 100644 --- a/src/client/class/GameComponentsClient.ts +++ b/src/client/class/GameComponentsClient.ts @@ -1,5 +1,6 @@ import * as c from "../constants.js" +import * as en from "../../shared_js/enums.js" import { Vector, VectorInteger } from "../../shared_js/class/Vector.js"; import { TextElem, TextNumericValue } from "./Text.js"; import { RectangleClient, RacketClient, BallClient, Line } from "./RectangleClient.js"; @@ -11,14 +12,21 @@ class GameComponentsExtensionForClient extends GameComponents { playerLeft: RacketClient; playerRight: RacketClient; ball: BallClient; - constructor(ctx: CanvasRenderingContext2D) + ball2?: BallClient; + ball3?: BallClient; + constructor(options: en.MatchOptions, ctx: CanvasRenderingContext2D) { - super(); + super(options); this.wallTop = new RectangleClient(this.wallTop.pos, this.wallTop.width, this.wallTop.height, ctx, "grey"); this.wallBottom = new RectangleClient(this.wallBottom.pos, this.wallBottom.width, this.wallBottom.height, ctx, "grey"); this.playerLeft = new RacketClient(this.playerLeft.pos, this.playerLeft.width, this.playerLeft.height, this.playerLeft.baseSpeed, ctx, "white"); this.playerRight = new RacketClient(this.playerRight.pos, this.playerRight.width, this.playerRight.height, this.playerRight.baseSpeed, ctx, "white"); this.ball = new BallClient(this.ball.pos, this.ball.width, this.ball.baseSpeed, this.ball.speedIncrease, ctx, "white"); + if (options & en.MatchOptions.multiBalls) + { // ALTERNATIVE POSSIBLE, Array of balls + this.ball2 = new BallClient(this.ball2.pos, this.ball2.width, this.ball2.baseSpeed, this.ball2.speedIncrease, ctx, "white"); + this.ball3 = new BallClient(this.ball3.pos, this.ball3.width, this.ball3.baseSpeed, this.ball3.speedIncrease, ctx, "white"); + } } } @@ -35,9 +43,9 @@ class GameComponentsClient extends GameComponentsExtensionForClient { h_grid_mid: RectangleClient; h_grid_u1: RectangleClient; h_grid_d1: RectangleClient; - constructor(ctx: CanvasRenderingContext2D) + constructor(options: en.MatchOptions, ctx: CanvasRenderingContext2D) { - super(ctx); + super(options, ctx); let pos = new VectorInteger; // Scores pos.assign(c.w_mid-c.scoreSize*1.6, c.scoreSize*1.5); diff --git a/src/client/constants.ts b/src/client/constants.ts index 325ea7af..59266782 100644 --- a/src/client/constants.ts +++ b/src/client/constants.ts @@ -20,4 +20,4 @@ export const soundPongVolume = 0.3; // between 0 and 1 // TODO: replace by a selector on the website import * as en from "../shared_js/enums.js" -export const optionsPLACEHOLDER = en.MatchOptions.noOption; +export const optionsPLACEHOLDER = en.MatchOptions.multiBalls; diff --git a/src/client/draw.ts b/src/client/draw.ts index 71dfa60b..848633da 100644 --- a/src/client/draw.ts +++ b/src/client/draw.ts @@ -1,5 +1,7 @@ import { pong, gc } from "./global.js" +import * as c from "./constants.js" +import * as en from "../shared_js/enums.js" import { gridDisplay } from "./handleInput.js"; function drawLoop() @@ -24,6 +26,11 @@ function drawDynamic() gc.playerLeft.update(); gc.playerRight.update(); gc.ball.update(); + if (c.optionsPLACEHOLDER & en.MatchOptions.multiBalls) + { // ALTERNATIVE POSSIBLE, Array of balls + gc.ball2.update(); + gc.ball3.update(); + } } function drawStatic() diff --git a/src/client/gameLoop.ts b/src/client/gameLoop.ts index 224e3d0e..55d53f82 100644 --- a/src/client/gameLoop.ts +++ b/src/client/gameLoop.ts @@ -1,5 +1,6 @@ import * as c from "./constants.js"; +import * as en from "../shared_js/enums.js" import { gc, clientInfo } from "./global.js"; let actual_time: number = Date.now(); @@ -23,6 +24,11 @@ function gameLoop() // client prediction gc.ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); + if (c.optionsPLACEHOLDER & en.MatchOptions.multiBalls) + { // ALTERNATIVE POSSIBLE, Array of balls + gc.ball2.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); + gc.ball3.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); + } } function opponentInterpolation(delta: number) diff --git a/src/client/pong.ts b/src/client/pong.ts index 05be7494..44eab63c 100644 --- a/src/client/pong.ts +++ b/src/client/pong.ts @@ -16,7 +16,7 @@ import {socket} from "./ws.js"; socket; // no-op, just for loading */ export const pong = new GameArea(); -export const gc = new GameComponentsClient(pong.ctx); +export const gc = new GameComponentsClient(c.optionsPLACEHOLDER, pong.ctx); function matchmaking() { diff --git a/src/client/ws.ts b/src/client/ws.ts index 63dd4d92..559f0c83 100644 --- a/src/client/ws.ts +++ b/src/client/ws.ts @@ -93,6 +93,17 @@ function gameUpdate(data: ev.EventGameUpdate) gc.ball.pos.assign(data.ball.x, data.ball.y); gc.ball.dir.assign(data.ball.dirX, data.ball.dirY); gc.ball.speed = data.ball.speed; + + if (c.optionsPLACEHOLDER & en.MatchOptions.multiBalls) + { // ALTERNATIVE POSSIBLE, Array of balls + gc.ball2.pos.assign(data.ball2.x, data.ball2.y); + gc.ball2.dir.assign(data.ball2.dirX, data.ball2.dirY); + gc.ball2.speed = data.ball2.speed; + + gc.ball3.pos.assign(data.ball3.x, data.ball3.y); + gc.ball3.dir.assign(data.ball3.dirX, data.ball3.dirY); + gc.ball3.speed = data.ball3.speed; + } const predictionPos = new VectorInteger(clientInfo.racket.pos.x, clientInfo.racket.pos.y); // debug diff --git a/src/server/class/GameComponentsServer.ts b/src/server/class/GameComponentsServer.ts index 31f3ca67..d8f2c044 100644 --- a/src/server/class/GameComponentsServer.ts +++ b/src/server/class/GameComponentsServer.ts @@ -1,14 +1,14 @@ import * as c from "../constants.js" +import * as en from "../../shared_js/enums.js" import { GameComponents } from "../../shared_js/class/GameComponents.js"; class GameComponentsServer extends GameComponents { scoreLeft: number = 0; scoreRight: number = 0; - ballInPlay: boolean = false; - constructor() + constructor(options: en.MatchOptions) { - super(); + super(options); } } diff --git a/src/server/class/GameSession.ts b/src/server/class/GameSession.ts index 3b39c888..adb5cb1a 100644 --- a/src/server/class/GameSession.ts +++ b/src/server/class/GameSession.ts @@ -6,6 +6,7 @@ import { ClientPlayer } from "./Client"; import { GameComponentsServer } from "./GameComponentsServer.js"; import { clientInputListener } from "../wsServer.js"; import { random } from "../utils.js"; +import { Ball } from "../../shared_js/class/Rectangle.js"; /* Arg "s: GameSession" replace "this: GameSession" for use with setTimeout(), @@ -27,11 +28,17 @@ class GameSession { constructor(id: string, matchOptions: en.MatchOptions) { this.id = id; this.matchOptions = matchOptions; - this.components = new GameComponentsServer(); + this.components = new GameComponentsServer(this.matchOptions); } start() { setTimeout(this.resume, c.matchStartDelay, this); - setTimeout(this._newRound, c.matchStartDelay + c.newRoundDelay, this); + const gc = this.components; + setTimeout(this._newRound, c.matchStartDelay + c.newRoundDelay, this, gc.ball); + if (this.matchOptions & en.MatchOptions.multiBalls) + { // ALTERNATIVE POSSIBLE, Array of balls + setTimeout(this._newRound, c.matchStartDelay + c.newRoundDelay + c.newRoundDelay*0.33, this, gc.ball2); + setTimeout(this._newRound, c.matchStartDelay + c.newRoundDelay + c.newRoundDelay*0.66, this, gc.ball3); + } } resume(s: GameSession) { s.playersMap.forEach( (client) => { @@ -84,53 +91,74 @@ class GameSession { }); */ const gc = s.components; - if (gc.ballInPlay) + s._ballMovement(s.delta_time, gc.ball); + if (s.matchOptions & en.MatchOptions.multiBalls) + { // ALTERNATIVE POSSIBLE, Array of balls + s._ballMovement(s.delta_time, gc.ball2); + s._ballMovement(s.delta_time, gc.ball3); + } + /* + gc.ballArr.forEach( (ball) => { + s._ballMovement(s.delta_time, ball); + }); + */ + } + private _ballMovement(delta: number, ball: Ball) { + const gc = this.components; + if (ball.ballInPlay) { - gc.ball.moveAndBounce(s.delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); - if (gc.ball.pos.x > c.w) { - gc.ballInPlay = false; + ball.moveAndBounce(delta, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); + if (ball.pos.x > c.w) { + ball.ballInPlay = false; ++gc.scoreLeft; - s.playersMap.forEach( (client) => { + this.playersMap.forEach( (client) => { client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); }); - setTimeout(s._newRound, c.newRoundDelay, s); + setTimeout(this._newRound, c.newRoundDelay, this, ball); } - else if (gc.ball.pos.x < 0 - gc.ball.width) { - gc.ballInPlay = false; + else if (ball.pos.x < 0 - ball.width) { + ball.ballInPlay = false; ++gc.scoreRight; - - s.playersMap.forEach( (client) => { + + this.playersMap.forEach( (client) => { client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); }); - setTimeout(s._newRound, c.newRoundDelay, s); + setTimeout(this._newRound, c.newRoundDelay, this, ball); } } } private _clientsUpdate(s: GameSession) { const gc = s.components; - const update: ev.EventGameUpdate = { - type: en.EventTypes.gameUpdate, - playerLeft: { - y: gc.playerLeft.pos.y - }, - playerRight: { - y: gc.playerRight.pos.y - }, - ball:{ - x: gc.ball.pos.x, - y: gc.ball.pos.y, - dirX: gc.ball.dir.x, - dirY: gc.ball.dir.y, - speed: gc.ball.speed - }, - lastInputId: 0 - }; + const update = new ev.EventGameUpdate(); + update.playerLeft.y = gc.playerLeft.pos.y; + update.playerRight.y = gc.playerRight.pos.y; + + update.ball.x = gc.ball.pos.x; + update.ball.y = gc.ball.pos.y; + update.ball.dirX = gc.ball.dir.x; + update.ball.dirY = gc.ball.dir.y; + update.ball.speed = gc.ball.speed; + if (s.matchOptions & en.MatchOptions.multiBalls) + { // ALTERNATIVE POSSIBLE, Array of balls + update.ball2.x = gc.ball2.pos.x; + update.ball2.y = gc.ball2.pos.y; + update.ball2.dirX = gc.ball2.dir.x; + update.ball2.dirY = gc.ball2.dir.y; + update.ball2.speed = gc.ball2.speed; + + update.ball3.x = gc.ball3.pos.x; + update.ball3.y = gc.ball3.pos.y; + update.ball3.dirX = gc.ball3.dir.x; + update.ball3.dirY = gc.ball3.dir.y; + update.ball3.speed = gc.ball3.speed; + } + s.playersMap.forEach( (client) => { update.lastInputId = client.lastInputId; client.socket.send(JSON.stringify(update)); }); } - private _newRound(s: GameSession) { + private _newRound(s: GameSession, ball: Ball) { const gc = s.components; // https://fr.wikipedia.org/wiki/Tennis_de_table#Nombre_de_manches if (gc.scoreLeft >= 11 || gc.scoreRight >= 11) @@ -142,10 +170,10 @@ class GameSession { return; } } - gc.ball.pos.x = c.w_mid; - gc.ball.pos.y = Math.floor((c.h * 0.1) + random() * (c.h * 0.8)); - gc.ball.speed = gc.ball.baseSpeed; - gc.ballInPlay = true; + ball.pos.x = c.w_mid; + ball.pos.y = Math.floor((c.h * 0.1) + random() * (c.h * 0.8)); + ball.speed = ball.baseSpeed; + ball.ballInPlay = true; } private _matchEnd(s: GameSession) { const gc = s.components; diff --git a/src/shared_js/class/Event.ts b/src/shared_js/class/Event.ts index 1b6ae6cd..d8849e10 100644 --- a/src/shared_js/class/Event.ts +++ b/src/shared_js/class/Event.ts @@ -39,6 +39,20 @@ class EventGameUpdate extends ServerEvent { dirY: 0, speed: 0 }; + ball2? = { // ALTERNATIVE POSSIBLE, Array of balls + x: 0, + y: 0, + dirX: 0, + dirY: 0, + speed: 0 + }; + ball3? = { + x: 0, + y: 0, + dirX: 0, + dirY: 0, + speed: 0 + }; lastInputId = 0; constructor() { // TODO: constructor that take GameComponentsServer maybe ? super(en.EventTypes.gameUpdate); diff --git a/src/shared_js/class/GameComponents.ts b/src/shared_js/class/GameComponents.ts index d6e4e3de..16375851 100644 --- a/src/shared_js/class/GameComponents.ts +++ b/src/shared_js/class/GameComponents.ts @@ -1,5 +1,6 @@ import * as c from "../constants.js" +import * as en from "../../shared_js/enums.js" import { VectorInteger } from "./Vector.js"; import { Rectangle, Racket, Ball } from "./Rectangle.js"; @@ -9,7 +10,9 @@ class GameComponents { playerLeft: Racket; playerRight: Racket; ball: Ball; - constructor() + ball2?: Ball; + ball3?: Ball; + constructor(options: en.MatchOptions) { let pos = new VectorInteger; @@ -26,6 +29,15 @@ class GameComponents { pos.assign(-c.ballSize, -c.ballSize); // ball out =) this.ball = new Ball(pos, c.ballSize, c.ballSpeed, c.ballSpeedIncrease); this.ball.dir.assign(-0.8, +0.2); + + if (options & en.MatchOptions.multiBalls) + { // ALTERNATIVE POSSIBLE, Array of balls + pos.assign(-c.ballSize, -c.ballSize); // ball out =) + this.ball2 = new Ball(pos, c.ballSize, c.ballSpeed, c.ballSpeedIncrease); + this.ball2.dir.assign(-0.8, +0.2); + this.ball3 = new Ball(pos, c.ballSize, c.ballSpeed, c.ballSpeedIncrease); + this.ball3.dir.assign(-0.8, +0.2); + } } } diff --git a/src/shared_js/class/Rectangle.ts b/src/shared_js/class/Rectangle.ts index 8b9e1260..fff71dc9 100644 --- a/src/shared_js/class/Rectangle.ts +++ b/src/shared_js/class/Rectangle.ts @@ -74,6 +74,7 @@ class Racket extends MovingRectangle { class Ball extends MovingRectangle { readonly speedIncrease: number; + ballInPlay: boolean = false; constructor(pos: VectorInteger, size: number, baseSpeed: number, speedIncrease: number) { super(pos, size, size, baseSpeed); this.speedIncrease = speedIncrease;