game: add: vector colision (Not work)

This commit is contained in:
2024-02-01 13:18:11 +01:00
parent ab325ae489
commit d332ef8103
12 changed files with 260 additions and 153 deletions

View File

@ -12,7 +12,7 @@ MAP_CENTER_Y = MAP_SIZE_Y / 2
WALL_RATIO = 1
BALL_SPEED_INC = 1
BALL_SPEED_START = 1
BALL_SPEED_START = 170
BALL_SIZE = 4
BALL_SPAWN_POS_X = MAP_SIZE_X / 2
BALL_SPAWN_POS_Y = MAP_SIZE_Y / 2

View File

@ -1,23 +1,28 @@
from __future__ import annotations
from .. import config
from .Point import Point
import math
class Ball:
def __init__(self) -> None:
self.postion_x: float = config.BALL_SPAWN_POS_X
self.postion_y: float = config.BALL_SPAWN_POS_Y
self.velocity_x: float = config.BALL_SPEED_START
self.velocity_y: float = config.BALL_SPEED_START
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
self.speed: float = config.BALL_SPEED_START
def to_dict(self):
data: dict = {
"size": self.size,
"position_x": self.postion_x,
"position_y": self.postion_y,
"velocity_x": self.velocity_x,
"velocity_y": self.velocity_y,
"speed": self.speed,
"position": self.position.to_dict(),
"angle": self.angle,
}
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})"

View File

@ -44,8 +44,8 @@ class Game(AbstractRoom):
angle: float = (i * 2 * math.pi / nb_sides) + (math.pi * 3 / nb_sides)
x: float = config.MAP_CENTER_X + radius * math.cos(angle)
y: float = config.MAP_CENTER_Y + radius * math.sin(angle)
x: float = round(config.MAP_CENTER_X + radius * math.cos(angle))
y: float = round(config.MAP_CENTER_Y + radius * math.sin(angle))
polygon.append(Point(x, y))

View File

@ -1,11 +1,28 @@
from __future__ import annotations
from math import dist
class Point:
def __init__(self, x: float, y: float) -> None:
self.x = x
self.y = y
def __str__(self) -> str:
return f"Point(x: {self.x}, y: {self.y})"
def __repr__(self) -> str:
return f"Point(x: {self.x}, y: {self.x})"
def __eq__(self, __value: object) -> bool:
return (self.x == __value.x and self.y == __value.y)
def distance(self, point: Point):
return dist((point.x, point.y), (self.x, self.y))
def copy(self):
return Point(self.x, self.y)
def to_dict(self):
data: dict[str: float] = {

View File

@ -1,12 +1,20 @@
from .Point import Point
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 __repr__(self) -> str:
return f"Segment(start: {self.start}, stop: {self.stop})"
def __str__(self) -> str:
return f"Segment(start: {self.start}, stop: {self.stop})"
def to_dict(self):
data: dict[str: dict] = {

35
games/objects/Vector.py Normal file
View File

@ -0,0 +1,35 @@
from __future__ import annotations
import math
from .Point import Point
class Vector:
def __init__(self, x: float, y: float) -> None:
self.norm: float = math.dist((0, 0), (x, y))
self.x: float = x
self.y: float = y
def __truediv__(self, denominator: float):
return Vector(self.x / denominator, self.y / denominator)
def angle(self, vector: Vector):
scalar_product: float = self.scalar(vector)
if (scalar_product is None):
return None
cos: float = scalar_product / (vector.norm * self.norm)
angle: float = math.acos(cos)
return angle
def scalar(self, vector: Vector):
return self.x * vector.x + vector.y * self.y
def __str__(self) -> str:
return f"Vector(x: {self.x}, y: {self.y}, norme: {self.norm})"
def __eq__(self, __value: Vector) -> bool:
return (self.x == __value.x and
self.x == __value.x and
self.norm == __value.norm)

View File

@ -9,73 +9,99 @@ if TYPE_CHECKING:
from .objects.Ball import Ball
from .objects.Point import Point
from .objects.Vector import Point
from .objects.Segment import Segment
from .objects.Vector import Vector
from . import config
import math
import asyncio
from asgiref.sync import SyncToAsync
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 get_sign(num: float):
return 1 if num >= 0 else -1
def determine_ordinate_at_origin(point: Point, director_cofficient: float):
return point.y - point.x * director_cofficient
def get_impact_point(segments: list[Segment], ball: Ball):
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)
angle_radian: float = ball.angle * math.pi / 180
def determine_intersections(ball: Ball, segments: list[Segment]):
intersections: list[Point] = []
direction_vector: Vector = Vector(math.cos(angle_radian), math.sin(angle_radian))
x: float = ball.position.x
if (direction_vector.x > 0):
x = x + ball.size / 2
elif (direction_vector.x < 0):
x = x - ball.size / 2
y: float = ball.position.y
if (direction_vector.y > 0):
y = y + ball.size / 2
elif (direction_vector.y < 0):
y = y - ball.size / 2
position: Point = Point(x, y)
for segment in segments:
# form m * x + p
m: float = determine_director_coefficient(segment)
p: float = determine_ordinate_at_origin(segment.start, m)
segment_vector: Vector = Vector(segment.start.x - segment.stop.x, segment.start.y - segment.stop.y)
segment_vector_unit = segment_vector / segment_vector.norm
x: float = determine_intersection(m, p, ball.velocity_y, 0)
scalar: float = segment_vector_unit.scalar(direction_vector)
if (x is None):
continue
y: float = m * x + p
intersections.append(Point(x, y))
if (scalar < 0.01):
continue
return intersections
print(segment_vector, segment_vector_unit, direction_vector)
distance: float = scalar * segment_vector.norm / 2
impact_x: float = position.x + distance * direction_vector.x
impact_y: float = position.y + distance * direction_vector.y
impact: Point = Point(impact_x, impact_y)
print("impact", impact)
return impact
async def update_ball(game: Game, impact: Point):
distance: float = impact.distance(game.ball.position) - game.ball.size / 2
time_before_impact: float = distance / game.ball.speed
await asyncio.sleep(time_before_impact)
game.ball.angle = game.ball.angle + 180
game.ball.position = impact
await SyncToAsync(game.broadcast)("update_ball", game.ball.to_dict())
async def render(game: Game):
while True:
segments: list[Segment] = [player.rail for player in game.players] + [wall.rail for wall in game.walls]
impact = get_impact_point(segments, game.ball)
await update_ball(game, impact)
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):
asyncio.run(render(game))
while True:
for player in game._updated_players:
game.broadcast("update_paddle", player.to_dict(), [player])
game._updated_players.clear()
if (game.started):
game.ball.postion_x = game.ball.postion_x + game.ball.velocity_x
game.ball.postion_y = game.ball.postion_y + game.ball.velocity_y
game.broadcast("update_ball", game.ball.to_dict())
sleep(1 / config.SERVER_TPS)