42_ft_transcendence/games/objects/Game.py
2024-02-21 11:04:28 +01:00

170 lines
5.0 KiB
Python

from transcendence.abstract.AbstractRoom import AbstractRoom
from transcendence.abstract.AbstractRoomMember import AbstractRoomMember
from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync
from .Ball import Ball
from .Player import Player
from .Spectator import Spectator
from .Wall import Wall
from .Point import Point
from .Segment import Segment
import math
from .. import config
from ..models import GameModel
from ..routine import routine
import threading
class Game(AbstractRoom):
def __init__(self, game_id):
super().__init__(None)
self.ball: Ball = Ball()
self.model: GameModel = GameModel.objects.get(pk = game_id)
self.started = False
radius: float = min(config.MAP_SIZE_X, config.MAP_SIZE_Y) / 2 - 10
players_id: list[int] = self.model.get_players_id()
nb_sides = len(players_id) * 2
polygon: list[Point] = []
for i in range(nb_sides):
angle: float = (i * 2 * math.pi / nb_sides) + (math.pi * 3 / nb_sides)
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))
segments: list[Point] = []
for i in range(nb_sides):
segments.append(Segment(polygon[i], polygon[(i + 1) % nb_sides]))
self.players: list[Player] = []
for i, player_id in enumerate(players_id):
player = Player(self, player_id, None, segments[i * 2])
self.players.append(player)
self.spectators: list[Spectator] = []
self.walls: list[Wall] = []
for i in range(1, nb_sides, 2):
self.walls.append(Wall(segments[i]))
self._updated_players: list[Player] = []
self.game_id: int = game_id
self.thread = threading.Thread(target = routine, args=(self,))
self.thread.start()
def get_players_id(self):
return [player.user_id for player in self.players]
def get_players_connected(self) -> list[Player]:
return [player for player in self.players if player.is_connected()]
def broadcast(self, detail: str, data: dict = {}, excludeds: list[Spectator | Player] = []):
members: list[Player | Spectator] = self.get_players_connected() + self.spectators
for excluded in excludeds:
if (excluded in members):
members.remove(excluded)
for member in members:
member.send(detail, data)
def get_player_by_user_id(self, user_id: int) -> Player:
for player in self.players:
if (player.user_id == user_id):
return player
return None
def _send_game_data(self, member: Spectator | Player):
member.send("init_game", self.to_dict())
def everbody_is_here(self):
for player in self.players:
if not player.is_connected():
return False
return True
def _player_join(self, user_id: int, socket: WebsocketConsumer):
player = self.get_player_by_user_id(user_id)
if (player is None):
return None
# check if player is already connected
if (player.is_connected()):
player.disconnect(1001)
player.socket = socket
if (self.everbody_is_here()):
self.start()
self._update_player(player)
return player
def _update_player(self, player: Player):
self._updated_players.append(player)
def _player_leave(self, player: Player):
self._update_player(player)
def _spectator_join(self, user_id: int, socket: WebsocketConsumer):
spectator: Spectator = Spectator(user_id, socket, self)
self.spectators.append(spectator)
return spectator
def _spectator_leave(self, spectator: Spectator):
self.spectators.remove(spectator)
def join(self, user_id: int, socket: WebsocketConsumer) -> Spectator | Player:
member: Player = self._player_join(user_id, socket)
if (member is None):
member: Spectator = self._spectator_join(user_id, socket)
self._send_game_data(member)
return member
def start(self):
if (self.started == True):
return
self.started = True
self.model.start()
def leave(self, member: AbstractRoomMember):
if (isinstance(member, Player)):
self._player_leave(member)
elif (isinstance(member, Spectator)):
self._spectator_leave(member)
def to_dict(self):
data: dict = {"ball": self.ball.to_dict(),
"players": [player.to_dict() for player in self.players],
"walls": [wall.to_dict() for wall in self.walls],
}
return data