Skip to content

Commit

Permalink
adding documentation, normally the game and pong engin work handle pr…
Browse files Browse the repository at this point in the history
…ivate and public matchmaking, spectator feature is not done yet but partially implemented, goal are not yet register nor display
  • Loading branch information
a-boring-man committed Apr 3, 2023
1 parent a124754 commit 6ee8b81
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 53 deletions.
28 changes: 7 additions & 21 deletions back/nest_project/src/game_engine/Ball.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,38 @@ import { Vec2 } from "./math/Vec2";

export class Ball {

aspect_ratio = 16/9;
public position: Vec2;
public r;
public speed: Vec2;
acc: Vec2;
acceleration;
colision_number;
friction;
elasticity;
mass;
alive: boolean;
inv_mass;

constructor (pos: Vec2, r) {
this.position = pos;
this.speed = new Vec2(0, 0);
this.acc = new Vec2(0, 0);
this.r = r;
this.colision_number = 0;
this.acceleration = 0.001;
this.friction = 0;
this.elasticity = 1.01;
this.mass = Math.PI * r * r;
this.alive = true;
if (this.mass === 0)
this.inv_mass = 0;
else
this.inv_mass = 1 / this.mass;
if (Math.random() * 2 - 1 > 0)
this.acc.setCoordinates(0.0001, 0);
else
this.acc.setCoordinates(-0.0001, 0);
}

process_input (body: any) {
if (body === "ArrowUp")
this.acc.y = -this.acceleration;
if (body === "ArrowDown")
this.acc.y = this.acceleration;
if (body === "ArrowRight")
this.acc.x = this.acceleration;
if (body === "ArrowLeft")
this.acc.x = -this.acceleration;
}

update_self_position() {
this.speed.setCoordinates((this.speed.x + this.acc.x) * (1 - this.friction), (this.speed.y + this.acc.y) * (1 - this.friction));
this.position = this.position.add(this.speed);
this.acc.setCoordinates(0, 0);
if ((this.position.x - this.r < 0) || (this.position.x + this.r > this.aspect_ratio)) { //TODO register the goal
this.alive = false;
return;
}
}

}
41 changes: 40 additions & 1 deletion back/nest_project/src/game_engine/Wall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ export class Wall {
end: Vec2;
x_position;
y_position;
speed;
length;
up: boolean;
down: boolean;

constructor(v1: Vec2, v2: Vec2) {
this.up = false;
this.down = false;
this.speed = 3/60;
this.start = v1;
this.end = v2;
this.x_position = this.start.x;
Expand All @@ -17,6 +23,39 @@ export class Wall {
}

wallUnit() {
return (this.end.sub(this.start).normalize());
return (new Vec2(0, 1));
}

update_self_position() {
if (this.up) {
this.y_position -= this.speed;
if (this.y_position < 0) {
this.y_position = 0;
}
}
else if (this.down) {
this.y_position += this.speed;
if (this.y_position + this.length > 1) {
this.y_position = 1 - this.length;
}
}
this.start.setCoordinates(this.x_position, this.y_position);
this.end.setCoordinates(this.x_position, this.y_position + this.length);
}

process_input (body: string) {
console.log("process input : " + body);
if (body === "ArrowUp" || body === "w") {
this.up = !this.up;
if (this.up) {
this.down = false;
}
}
if (body === "ArrowDown" || body === "s") {
this.down = !this.down;
if (this.down) {
this.up = false;
}
}
}
}
115 changes: 107 additions & 8 deletions back/nest_project/src/game_engine/game_engine.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ import { Wall } from './Wall';
import { Collision } from './math/Collision';
import { Socket } from 'socket.io';

/**
* use to store info on a ball
*/
interface ballpos {
x: number,
y: number,
r: number,
}

/**
* use to share the game state
*/
interface gameState {
ballPosition: ballpos[],
paddleOne: {x: number, y: number },
Expand Down Expand Up @@ -39,23 +45,28 @@ export class GameEngineService {
this.ballz = [];
this.wallz = [];

// creating the two ball
let small_ball = new Ball(new Vec2(0.5 * this.aspect_ratio, 0.35), 0.04);
this.set_ball_random_start(small_ball);
let big_ball = new Ball(new Vec2(0.5 * this.aspect_ratio, 0.7), 0.08);
this.ballz[0] = small_ball;
this.ballz[1] = big_ball;

// creating the pl1 and pl2 paddle respectivly
this.wallz[0] = new Wall(new Vec2(0.025, 0.415), new Vec2(0.025, 0.585));
this.wallz[1] = new Wall(new Vec2(this.aspect_ratio - 0.025, 0.415), new Vec2(this.aspect_ratio - 0.025, 0.585));

// creating the wall
this.wallz[2] = new Wall(new Vec2(0, 0), new Vec2(this.aspect_ratio, 0));
this.wallz[3] = new Wall(new Vec2(0, 1), new Vec2(this.aspect_ratio, 1));

// setting the game start and stop variables
this.pl1_ready = false;
this.pl2_ready = false;
this.game_must_stop = false;

this.cooldown_start = 0;

// filling the gamestate
this.gs = { ballPosition: [ {x: this.ballz[0].position.x, y: this.ballz[0].position.y, r: this.ballz[0].r},
{x: this.ballz[1].position.x, y: this.ballz[1].position.y, r: this.ballz[1].r}],
paddleOne: { x: this.wallz[0].x_position, y: this.wallz[0].y_position },
Expand All @@ -64,31 +75,115 @@ export class GameEngineService {

}

/**
* give a random speed to a ball
* @param ball the ball to witch you want to give a random speed
*/
set_ball_random_start(ball: Ball) {
let signe = (Math.random() - 0.5) > 0 ? 1 : -1;
ball.speed = new Vec2((signe/120) * this.aspect_ratio, (Math.random() - 0.5) * Math.random()/120);
}

/**
* set who is gonna play the game
* @param player1 se
* @param player2
*/
set_player (player1: Socket, player2: Socket) {
this.pl1 = player1;
this.pl2 = player2;
}

/**
* tell the correct wall to process the input of the client
* @param client the client sendin the input
* @param key the input in string format
*/
process_input (client: Socket, key: string) {
if (client === this.pl1) {
this.wallz[0].process_input(key);
}
else {
this.wallz[1].process_input(key);
}
}

/**
* tell the game to stop
*/
stop_game() {
this.game_must_stop = true;
}

/**
* set the readyness of the playerm if both are ready then the game start
* @param player the player sendin the ready signal
* @param server use to emit to the correct room
*/
set_player_ready (player: Socket, server) {
if (player === this.pl1) {
this.pl1_ready = !this.pl1_ready;
}
else if (player === this.pl2) {
this.pl2_ready = !this.pl2_ready;
}
if (this.pl1_ready && this.pl2_ready) {
let thiss = this;
this.loop = setInterval(function() {
if (thiss.game_must_stop) {
thiss.pl1_ready = false;
thiss.pl2_ready = false;
clearInterval(thiss.loop);
}
thiss.main_loop();
server.to(thiss.pl1.id).emit('Game_Update', thiss.gs)
}, 1000/60);
}
}

main_loop() {
this.cooldown_start++; // use to time the delay between balls respawn

// check if a ball is dead
if (this.ballz[0].alive === false || this.ballz[1].alive === false) { // respawn a ball if there was a goal TODO register goal
// spwan and set the new balls
let small_ball = new Ball(new Vec2(0.5 * this.aspect_ratio, 0.35), 0.04);
this.set_ball_random_start(small_ball);
let big_ball = new Ball(new Vec2(0.5 * this.aspect_ratio, 0.7), 0.08);
this.ballz[0] = small_ball;
this.ballz[1] = big_ball;
// reset the timer
this.cooldown_start = 0;
}
if (this.cooldown_start - this.cooldown < 0) // don't do anything if on cooldown
return;

// update the paddle
this.wallz[0].update_self_position();
this.wallz[1].update_self_position();
// for each ball check the collision with each wall then with the other ball
this.ballz.forEach((ball, index) => {
// update the ball position
ball.update_self_position();

// check for ball wall collision
this.wallz.forEach((w) => {
if (Collision.coll_det_bw(ball, w)) {
Collision.penetration_resolution_bw(ball, w);
Collision.collision_resolution_bw(ball, w);
if (Collision.coll_det_bw(ball, w)) { // if collision
Collision.penetration_resolution_bw(ball, w); // then do the repositionning
Collision.collision_resolution_bw(ball, w); // and the change in speed
}
});

// check ball ball collision
for (let i = index + 1; i < this.ballz.length; i++) {
if (Collision.coll_det_bb(this.ballz[index], this.ballz[i])) {
Collision.penetration_resolution_bb(this.ballz[index], this.ballz[i]);
Collision.collision_response_bb(this.ballz[index], this.ballz[i]);
}
}
});

// update the state of the game
this.ballz.forEach((ball, index) => {
let bp: ballpos;
bp = {
Expand All @@ -99,9 +194,13 @@ export class GameEngineService {
// console.log("test", this.gs.ballPosition[index]);
this.gs.ballPosition[index] = bp;
});
}

game_init() {
console.log("creating game");
this.gs.paddleOne = {
x: this.wallz[0].x_position - 0.015,
y: this.wallz[0].y_position + this.wallz[0].length/2
};
this.gs.paddleTwo = {
x: this.wallz[1].x_position + 0.015,
y: this.wallz[1].y_position + this.wallz[1].length/2
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { GameEngineService } from 'src/game_engine/game_engine.service';
import { PongEngineService } from 'src/pong_engine/pong_engine.service';
import { OnGatewayInit } from '@nestjs/websockets';

/**
* use to send a private matchmaking request
*/
interface Private_order {
target: string,
type: string,
Expand Down Expand Up @@ -41,8 +44,8 @@ export class Game_instance {
* use to share the player login at the start of a match
*/
export class Players {
l1: string;
l2: string;
login1: string;
login2: string;
}

/**
Expand Down Expand Up @@ -100,8 +103,8 @@ export class GameUpdateCenterGateway implements OnGatewayInit, OnGatewayConnecti

// emit the Player struct to the front to display the player login
let players = new Players();
players.l1 = this.socket_login.get(player1.id);
players.l2 = this.socket_login.get(player2.id);
players.login1 = this.socket_login.get(player1.id);
players.login2 = this.socket_login.get(player2.id);
this.server.to(player1.id).emit('players', players);
this.logger.debug("a game room has been created");
}
Expand Down

0 comments on commit 6ee8b81

Please sign in to comment.