WIP multiBalls (need refactoring)

This commit is contained in:
LuckyLaszlo
2022-12-01 15:55:40 +01:00
parent 6e572f2fb5
commit c8c3111ed4
11 changed files with 132 additions and 45 deletions

View File

@@ -1,5 +1,6 @@
import * as c from "../constants.js" import * as c from "../constants.js"
import * as en from "../../shared_js/enums.js"
import { Vector, VectorInteger } from "../../shared_js/class/Vector.js"; import { Vector, VectorInteger } from "../../shared_js/class/Vector.js";
import { TextElem, TextNumericValue } from "./Text.js"; import { TextElem, TextNumericValue } from "./Text.js";
import { RectangleClient, RacketClient, BallClient, Line } from "./RectangleClient.js"; import { RectangleClient, RacketClient, BallClient, Line } from "./RectangleClient.js";
@@ -11,14 +12,21 @@ class GameComponentsExtensionForClient extends GameComponents {
playerLeft: RacketClient; playerLeft: RacketClient;
playerRight: RacketClient; playerRight: RacketClient;
ball: BallClient; 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.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.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.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.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"); 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_mid: RectangleClient;
h_grid_u1: RectangleClient; h_grid_u1: RectangleClient;
h_grid_d1: RectangleClient; h_grid_d1: RectangleClient;
constructor(ctx: CanvasRenderingContext2D) constructor(options: en.MatchOptions, ctx: CanvasRenderingContext2D)
{ {
super(ctx); super(options, ctx);
let pos = new VectorInteger; let pos = new VectorInteger;
// Scores // Scores
pos.assign(c.w_mid-c.scoreSize*1.6, c.scoreSize*1.5); pos.assign(c.w_mid-c.scoreSize*1.6, c.scoreSize*1.5);

View File

@@ -20,4 +20,4 @@ export const soundPongVolume = 0.3; // between 0 and 1
// TODO: replace by a selector on the website // TODO: replace by a selector on the website
import * as en from "../shared_js/enums.js" import * as en from "../shared_js/enums.js"
export const optionsPLACEHOLDER = en.MatchOptions.noOption; export const optionsPLACEHOLDER = en.MatchOptions.multiBalls;

View File

@@ -1,5 +1,7 @@
import { pong, gc } from "./global.js" 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"; import { gridDisplay } from "./handleInput.js";
function drawLoop() function drawLoop()
@@ -24,6 +26,11 @@ function drawDynamic()
gc.playerLeft.update(); gc.playerLeft.update();
gc.playerRight.update(); gc.playerRight.update();
gc.ball.update(); gc.ball.update();
if (c.optionsPLACEHOLDER & en.MatchOptions.multiBalls)
{ // ALTERNATIVE POSSIBLE, Array of balls
gc.ball2.update();
gc.ball3.update();
}
} }
function drawStatic() function drawStatic()

View File

@@ -1,5 +1,6 @@
import * as c from "./constants.js"; import * as c from "./constants.js";
import * as en from "../shared_js/enums.js"
import { gc, clientInfo } from "./global.js"; import { gc, clientInfo } from "./global.js";
let actual_time: number = Date.now(); let actual_time: number = Date.now();
@@ -23,6 +24,11 @@ function gameLoop()
// client prediction // client prediction
gc.ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); 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) function opponentInterpolation(delta: number)

View File

@@ -16,7 +16,7 @@ import {socket} from "./ws.js"; socket; // no-op, just for loading
*/ */
export const pong = new GameArea(); export const pong = new GameArea();
export const gc = new GameComponentsClient(pong.ctx); export const gc = new GameComponentsClient(c.optionsPLACEHOLDER, pong.ctx);
function matchmaking() function matchmaking()
{ {

View File

@@ -94,6 +94,17 @@ function gameUpdate(data: ev.EventGameUpdate)
gc.ball.dir.assign(data.ball.dirX, data.ball.dirY); gc.ball.dir.assign(data.ball.dirX, data.ball.dirY);
gc.ball.speed = data.ball.speed; 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 const predictionPos = new VectorInteger(clientInfo.racket.pos.x, clientInfo.racket.pos.y); // debug
if (clientInfo.side === en.PlayerSide.left) { if (clientInfo.side === en.PlayerSide.left) {

View File

@@ -1,14 +1,14 @@
import * as c from "../constants.js" import * as c from "../constants.js"
import * as en from "../../shared_js/enums.js"
import { GameComponents } from "../../shared_js/class/GameComponents.js"; import { GameComponents } from "../../shared_js/class/GameComponents.js";
class GameComponentsServer extends GameComponents { class GameComponentsServer extends GameComponents {
scoreLeft: number = 0; scoreLeft: number = 0;
scoreRight: number = 0; scoreRight: number = 0;
ballInPlay: boolean = false; constructor(options: en.MatchOptions)
constructor()
{ {
super(); super(options);
} }
} }

View File

@@ -6,6 +6,7 @@ import { ClientPlayer } from "./Client";
import { GameComponentsServer } from "./GameComponentsServer.js"; import { GameComponentsServer } from "./GameComponentsServer.js";
import { clientInputListener } from "../wsServer.js"; import { clientInputListener } from "../wsServer.js";
import { random } from "../utils.js"; import { random } from "../utils.js";
import { Ball } from "../../shared_js/class/Rectangle.js";
/* /*
Arg "s: GameSession" replace "this: GameSession" for use with setTimeout(), Arg "s: GameSession" replace "this: GameSession" for use with setTimeout(),
@@ -27,11 +28,17 @@ class GameSession {
constructor(id: string, matchOptions: en.MatchOptions) { constructor(id: string, matchOptions: en.MatchOptions) {
this.id = id; this.id = id;
this.matchOptions = matchOptions; this.matchOptions = matchOptions;
this.components = new GameComponentsServer(); this.components = new GameComponentsServer(this.matchOptions);
} }
start() { start() {
setTimeout(this.resume, c.matchStartDelay, this); 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) { resume(s: GameSession) {
s.playersMap.forEach( (client) => { s.playersMap.forEach( (client) => {
@@ -84,53 +91,74 @@ class GameSession {
}); */ }); */
const gc = s.components; 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]); ball.moveAndBounce(delta, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]);
if (gc.ball.pos.x > c.w) { if (ball.pos.x > c.w) {
gc.ballInPlay = false; ball.ballInPlay = false;
++gc.scoreLeft; ++gc.scoreLeft;
s.playersMap.forEach( (client) => { this.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); 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) { else if (ball.pos.x < 0 - ball.width) {
gc.ballInPlay = false; ball.ballInPlay = false;
++gc.scoreRight; ++gc.scoreRight;
s.playersMap.forEach( (client) => { this.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); 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) { private _clientsUpdate(s: GameSession) {
const gc = s.components; const gc = s.components;
const update: ev.EventGameUpdate = { const update = new ev.EventGameUpdate();
type: en.EventTypes.gameUpdate, update.playerLeft.y = gc.playerLeft.pos.y;
playerLeft: { update.playerRight.y = gc.playerRight.pos.y;
y: gc.playerLeft.pos.y
}, update.ball.x = gc.ball.pos.x;
playerRight: { update.ball.y = gc.ball.pos.y;
y: gc.playerRight.pos.y update.ball.dirX = gc.ball.dir.x;
}, update.ball.dirY = gc.ball.dir.y;
ball:{ update.ball.speed = gc.ball.speed;
x: gc.ball.pos.x, if (s.matchOptions & en.MatchOptions.multiBalls)
y: gc.ball.pos.y, { // ALTERNATIVE POSSIBLE, Array of balls
dirX: gc.ball.dir.x, update.ball2.x = gc.ball2.pos.x;
dirY: gc.ball.dir.y, update.ball2.y = gc.ball2.pos.y;
speed: gc.ball.speed update.ball2.dirX = gc.ball2.dir.x;
}, update.ball2.dirY = gc.ball2.dir.y;
lastInputId: 0 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) => { s.playersMap.forEach( (client) => {
update.lastInputId = client.lastInputId; update.lastInputId = client.lastInputId;
client.socket.send(JSON.stringify(update)); client.socket.send(JSON.stringify(update));
}); });
} }
private _newRound(s: GameSession) { private _newRound(s: GameSession, ball: Ball) {
const gc = s.components; const gc = s.components;
// https://fr.wikipedia.org/wiki/Tennis_de_table#Nombre_de_manches // https://fr.wikipedia.org/wiki/Tennis_de_table#Nombre_de_manches
if (gc.scoreLeft >= 11 || gc.scoreRight >= 11) if (gc.scoreLeft >= 11 || gc.scoreRight >= 11)
@@ -142,10 +170,10 @@ class GameSession {
return; return;
} }
} }
gc.ball.pos.x = c.w_mid; ball.pos.x = c.w_mid;
gc.ball.pos.y = Math.floor((c.h * 0.1) + random() * (c.h * 0.8)); ball.pos.y = Math.floor((c.h * 0.1) + random() * (c.h * 0.8));
gc.ball.speed = gc.ball.baseSpeed; ball.speed = ball.baseSpeed;
gc.ballInPlay = true; ball.ballInPlay = true;
} }
private _matchEnd(s: GameSession) { private _matchEnd(s: GameSession) {
const gc = s.components; const gc = s.components;

View File

@@ -39,6 +39,20 @@ class EventGameUpdate extends ServerEvent {
dirY: 0, dirY: 0,
speed: 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; lastInputId = 0;
constructor() { // TODO: constructor that take GameComponentsServer maybe ? constructor() { // TODO: constructor that take GameComponentsServer maybe ?
super(en.EventTypes.gameUpdate); super(en.EventTypes.gameUpdate);

View File

@@ -1,5 +1,6 @@
import * as c from "../constants.js" import * as c from "../constants.js"
import * as en from "../../shared_js/enums.js"
import { VectorInteger } from "./Vector.js"; import { VectorInteger } from "./Vector.js";
import { Rectangle, Racket, Ball } from "./Rectangle.js"; import { Rectangle, Racket, Ball } from "./Rectangle.js";
@@ -9,7 +10,9 @@ class GameComponents {
playerLeft: Racket; playerLeft: Racket;
playerRight: Racket; playerRight: Racket;
ball: Ball; ball: Ball;
constructor() ball2?: Ball;
ball3?: Ball;
constructor(options: en.MatchOptions)
{ {
let pos = new VectorInteger; let pos = new VectorInteger;
@@ -26,6 +29,15 @@ class GameComponents {
pos.assign(-c.ballSize, -c.ballSize); // ball out =) pos.assign(-c.ballSize, -c.ballSize); // ball out =)
this.ball = new Ball(pos, c.ballSize, c.ballSpeed, c.ballSpeedIncrease); this.ball = new Ball(pos, c.ballSize, c.ballSpeed, c.ballSpeedIncrease);
this.ball.dir.assign(-0.8, +0.2); 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);
}
} }
} }

View File

@@ -74,6 +74,7 @@ class Racket extends MovingRectangle {
class Ball extends MovingRectangle { class Ball extends MovingRectangle {
readonly speedIncrease: number; readonly speedIncrease: number;
ballInPlay: boolean = false;
constructor(pos: VectorInteger, size: number, baseSpeed: number, speedIncrease: number) { constructor(pos: VectorInteger, size: number, baseSpeed: number, speedIncrease: number) {
super(pos, size, size, baseSpeed); super(pos, size, size, baseSpeed);
this.speedIncrease = speedIncrease; this.speedIncrease = speedIncrease;