From c60d0ba08b09ccaa7e1d8104b00c0039c606e70e Mon Sep 17 00:00:00 2001 From: starnakin Date: Thu, 8 Feb 2024 12:38:56 +0100 Subject: [PATCH] game: add: goal work --- frontend/static/js/api/game/Player.js | 68 ++++++------------ frontend/static/js/api/game/Segment.js | 24 +++++++ games/objects/Ball.py | 20 ++++-- games/objects/Segment.py | 14 +++- games/routine.py | 95 ++++++++++++++++++++++---- 5 files changed, 150 insertions(+), 71 deletions(-) diff --git a/frontend/static/js/api/game/Player.js b/frontend/static/js/api/game/Player.js index 8736db1..728d0e6 100644 --- a/frontend/static/js/api/game/Player.js +++ b/frontend/static/js/api/game/Player.js @@ -43,26 +43,6 @@ class Player * @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; - - /** - * @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; } /** @@ -85,17 +65,29 @@ class Player ctx.lineTo(this.rail.stop.x, this.rail.stop.y); return; } - let paddle_pos = new Point(this.rail.start.x + this.diff_x * this.position, - this.rail.start.y + this.diff_y * this.position); + let diff_x = this.rail.stop.x - this.rail.start.x, + diff_y = this.rail.stop.y - this.rail.start.y; + + let rail_length = this.rail.len(), + paddle_length = rail_length * this.game.config.paddle_ratio; + + let paddle_center = new Point(this.rail.start.x + diff_x * this.position, + this.rail.start.y + diff_y * this.position); + + let paddle_start_x = paddle_center.x - (diff_x * (paddle_length / 2 / rail_length)), + paddle_start_y = paddle_center.y - (diff_y * (paddle_length / 2 / rail_length)), + paddle_stop_x = paddle_center.x + (diff_x * (paddle_length / 2 / rail_length)), + paddle_stop_y = paddle_center.y + (diff_y * (paddle_length / 2 / rail_length)); - 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)), - 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)); + let paddle_start = new Point(paddle_start_x, paddle_start_y), + paddle_stop = new Point (paddle_stop_x, paddle_stop_y); + + let paddle = new Segment(paddle_start, paddle_stop); + + console.log(paddle) - ctx.moveTo(start_x, start_y); - ctx.lineTo(stop_x, stop_y); + paddle.draw(ctx); } from_json(data) @@ -125,26 +117,6 @@ class Player */ 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 } } diff --git a/frontend/static/js/api/game/Segment.js b/frontend/static/js/api/game/Segment.js index 7d6fedc..5c146e8 100644 --- a/frontend/static/js/api/game/Segment.js +++ b/frontend/static/js/api/game/Segment.js @@ -8,8 +8,32 @@ class Segment */ constructor(start, stop) { + /** + * @type {Point} + */ this.start = start === undefined ? new Point() : start; + + /** + * @type {Point} + */ this.stop = stop === undefined ? new Point() : stop; + + } + + angle() + { + let x = this.start.x - this.stop.x, + y = this.start.y - this.stop.y; + + return Math.atan2(y, x); + } + + len() + { + let x = this.start.x - this.stop.x, + y = this.start.y - this.stop.y; + + return (x ** 2 + y ** 2) ** (1 / 2); } /** diff --git a/games/objects/Ball.py b/games/objects/Ball.py index bb8b8ab..4c03d0d 100644 --- a/games/objects/Ball.py +++ b/games/objects/Ball.py @@ -8,12 +8,20 @@ import math class Ball: def __init__(self) -> None: - self.size: float = config.BALL_SIZE - self.position: Point = Point(config.BALL_SPAWN_POS_X + self.size / 2, config.BALL_SPAWN_POS_Y + self.size / 2) - self.angle: float = math.pi * 0.25 - self.speed: float = config.BALL_SPEED_START + self.size: float + self.position: Point + self.angle: float + self.speed: float + + self.reset() - def to_dict(self): + def reset(self) -> None: + self.size = config.BALL_SIZE + self.position = Point(config.BALL_SPAWN_POS_X + self.size / 2, config.BALL_SPAWN_POS_Y + self.size / 2) + self.angle = math.pi * 1 + self.speed = config.BALL_SPEED_START + + def to_dict(self) -> dict: data: dict = { "size": self.size, @@ -25,4 +33,4 @@ class Ball: return data def __str__(self) -> str: - return f"Ball(size: {self.size}, speed: {self.speed}, director_coefficient: {self.director_coefficient}, ordinate_at_origin: {self.ordinate_at_origin}, position: {self.position})" \ No newline at end of file + return f"Ball(size: {self.size}, speed: {self.speed}, angle: {self.angle}, position: {self.position})" \ No newline at end of file diff --git a/games/objects/Segment.py b/games/objects/Segment.py index b785756..fc62ada 100644 --- a/games/objects/Segment.py +++ b/games/objects/Segment.py @@ -1,13 +1,23 @@ from .Point import Point +from .Vector import Vector import math + class Segment: def __init__(self, start: Point, stop: Point) -> None: self.start: Point = start self.stop: Point = stop - self.length: float = math.dist((self.start.x, self.start.y), (self.stop.x, self.stop.y)) + + def angle(self): + return math.atan2((self.start.x - self.start.y), (self.stop.x - self.stop.y)) + + def length(self): + return self.start.distance(self.stop) + + def is_on(self, C: Point): + return (self.start.distance(C) + self.stop.distance(C) == self.length()) def __repr__(self) -> str: return f"Segment(start: {self.start}, stop: {self.stop})" @@ -18,7 +28,7 @@ class Segment: def copy(self): return Segment(self.start.copy(), self.stop.copy()) - def to_dict(self): + def to_dict(self) -> dict: data: dict[str: dict] = { "start": self.start.to_dict(), diff --git a/games/routine.py b/games/routine.py index 00f70a9..2c01d08 100644 --- a/games/routine.py +++ b/games/routine.py @@ -136,19 +136,22 @@ def get_impact_point(segments: list[Segment], ball: Ball) -> dict: if (get_sign(diff_y) != get_sign(sin) and sin != 0): continue - impact.x += (ball.size / 2) * get_sign(cos) * (-1) - impact.y += (ball.size / 2) * get_sign(sin) + impact_with_padding: Point = impact.copy() - if (closest is None or impact.distance(ball.position) < closest.get("distance")): + impact_with_padding.x += (ball.size / 2) * get_sign(cos) * (-1) + impact_with_padding.y += (ball.size / 2) * get_sign(sin) + + if (closest is None or impact_with_padding.distance(ball.position) < closest.get("distance")): closest = { + "impact_with_padding": impact_with_padding, "impact": impact, "segment": segment, - "distance": impact.distance(ball.position), + "distance": impact_with_padding.distance(ball.position), } return closest -def wall_colision(ball_angle: float, wall_angle: float) -> float: +def wall_collision(ball_angle: float, wall_angle: float) -> float: ball_cos: float = math.cos(ball_angle) ball_sin: float = math.sin(ball_angle) @@ -164,21 +167,83 @@ def wall_colision(ball_angle: float, wall_angle: float) -> float: return new_angle -async def update_ball(game: Game, impact: dict): +def paddle_collision(ball: Ball, impact: Point, player: Player): + + diff_x: float = player.rail.stop.x - player.rail.start.x + diff_y: float = player.rail.stop.y - player.rail.start.y - distance: float = impact.get("distance") + paddle_center_x: float = player.rail.start.x + diff_x * player.position.position + paddle_center_y: float = player.rail.start.y + diff_y * player.position.position + + paddle_center: Point = Point(paddle_center_x, paddle_center_y) + + rail_length: float = player.rail.length() + paddle_length: float = rail_length * config.PADDLE_RATIO; + + print(paddle_length) + print(paddle_center) + + start_x: float = paddle_center.x - (diff_x * (paddle_length / 2 / rail_length)) + start_y: float = paddle_center.y - (diff_y * (paddle_length / 2 / rail_length)) + stop_x: float = paddle_center.x + (diff_x * (paddle_length / 2 / rail_length)) + stop_y: float = paddle_center.y + (diff_y * (paddle_length / 2 / rail_length)) + + start: Point = Point(start_x, start_y) + stop: Point = Point(stop_x, stop_y) + + paddle: Segment = Segment(start, stop) + + if (not paddle.is_on(impact)): + print(not paddle.is_on(impact)) + return None + + return ball.angle + math.pi + +def collision(game: Game, impact_data: dict) -> bool: + + segment: Segment = impact_data.get("segment") + + player_hitted = None + for player in game.players: + if (not player.is_connected()): + continue + if (player.rail is segment): + player_hitted = player + break + + surface_angle: float = math.atan2(segment.start.y - segment.stop.y, segment.start.x - segment.stop.y) + + if (player_hitted is None): + + game.ball.angle = wall_collision(game.ball.angle, surface_angle) + + return True + else: + angle = paddle_collision(game.ball, impact_data.get("impact"), player_hitted) + + if (angle is None): + return False + + game.ball.angle = angle + + return True + +async def update_ball(game: Game, impact_data: dict) -> None: + + distance: float = impact_data.get("distance") time_before_impact: float = distance / game.ball.speed await asyncio.sleep(time_before_impact) - segment: Segment = impact.get("segment") - - wall_angle: float = math.atan2(segment.stop.y - segment.start.y, segment.stop.x - segment.start.x) - - game.ball.angle = wall_colision(game.ball.angle, wall_angle) + hit: bool = collision(game, impact_data) - game.ball.position = impact.get("impact") + if (hit == False): + await asyncio.sleep(0.1) + print("Goal") + game.ball.reset() + else: + game.ball.position = impact_data.get("impact_with_padding") await SyncToAsync(game.broadcast)("update_ball", game.ball.to_dict()) @@ -188,9 +253,9 @@ async def render(game: Game): segments: list[Segment] = [player.rail for player in game.players] + [wall.rail for wall in game.walls] - impact: dict = get_impact_point(segments, game.ball, ) + impact_data: dict = get_impact_point(segments, game.ball) - await update_ball(game, impact) + await update_ball(game, impact_data) def routine(game: Game):