game: add: class: point and segment, add: type docstring

This commit is contained in:
2024-01-21 00:33:30 +01:00
parent 6f8768e149
commit 8da7e09af7
19 changed files with 478 additions and 125 deletions

View File

@ -1,22 +1,45 @@
import { Game } from "./Game.js";
import { Point } from "./Point.js";
class Ball class Ball
{ {
/**
*
* @param {Game} game
* @param {Number} position_x
* @param {Number} position_y
* @param {Number} velocity_x
* @param {Number} velocity_y
*/
constructor(game, position_x, position_y, velocity_x, velocity_y) constructor(game, position_x, position_y, velocity_x, velocity_y)
{ {
/**
* @type {Game}
*/
this.game = game; this.game = game;
/**
* @type {Number}
*/
this.position_x = position_x; this.position_x = position_x;
/**
* @type {Number}
*/
this.position_y = position_y; this.position_y = position_y;
/**
* @type {Number}
*/
this.velocity_x = velocity_x; this.velocity_x = velocity_x;
/**
* @type {Number}
*/
this.velocity_y = velocity_y; this.velocity_y = velocity_y;
} }
_collision(old_pos_x, old_pos_y, new_pos_x, new_pos_y) /**
{ *
* @param {CanvasRenderingContext2D} ctx
return 0; */
}
draw(ctx) draw(ctx)
{ {
ctx.rect(this.position_x, this.position_y, this.game.config.ball_size, this.game.config.ball_size); ctx.rect(this.position_x, this.position_y, this.game.config.ball_size, this.game.config.ball_size);
@ -24,8 +47,14 @@ class Ball
render() render()
{ {
new_pos_x = this.position_x + this.velocity_x * this.game.time.deltaTime(); /**
new_pos_y = this.position_y + this.velocity_y * this.game.time.deltaTime(); * @type {Number}
*/
let new_pos_x = this.position_x + this.velocity_x * this.game.time.deltaTime();
/**
* @type {Number}
*/
let new_pos_y = position_y + this.velocity_y * this.game.time.deltaTime();
if (this._collision(this.position_x, this.position_y, new_pos_x, new_pos_y)) if (this._collision(this.position_x, this.position_y, new_pos_x, new_pos_y))
{ {

View File

@ -1,7 +1,6 @@
import { sleep } from "../../utils/sleep.js"; import { sleep } from "../../utils/sleep.js";
import { Ball } from "./Ball.js"; import { Ball } from "./Ball.js";
import { GameConfig } from "./GameConfig.js" import { GameConfig } from "./GameConfig.js"
import { MyPlayer } from "./MyPlayer.js";
import { Player } from "./Player.js"; import { Player } from "./Player.js";
import { Time } from "./Time.js"; import { Time } from "./Time.js";
import { Wall } from "./Wall.js"; import { Wall } from "./Wall.js";
@ -20,6 +19,10 @@ class Game
this.id = id; this.id = id;
} }
/**
*
* @returns {Number}
*/
async init() async init()
{ {
let response = await this.client._get(`/api/games/${this.id}`); let response = await this.client._get(`/api/games/${this.id}`);
@ -35,7 +38,7 @@ class Game
this.finished = response_data.finished; this.finished = response_data.finished;
this.winner_id = this.finished ? response_data.winner_id : undefined; this.winner_id = this.finished ? response_data.winner_id : undefined;
if (this.finished === true || this.started === false) if (this.finished === true)
return 0; return 0;
this.config = new GameConfig(this.client); this.config = new GameConfig(this.client);
@ -51,6 +54,10 @@ class Game
return 0; return 0;
} }
/**
*
* @param {CanvasRenderingContext2D} ctx
*/
draw_sides(ctx) draw_sides(ctx)
{ {
this.walls.forEach(wall => { this.walls.forEach(wall => {
@ -61,6 +68,10 @@ class Game
}); });
} }
/**
*
* @param {CanvasRenderingContext2D} ctx
*/
draw(ctx) draw(ctx)
{ {
ctx.clearRect(0, 0, this.config.size_x, this.config.size_y); ctx.clearRect(0, 0, this.config.size_x, this.config.size_y);
@ -91,6 +102,7 @@ class Game
_receive_player_join(player_data) _receive_player_join(player_data)
{ {
console.log(player_data)
let index = this.players.indexOf((player) => player.id === player_data.user_id); let index = this.players.indexOf((player) => player.id === player_data.user_id);
this.players[index].is_connected = true; this.players[index].is_connected = true;
@ -126,7 +138,6 @@ class Game
_receive(data) _receive(data)
{ {
console.log(data)
if (data.detail === "update_paddle") if (data.detail === "update_paddle")
this._receive_update_paddle(data); this._receive_update_paddle(data);
else if (data.detail === "update_ball") else if (data.detail === "update_ball")
@ -147,26 +158,13 @@ class Game
this.walls = []; this.walls = [];
const walls_data = data.walls; const walls_data = data.walls;
walls_data.forEach((wall_data) => { walls_data.forEach((wall_data) => {
this.walls.push(new Wall(wall_data.rail_start_x, this.walls.push(new Wall().from_json(wall_data));
wall_data.rail_start_y,
wall_data.rail_stop_x,
wall_data.rail_stop_y));
}); });
this.players = [] this.players = []
const players_data = data.players; const players_data = data.players;
players_data.forEach((player_data) => { players_data.forEach((player_data) => {
this.players.push(new Player(player_data.user_id, this.players.push(new Player(this).from_json(player_data));
this,
player_data.rail_start_x,
player_data.rail_start_y,
player_data.rail_stop_x,
player_data.rail_stop_y,
player_data.nb_goal,
player_data.position.position,
player_data.is_connected,
));
}); });
this._inited = true; this._inited = true;
@ -180,7 +178,7 @@ class Game
async join() async join()
{ {
if (this.started !== true || this.finished === true) if (this.finished === true)
{ {
console.error("The Game is not currently ongoing."); console.error("The Game is not currently ongoing.");
return; return;

View File

@ -20,21 +20,56 @@ class GameConfig
let response_data = await response.json(); let response_data = await response.json();
/**
* @type {Number}
*/
this.size_x = response_data.MAP_SIZE_X; this.size_x = response_data.MAP_SIZE_X;
/**
* @type {Number}
*/
this.size_y = response_data.MAP_SIZE_Y; this.size_y = response_data.MAP_SIZE_Y;
/**
* @type {Number}
*/
this.center_x = this.size_x / 2; this.center_x = this.size_x / 2;
/**
* @type {Number}
*/
this.center_y = this.size_y / 2; this.center_y = this.size_y / 2;
/**
* @type {Number}
*/
this.paddle_ratio = response_data.PADDLE_RATIO; this.paddle_ratio = response_data.PADDLE_RATIO;
/**
* @type {Number}
*/
this.paddle_speed_per_second_max = response_data.PADDLE_SPEED_PER_SECOND_MAX; this.paddle_speed_per_second_max = response_data.PADDLE_SPEED_PER_SECOND_MAX;
/**
* @type {Number}
*/
this.wall_ratio = response_data.WALL_RATIO; this.wall_ratio = response_data.WALL_RATIO;
/**
* @type {Number}
*/
this.ball_speed_inc = response_data.BALL_SPEED_INC; this.ball_speed_inc = response_data.BALL_SPEED_INC;
/**
* @type {Number}
*/
this.ball_speed_start = response_data.BALL_SPEED_START; this.ball_speed_start = response_data.BALL_SPEED_START;
/**
* @type {Number}
*/
this.ball_size = response_data.BALL_SIZE; this.ball_size = response_data.BALL_SIZE;
/**
* @type {Number}
*/
this.ball_spawn_x = this.center_x; this.ball_spawn_x = this.center_x;
/**
* @type {Number}
*/
this.ball_spawn_y = this.center_y; this.ball_spawn_y = this.center_y;
return 0; return 0;

View File

@ -1,17 +1,35 @@
import { Player } from "./Player.js"; import { Player } from "./Player.js";
import { Client } from "../client.js"
import { Game } from "./Game.js";
import { Segment } from "./Segment.js";
class MyPlayer extends Player class MyPlayer extends Player
{ {
constructor(client, game, rail_start_x, rail_start_y, rail_stop_x, rail_stop_y, nb_goal, positon) /**
*
* @param {Client} client
* @param {Game} game
* @param {Segment} rail
* @param {Number} nb_goal
* @param {Number} position
*/
constructor(client, game, rail, nb_goal, position)
{ {
super(client.me.id, game, rail_start_x, rail_start_y, rail_stop_x, rail_stop_y, nb_goal, positon, true); super(game, client.me.id, rail, nb_goal, position, true);
/**
* @type {Client}
*/
this.client = client; this.client = client;
} }
/**
*
* @param {[string]} keys_pressed
* @returns
*/
update_paddle(keys_pressed) update_paddle(keys_pressed)
{ {
let new_pos = this.positon; let new_pos = this.position;
if (keys_pressed.includes("s")) if (keys_pressed.includes("s"))
new_pos -= this.game.config.paddle_speed_per_second_max * this.game.time.deltaTimeSecond() * 1.0; new_pos -= this.game.config.paddle_speed_per_second_max * this.game.time.deltaTimeSecond() * 1.0;
@ -20,14 +38,19 @@ class MyPlayer extends Player
new_pos = Math.max(0 + this.game.config.paddle_ratio / 2, new_pos); new_pos = Math.max(0 + this.game.config.paddle_ratio / 2, new_pos);
new_pos = Math.min(1 - this.game.config.paddle_ratio / 2, new_pos); new_pos = Math.min(1 - this.game.config.paddle_ratio / 2, new_pos);
if (this.positon === new_pos) if (this.position === new_pos)
return; return;
this.positon = new_pos; this.position = new_pos;
this.game._send_paddle_position(this.positon, this.game.time._current_frame); this.game._send_paddle_position(this.position, this.game.time._current_frame);
} }
/**
*
* @param {Number} new_position
* @param {Number} time
*/
update_pos(new_position, time) update_pos(new_position, time)
{ {
let position_verified = new_position; let position_verified = new_position;
@ -36,14 +59,14 @@ class MyPlayer extends Player
let sign = this - new_position >= 0 ? 1 : -1; let sign = this - new_position >= 0 ? 1 : -1;
let distance = Math.abs(this.positon - new_position); let distance = Math.abs(this.position - new_position);
let distance_max = time_diff * this.game.config.paddle_speed_per_second_max; let distance_max = time_diff * this.game.config.paddle_speed_per_second_max;
if (distance > distance_max) if (distance > distance_max)
position_verified = distance_max * sign; position_verified = distance_max * sign;
this.positon = position_verified; this.position = position_verified;
} }
} }

View File

@ -1,52 +1,153 @@
import { Game } from "./Game.js";
import { Point } from "./Point.js";
import { Segment } from "./Segment.js";
class Player class Player
{ {
constructor(id, game, rail_start_x, rail_start_y, rail_stop_x, rail_stop_y, nb_goal, positon, is_connected) /**
*
* @param {Number} id
* @param {Game} game
* @param {Segment} rail
* @param {Number} nb_goal
* @param {Number} position
* @param {Boolean} is_connected
*/
constructor(game, id, rail, nb_goal, position, is_connected)
{ {
this.is_connected = is_connected; /**
this.id = id; * @type {Game}
this.positon = positon; */
this.nb_goal = nb_goal;
this.game = game; this.game = game;
this.rail_start_x = rail_start_x; /**
this.rail_start_y = rail_start_y; * @type {Boolean}
this.rail_stop_x = rail_stop_x; */
this.rail_stop_y = rail_stop_y; this.is_connected = is_connected;
this.rail_size = Math.abs(this.rail_stop_x - this.rail_start_x) + Math.abs(this.rail_stop_y - this.rail_start_y) /**
* @type {Number}
*/
this.id = id;
/**
* @type {Number}
*/
this.position = position;
/**
* @type {Number}
*/
this.nb_goal = nb_goal;
/**
* @type {Segment}
*/
this.rail = rail === undefined ? new Segment() : rail;
/**
* @type {Number}
*/
this.rail_size = Math.abs(this.rail.stop.x - this.rail.start.x) + Math.abs(this.rail.stop.y - this.rail.start.y);
/**
* @type {Number}
*/
this.paddle_size = this.rail_size * this.game.config.paddle_ratio; this.paddle_size = this.rail_size * this.game.config.paddle_ratio;
/**
* @type {Number}
*/
this.diff_x = this.rail.stop.x - this.rail.start.x;
this.diff_x = this.rail_stop_x - this.rail_start_x, /**
this.diff_y = this.rail_stop_y - this.rail_start_y; * @type {Number}
*/
this.diff_y = this.rail.stop.y - this.rail.start.y;
} }
/**
*
* @param {Number} new_position
*/
update_pos(new_position, time) update_pos(new_position, time)
{ {
this.positon = new_position; this.position = new_position;
} }
/**
* @param {CanvasRenderingContext2D} ctx
*/
draw(ctx) draw(ctx)
{ {
if (this.is_connected === false) if (this.is_connected === false)
{ {
ctx.moveTo(this.rail_start_x, this.rail_start_y); ctx.moveTo(this.rail.start.x, this.rail.start.y);
ctx.lineTo(this.rail_stop_x, this.rail_stop_y); ctx.lineTo(this.rail.stop.x, this.rail.stop.y);
return; return;
} }
let paddle_pos_x = this.rail_start_x + this.diff_x * this.positon, let paddle_pos = new Point(this.rail.start.x + this.diff_x * this.position,
paddle_pos_y = this.rail_start_y + this.diff_y * this.positon; this.rail.start.y + this.diff_y * this.position);
let start_x = paddle_pos_x - (this.diff_x * (this.paddle_size / 2 / this.rail_size)), let start_x = paddle_pos.x - (this.diff_x * (this.paddle_size / 2 / this.rail_size)),
start_y = paddle_pos_y - (this.diff_y * (this.paddle_size / 2 / this.rail_size)), start_y = paddle_pos.y - (this.diff_y * (this.paddle_size / 2 / this.rail_size)),
stop_x = paddle_pos_x + (this.diff_x * (this.paddle_size / 2 / this.rail_size)), stop_x = paddle_pos.x + (this.diff_x * (this.paddle_size / 2 / this.rail_size)),
stop_y = paddle_pos_y + (this.diff_y * (this.paddle_size / 2 / this.rail_size)); stop_y = paddle_pos.y + (this.diff_y * (this.paddle_size / 2 / this.rail_size));
ctx.moveTo(start_x, start_y); ctx.moveTo(start_x, start_y);
ctx.lineTo(stop_x, stop_y); ctx.lineTo(stop_x, stop_y);
} }
from_json(data)
{
/**
* @type {Boolean}
*/
this.is_connected = data.is_connected;
/**
* @type {Number}
*/
this.id = data.user_id;
/**
* @type {Number}
*/
this.position = data.position.position ;
/**
* @type {Number}
*/
this.nb_goal = data.nb_goal;
/**
* @type {Segment}
*/
this.rail = this.rail.from_json(data.rail);
/**
* @type {Number}
*/
this.rail_size = Math.abs(this.rail.stop.x - this.rail.start.x) + Math.abs(this.rail.stop.y - this.rail.start.y);
/**
* @type {Number}
*/
this.paddle_size = this.rail_size * this.game.config.paddle_ratio;
/**
* @type {Number}
*/
this.diff_x = this.rail.stop.x - this.rail.start.x;
/**
* @type {Number}
*/
this.diff_y = this.rail.stop.y - this.rail.start.y;
return this
}
} }
export { Player } export { Player }

View File

@ -0,0 +1,30 @@
class Point
{
/**
* @param {Number} x
* @param {Number} y
*/
constructor(x, y)
{
/**
* @type {Number}
*/
this.x = x;
/**
* @type {Number}
*/
this.y = y;
}
from_json(data)
{
this.x = data.x
this.y = data.y
return this
}
}
export { Point }

View File

@ -0,0 +1,33 @@
import { Point } from "./Point.js"
class Segment
{
/**
* @param {Point} start
* @param {Point} stop
*/
constructor(start, stop)
{
this.start = start === undefined ? new Point() : start;
this.stop = stop === undefined ? new Point() : stop;
}
/**
* @param {CanvasRenderingContext2D} ctx
*/
draw(ctx)
{
ctx.moveTo(this.start.x, this.start.y);
ctx.lineTo(this.stop.x, this.stop.y);
}
from_json(data)
{
this.start = this.start.from_json(data.start);
this.stop = this.stop.from_json(data.stop);
return this;
}
}
export { Segment }

View File

@ -4,7 +4,14 @@ class Time
{ {
constructor() constructor()
{ {
/**
* @type {Number}
*/
this._last_frame = undefined; this._last_frame = undefined;
/**
* @type {Number}
*/
this._current_frame = undefined; this._current_frame = undefined;
} }

View File

@ -1,19 +1,28 @@
import { Segment } from "./Segment.js";
class Wall class Wall
{ {
constructor (rail_start_x, rail_start_y, rail_stop_x, rail_stop_y) /**
* @param {Segment} start
*/
constructor (rail)
{ {
this.rail_start_x = rail_start_x; /**
this.rail_start_y = rail_start_y; * @type {Segment}
this.rail_stop_x = rail_stop_x; */
this.rail_stop_y = rail_stop_y; this.rail = rail === undefined ? new Segment() : rail;
} }
draw(ctx) draw(ctx)
{ {
ctx.moveTo(this.rail_start_x, this.rail_start_y); this.rail.draw(ctx);
ctx.lineTo(this.rail_stop_x, this.rail_stop_y); }
from_json(data)
{
this.rail = this.rail.from_json(data.rail)
return this
} }
} }

View File

@ -1,9 +1,7 @@
import { client } from "../index.js"; import { client } from "../index.js";
import { Game } from "../api/game/Game.js"; import { Game } from "../api/game/Game.js";
import AbstractView from "./abstracts/AbstractView.js"; import AbstractView from "./abstracts/AbstractView.js";
import { Time } from "../api/game/Time.js";
import { MyPlayer } from "../api/game/MyPlayer.js"; import { MyPlayer } from "../api/game/MyPlayer.js";
import { Ball } from "../api/game/Ball.js";
export default class extends AbstractView export default class extends AbstractView
{ {
@ -35,6 +33,9 @@ export default class extends AbstractView
if (canva === null) if (canva === null)
return 1; return 1;
/**
* @type {CanvasRenderingContext2D}
*/
let ctx = canva.getContext('2d'); let ctx = canva.getContext('2d');
ctx.beginPath(); ctx.beginPath();
@ -71,7 +72,7 @@ export default class extends AbstractView
document.removeEventListener('keyup', this.keyStretchHandler); document.removeEventListener('keyup', this.keyStretchHandler);
} }
async start_game() async join_game()
{ {
await this.game.join() await this.game.join()
@ -89,16 +90,13 @@ export default class extends AbstractView
let my_player = this.game.players[index]; let my_player = this.game.players[index];
this.my_player = new MyPlayer(client, this.my_player = new MyPlayer(client,
this.game, this.game,
my_player.rail_start_x, my_player.rail,
my_player.rail_start_y, my_player.nb_gool,
my_player.rail_stop_x, my_player.position,
my_player.rail_stop_y,
my_player.nb_goal,
my_player.positon,
); );
this.game.players[index] = this.my_player; this.game.players[index] = this.my_player;
} }
this.register_key() this.register_key()
this.render_game(); this.render_game();
@ -108,8 +106,8 @@ export default class extends AbstractView
{ {
document.getElementById("game-state").innerText = this.game.state; document.getElementById("game-state").innerText = this.game.state;
if (this.game.started === true && this.game.finished === false) if (this.game.finished === false)
await this.start_game(); await this.join_game();
} }
async postInit() async postInit()
@ -124,7 +122,7 @@ export default class extends AbstractView
async leavePage() async leavePage()
{ {
if (this.game.started === true && this.game.finished === false) if (this.game.finished === false)
{ {
this.game.leave(); this.game.leave();
this.game = undefined; this.game = undefined;

View File

@ -23,6 +23,7 @@ class GameWebSocket(WebsocketConsumer):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.channel_name = "games" self.channel_name = "games"
self.group_name = "games" self.group_name = "games"
self.member = None
def connect(self): def connect(self):
@ -30,20 +31,23 @@ class GameWebSocket(WebsocketConsumer):
if (self.user.pk is None): if (self.user.pk is None):
self.user.pk = 0 self.user.pk = 0
self.channel_layer.group_add(self.group_name, self.channel_name) self.accept()
self.game_id = int(self.scope['url_route']['kwargs']['game_id']) self.game_id = int(self.scope['url_route']['kwargs']['game_id'])
self.game: Game = game_manager.get(self.game_id) self.game: Game = game_manager.get(self.game_id)
if (self.game is None): if (self.game is None):
self.send("Game not found.") self.send(text_data=json.dumps({"detail": "Game not found"}))
self.disconnect(1017) self.disconnect(1404)
return
self.member: Player | Spectator = self.game.join(self.user.pk, self) self.member: Player | Spectator = self.game.join(self.user.pk, self)
def disconnect(self, code): def disconnect(self, code):
self.member.disconnect() if (self.member is not None):
self.member.disconnect()
super().disconnect(code)
def receive(self, text_data: str = None, bytes_data: bytes = None): def receive(self, text_data: str = None, bytes_data: bytes = None):

View File

@ -7,10 +7,12 @@ class Ball:
self.postion_y: float = config.BALL_SPAWN_POS_Y self.postion_y: float = config.BALL_SPAWN_POS_Y
self.velocity_x: float = config.BALL_SPEED_START self.velocity_x: float = config.BALL_SPEED_START
self.velocity_y: float = config.BALL_SPEED_START self.velocity_y: float = config.BALL_SPEED_START
self.size: float = config.BALL_SIZE
def to_dict(self): def to_dict(self):
data: dict = { data: dict = {
"size": self.size,
"position_x": self.postion_x, "position_x": self.postion_x,
"position_y": self.postion_y, "position_y": self.postion_y,
"velocity_x": self.velocity_x, "velocity_x": self.velocity_x,

View File

@ -9,6 +9,8 @@ from .Ball import Ball
from .Player import Player from .Player import Player
from .Spectator import Spectator from .Spectator import Spectator
from .Wall import Wall from .Wall import Wall
from .Point import Point
from .Segment import Segment
import math import math
@ -34,30 +36,34 @@ class Game(AbstractRoom):
players_id: list[int] = self.model.get_players_id() players_id: list[int] = self.model.get_players_id()
self.nb_sides = len(players_id) * 2 nb_sides = len(players_id) * 2
self.polygon: list[tuple[float, float]] = [] polygon: list[Point] = []
for i in range(self.nb_sides): for i in range(nb_sides):
angle: float = (i * 2 * math.pi / self.nb_sides) + (math.pi * 3 / 4) angle: float = (i * 2 * math.pi / nb_sides) + (math.pi * 3 / 4)
x: float = config.MAP_CENTER_X + radius * math.cos(angle) x: float = config.MAP_CENTER_X + radius * math.cos(angle)
y: float = config.MAP_CENTER_Y + radius * math.sin(angle) y: float = config.MAP_CENTER_Y + radius * math.sin(angle)
self.polygon.append((x, y)) polygon.append(Point(x, y))
segments: list[Point] = []
for i in range(nb_sides):
segments.append(Segment(polygon[i], polygon[(i + 1) % nb_sides]))
self.players: list[Player] = [] self.players: list[Player] = []
for i, player_id in enumerate(players_id): for i, player_id in enumerate(players_id):
player = Player(self, player_id, None, *self.polygon[i * 2], *self.polygon[(i * 2 + 1) % self.nb_sides]) player = Player(self, player_id, None, segments[i * 2])
self.players.append(player) self.players.append(player)
self.spectators: list[Spectator] = [] self.spectators: list[Spectator] = []
self.walls: list[Wall] = [] self.walls: list[Wall] = []
for i in range(1, self.nb_sides, 2): for i in range(1, nb_sides, 2):
self.walls.append(Wall(*self.polygon[i], *self.polygon[(i + 1) % self.nb_sides])) self.walls.append(Wall(segments[i]))
self._updated_players: list[Player] = [] self._updated_players: list[Player] = []
@ -86,12 +92,11 @@ class Game(AbstractRoom):
def get_player_by_user_id(self, user_id: int) -> Player: def get_player_by_user_id(self, user_id: int) -> Player:
for player in self.players: for player in self.players:
player: Player
if (player.user_id == user_id): if (player.user_id == user_id):
return player return player
return None return None
def _send_game_data(self, member: AbstractRoomMember): def _send_game_data(self, member: Spectator | Player):
member.send("init_game", self.to_dict()) member.send("init_game", self.to_dict())
def everbody_is_here(self): def everbody_is_here(self):
@ -109,20 +114,24 @@ class Game(AbstractRoom):
if (player.is_connected()): if (player.is_connected()):
player.disconnect(1001) player.disconnect(1001)
player.connect(socket)
player.socket = socket
if (self.everbody_is_here()): if (self.everbody_is_here()):
print("chie moi dessu")
print("start") print("start")
self.start() self.start()
self._update_player(player)
return player return player
def _update_player(self, player: Player): def _update_player(self, player: Player):
self._updated_players.append(player) self._updated_players.append(player)
def _player_leave(self, player: Player): def _player_leave(self, player: Player):
self._updated_players.append(player) print(player.socket)
self._update_player(player)
def _spectator_join(self, user_id: int, socket: WebsocketConsumer): def _spectator_join(self, user_id: int, socket: WebsocketConsumer):
@ -130,8 +139,6 @@ class Game(AbstractRoom):
self.spectators.append(spectator) self.spectators.append(spectator)
spectator.accept()
return spectator return spectator
def _spectator_leave(self, spectator: Spectator): def _spectator_leave(self, spectator: Spectator):

View File

@ -9,7 +9,7 @@ class GameManager():
def get(self, game_id: int) -> Game: def get(self, game_id: int) -> Game:
if (not GameModel.objects.filter(pk = game_id, started = True, finished = False).exists()): if (not GameModel.objects.filter(pk = game_id, finished = False).exists()):
return None return None
for game in self._game_list: for game in self._game_list:

View File

@ -6,6 +6,8 @@ from channels.generic.websocket import WebsocketConsumer
from .Position import Position from .Position import Position
from .Spectator import Spectator from .Spectator import Spectator
from .Point import Point
from .Segment import Segment
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -15,7 +17,7 @@ if TYPE_CHECKING:
class Player(Spectator): class Player(Spectator):
def __init__(self, game: Game, user_id: int, socket: WebsocketConsumer, rail_start_x: float, rail_start_y: float, rail_stop_x: float, rail_stop_y: float) -> None: def __init__(self, game: Game, user_id: int, socket: WebsocketConsumer, rail: Segment) -> None:
super().__init__(user_id, socket, game) super().__init__(user_id, socket, game)
@ -23,10 +25,7 @@ class Player(Spectator):
self.nb_goal: int = 0 self.nb_goal: int = 0
self.rail_start_x: float = rail_start_x self.rail: Segment = rail
self.rail_start_y: float = rail_start_y
self.rail_stop_x: float = rail_stop_x
self.rail_stop_y: float = rail_stop_y
def receive(self, data: dict): def receive(self, data: dict):
@ -106,19 +105,17 @@ class Player(Spectator):
def disconnect(self, code: int = 1000): def disconnect(self, code: int = 1000):
self.socket = None self.socket = None
print("bozoman")
self.game.leave(self) self.game.leave(self)
def to_dict(self): def to_dict(self) -> dict:
data = { data = {
"user_id": self.user_id, "user_id": self.user_id,
"position": self.position.to_dict(), "position": self.position.to_dict(),
"nb_goal": self.nb_goal, "nb_goal": self.nb_goal,
"rail_start_x": self.rail_start_x, "rail": self.rail.to_dict(),
"rail_start_y": self.rail_start_y,
"rail_stop_x": self.rail_stop_x,
"rail_stop_y": self.rail_stop_y,
"is_connected": self.is_connected(), "is_connected": self.is_connected(),
} }

16
games/objects/Point.py Normal file
View File

@ -0,0 +1,16 @@
class Point:
def __init__(self, x: float, y: float) -> None:
self.x = x
self.y = y
def to_dict(self):
data: dict[str: float] = {
"x": self.x,
"y": self.y,
}
return data

17
games/objects/Segment.py Normal file
View File

@ -0,0 +1,17 @@
from .Point import Point
class Segment:
def __init__(self, start: Point, stop: Point) -> None:
self.start: Point = start
self.stop: Point = stop
def to_dict(self):
data: dict[str: dict] = {
"start": self.start.to_dict(),
"stop": self.stop.to_dict(),
}
return data

View File

@ -1,20 +1,15 @@
from .Segment import Segment
class Wall: class Wall:
def __init__(self, rail_start_x, rail_start_y, rail_stop_x, rail_stop_y) -> None: def __init__(self, rail: Segment) -> None:
self.rail_start_x = rail_start_x self.rail: Segment = rail
self.rail_start_y = rail_start_y
self.rail_stop_x = rail_stop_x
self.rail_stop_y = rail_stop_y
def to_dict(self): def to_dict(self) -> dict[str: dict]:
data = { data = {
"rail_start_x": self.rail_start_x, "rail": self.rail.to_dict(),
"rail_start_y": self.rail_start_y,
"rail_stop_x": self.rail_stop_x,
"rail_stop_y": self.rail_stop_y,
} }
return data return data

View File

@ -5,16 +5,68 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from .objects.Spectator import Spectator from .objects.Spectator import Spectator
from .objects.Player import Player from .objects.Player import Player
from .objects.Game import Game from .objects.Game import Game
from .objects.Ball import Ball
from .objects.Point import Point
from .objects.Segment import Segment
from . import config from . import config
import math
from time import sleep from time import sleep
#see the video to understand the algorithme
#https://www.youtube.com/watch?v=KOYoMYWUTEo
def determine_director_coefficient(segment: Segment):
return ((segment.start.y - segment.stop.y) / (segment.start.x - segment.stop.x))
def determine_ordinate_at_origin(point: Point, director_cofficient: float):
return point.y - point.x * director_cofficient
def determine_intersection(director_coefficient1: float, ordinate_at_origin1: float, director_coefficient2: float, ordinate_at_origin2: float):
if (director_coefficient1 == director_coefficient2):
return None
return (ordinate_at_origin1 + ordinate_at_origin2) / (director_coefficient1 + director_coefficient2)
def determine_intersections(ball: Ball, segments: list[Segment]):
intersections: list[Point] = []
for segment in segments:
# form m * x + p
m: float = determine_director_coefficient(segment)
p: float = determine_ordinate_at_origin(segment.start, m)
x: float = determine_intersection(m, p, ball.velocity_y, 0)
if (x is None):
continue
y: float = m * x + p
intersections.append(Point(x, y))
return intersections
def determine_distance_between_ball_and_wall(ball: Ball, segments: list[Segment]):
intersections: list[Point] = determine_intersections(ball, segments)
distances = list(map(math.dist, intersections))
return min(distances)
def render(ball: Ball, game: Game):
segments: list[Segment] = [player.rail for player in game.players]
print(determine_distance_between_ball_and_wall(ball))
def routine(game: Game): def routine(game: Game):
while True: while True:
for player in game._updated_players: for player in game._updated_players:
game.broadcast("update_paddle", player.to_dict(), [player]) game.broadcast("update_paddle", player.to_dict(), [player])