From cc4c09fd0d5f818963e4d6a9cc698bb1a081d1ba Mon Sep 17 00:00:00 2001 From: starnakin Date: Wed, 7 Feb 2024 14:50:03 +0100 Subject: [PATCH] game: add: wall collision --- games/routine.py | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/games/routine.py b/games/routine.py index b3dd8c9..00f70a9 100644 --- a/games/routine.py +++ b/games/routine.py @@ -110,7 +110,7 @@ def get_interception(segment1: Segment, segment2: Segment): return impact -def get_impact_point(segments: list[Segment], ball: Ball): +def get_impact_point(segments: list[Segment], ball: Ball) -> dict: cos: float = round(math.cos(ball.angle), 6) sin: float = round(math.sin(ball.angle), 6) @@ -119,7 +119,7 @@ def get_impact_point(segments: list[Segment], ball: Ball): ball_segment = Segment(ball.position, point) - closest: Point = None + closest: dict = None for segment in segments: @@ -139,22 +139,46 @@ def get_impact_point(segments: list[Segment], ball: Ball): impact.x += (ball.size / 2) * get_sign(cos) * (-1) impact.y += (ball.size / 2) * get_sign(sin) - if (closest is None or impact.distance(ball.position) < closest.distance(ball.position)): - closest = impact + if (closest is None or impact.distance(ball.position) < closest.get("distance")): + closest = { + "impact": impact, + "segment": segment, + "distance": impact.distance(ball.position), + } return closest + +def wall_colision(ball_angle: float, wall_angle: float) -> float: + + ball_cos: float = math.cos(ball_angle) + ball_sin: float = math.sin(ball_angle) + + incident_angle: float = ball_angle - wall_angle + + reflection_angle: float = wall_angle - incident_angle + + new_cos: float = math.cos(reflection_angle) + new_sin: float = math.sin(reflection_angle) + + new_angle: float = math.atan2(new_sin, new_cos) + + return new_angle + +async def update_ball(game: Game, impact: dict): -async def update_ball(game: Game, impact: Point): - - distance: float = impact.distance(game.ball.position) + distance: float = impact.get("distance") time_before_impact: float = distance / game.ball.speed await asyncio.sleep(time_before_impact) - game.ball.angle = game.ball.angle + math.pi + 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) - game.ball.position = impact + game.ball.position = impact.get("impact") await SyncToAsync(game.broadcast)("update_ball", game.ball.to_dict()) @@ -164,7 +188,7 @@ async def render(game: Game): segments: list[Segment] = [player.rail for player in game.players] + [wall.rail for wall in game.walls] - impact = get_impact_point(segments, game.ball, ) + impact: dict = get_impact_point(segments, game.ball, ) await update_ball(game, impact)