From aeca50f5c71ced3949b73b41a0f98c6939a5ffdc Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Sun, 29 Sep 2024 12:23:34 +0200 Subject: [PATCH 01/15] menu themes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit menu directs et HDG coloriés comme ils devraient --- client.py | 2 +- geometry.py | 17 +++++++++++++++++ interface.py | 28 ++++++++++++++++++---------- theme.json | 29 +++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/client.py b/client.py index df9604c..708cdbd 100644 --- a/client.py +++ b/client.py @@ -312,7 +312,7 @@ def main(server_ip: str): pressing = True delaiPressage = pygame.time.get_ticks() - # commandes vecteurs + # commandes pour vecteurs if keys[pygame.K_3]: vecteurSetting = 3 pressing = True diff --git a/geometry.py b/geometry.py index 16b2819..ed090b4 100644 --- a/geometry.py +++ b/geometry.py @@ -124,3 +124,20 @@ def calculateAngle(principal, secondaire): return [principal - secondaire, 180 - principal + secondaire] else: return [secondaire - principal + 360, principal - 180 - secondaire] + + +def distanceMinie(pos1: tuple[float, float], vitesse1: float, heading1: float, + pos2: tuple[float, float], vitesse2: float, heading2: float): + """ + Calcule la position future de deux avions où la distance sera minimale entre les deux. + :param pos1: Position actuelle de l'avion 1 + :param vitesse1: Vitesse actuelle de l'avion 1 + :param heading1: Heading actuelle de l'avion 1 en radiants + :param pos2: Position actuelle de l'avion 2 + :param vitesse2: Vitesse actuelle de l'avion 2 + :param heading2: Heading actuelle de l'avion 2 en radiants + :return: + """ + + + diff --git a/interface.py b/interface.py index 8c13821..1b53a22 100644 --- a/interface.py +++ b/interface.py @@ -12,13 +12,14 @@ def selectButtonInList(liste: list, event): bouton.unselect() -def scrollListGen(valueList, rect, container, sliderBool=True, sliderDroite=False): +def scrollListGen(valueList, rect, container, sliderBool=True, sliderDroite=False, objectID = None): """Fonction qui construit une liste de boutons, avec une scrollbar width 17 :arg valueList: liste des valeurs en txt ou autre peu importe :arg rect: taille des boutons :arg container: conteneur Pygame_gui dans lequel on met les boutons :parameter sliderBool: Bool, si on veut un slider ou non. True par defaut :parameter sliderDroite: Bool, si on veut le slider à droite ou non + :parameter objectID: Une option de thème optionnelle pour les boutons. :return (slider, listeBoutons)""" valueList = list(valueList) @@ -41,7 +42,7 @@ def scrollListGen(valueList, rect, container, sliderBool=True, sliderDroite=Fals liste = [pygame_gui.elements.UIButton( relative_rect=rect, text=str(valueList[0]), - container=container, anchors=boutonAnchor)] + container=container, anchors=boutonAnchor, object_id=objectID)] for value in valueList[1:]: boutonAnchor.update({'top': 'top', 'top_target': liste[-1]}) @@ -49,7 +50,8 @@ def scrollListGen(valueList, rect, container, sliderBool=True, sliderDroite=Fals relative_rect=rect, text=str(value), container=container, - anchors=boutonAnchor)) + anchors=boutonAnchor, + object_id=objectID)) if sliderDroite: decalage = liste[0].get_abs_rect()[2] @@ -760,14 +762,17 @@ def __init__(self, avion, pos: list[float, float], valeur: str): self.headingDCT = None self.listeGauche = None self.listeDroite = None + objectID = None if valeur == 'DCT': # TODO boutons directs en blanc self.liste = [point['name'] for point in self.avion.papa.route['points']] self.listeAff = self.liste[self.liste.index(avion.papa.nextPoint['name']):] + objectID = pygame_gui.core.ObjectID('@menuLabel', 'menuBlanc') elif valeur == 'XPT': # la diff de liste est qu'on ne prend pas en compte les points de notre secteur ici self.liste = [point['name'] for point in self.avion.papa.route['points']] self.listeAff = self.liste[self.liste.index(avion.papa.defaultXPT):] + objectID = pygame_gui.core.ObjectID('@menuLabel', 'menuBlanc') elif valeur == 'C_IAS': self.liste = [*range(0, 60)] @@ -797,6 +802,7 @@ def __init__(self, avion, pos: list[float, float], valeur: str): self.liste = [*range(0, 365, 5)] indexDuCap = self.liste.index(cap) self.listeAff = self.liste[indexDuCap - 3: indexDuCap + 4] + objectID = pygame_gui.core.ObjectID('@menuLabel', 'menuBlanc') self.window = pygame_gui.elements.UIWindow(pygame.Rect((x, y), (width, height)), window_display_title=valeur, @@ -918,7 +924,7 @@ def __init__(self, avion, pos: list[float, float], valeur: str): self.listeGauche = scrollListGen( listeGauche, - pygame.Rect((0, 0), (width / 3, -1)), + pygame.Rect((1, 0), (width / 3, -1)), self.containerHdgGauche, sliderBool=False)[1] @@ -933,15 +939,16 @@ def __init__(self, avion, pos: list[float, float], valeur: str): tempo = scrollListGen( self.listeAff, - pygame.Rect((0, 0), (width / 3, -1)), + pygame.Rect((1, 0), (width / 3, -1)), self.listeContainer, - sliderBool=False) + sliderBool=False, + objectID=objectID) self.listeBoutons = tempo[1] self.containerHdgDroite = pygame_gui.elements.UIScrollingContainer( container=self.window, - relative_rect=pygame.Rect((0, 0), (width / 3, height)), + relative_rect=pygame.Rect((1, 0), (width / 3, height)), allow_scroll_x=False, allow_scroll_y=False, anchors={'top': 'top', 'top_target': self.topContainer, @@ -950,7 +957,7 @@ def __init__(self, avion, pos: list[float, float], valeur: str): self.listeDroite = scrollListGen( listeDroite, - pygame.Rect((0, 0), (width / 3, -1)), + pygame.Rect((1, 0), (width / 3, -1)), self.containerHdgDroite, sliderBool=False)[1] else: @@ -964,9 +971,10 @@ def __init__(self, avion, pos: list[float, float], valeur: str): tempo = scrollListGen( self.listeAff, - pygame.Rect((0, 0), (width, -1)), + pygame.Rect((1, 0), (width, -1)), self.listeContainer, - sliderBool=False) + sliderBool=False, + objectID=objectID) self.listeBoutons = tempo[1] diff --git a/theme.json b/theme.json index 0040240..7c6943a 100644 --- a/theme.json +++ b/theme.json @@ -51,6 +51,35 @@ "active_border": "#3E3E3E" } }, + "menuBleu": { + "colours": + { + "normal_border": "#808080", + "hovered_border": "#808080", + "disabled_border": "#808080", + "selected_border": "#808080", + "active_border": "#808080" + } + }, + "menuBlanc": { + "colours": + { + "normal_bg": "#C6DADA", + "hovered_bg": "#A3B6C4", + "active_bg": "#C6DADA" + } + }, + "@menuLabel": + { + "misc": { + "border_width": "1", + "text_horiz_alignment": "left", + "text_horiz_alignment_padding": "0", + "text_vert_alignment": "left", + "text_vert_alignment_padding": "2", + "shadow_width": "0" + } + }, "@flightDataWindow": { "misc": { From cb4aa4126f0c55e1da0adca2b6fed9dccaa0b0c6 Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Sun, 29 Sep 2024 12:35:23 +0200 Subject: [PATCH 02/15] fix : directs se dessinent tout le temps mtn --- interface.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interface.py b/interface.py index 1b53a22..3fc7272 100644 --- a/interface.py +++ b/interface.py @@ -1127,7 +1127,13 @@ def checkUnHovered(self, event) -> None: """ if self.valeur in ['DCT', 'XPT']: if event.ui_element in self.listeBoutons: - self.avion.pointDessinDirect = None + dessin = False + for element in self.listeBoutons: + if element.hovered: + dessin = True + break + if not dessin: + self.avion.pointDessinDirect = None def checkMenuHovered(self) -> None: """ From 34edf27ad490c5d9b7d008e650a7d0da8ecc0fbb Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Sun, 29 Sep 2024 20:50:09 +0200 Subject: [PATCH 03/15] alisep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit alisep fonctionnel et hyper stylé --- XML/simu.xml | 10 ++-- client.py | 38 ++++++++++++++- geometry.py | 30 ++++++++---- interface.py | 82 +++++++++++++++++++++++++++++++ player.py | 122 +++++++++++++++++++++++++++++++++++------------ requirements.txt | 7 +-- server.py | 1 + server_def.py | 37 ++++++++++++++ 8 files changed, 280 insertions(+), 47 deletions(-) create mode 100644 server_def.py diff --git a/XML/simu.xml b/XML/simu.xml index 3858b0a..0570c15 100644 --- a/XML/simu.xml +++ b/XML/simu.xml @@ -2,14 +2,14 @@ 1002 - + FCACA - DA42 - GAI-JUVEN + DH8D + ABISA-BERNI 30000 False - 720 - 1339 + 1375 + 1644 300 diff --git a/client.py b/client.py index 708cdbd..4e81d10 100644 --- a/client.py +++ b/client.py @@ -64,6 +64,11 @@ def main(server_ip: str): alidadPos = (0, 0) curseur_alidad = False + # alisep + curseur_aliSep = False + sepA = interface.aliSep('A') + sepB = interface.aliSep('B') + # scroll and zoom zoomDef = 0.5 scrollDef = [width / 4, height/4] @@ -118,6 +123,9 @@ def main(server_ip: str): game = packet.game dictAvions = packet.dictAvions + sepA.calculation(carte) + sepB.calculation(carte) + for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -185,6 +193,18 @@ def main(server_ip: str): elif action in ['HDG', 'DCT']: menuValeurs = interface.menuValeurs(menuValeurs.avion, pygame.mouse.get_pos(), action) + if curseur_aliSep: + for avion in dictAvionsAff.values(): + if avion.checkClicked(event): + if curseur_aliSep == 'A': + if sepA.linkAvion(avion, carte): + curseur_aliSep = False + pygame.mouse.set_cursor(pygame.cursors.arrow) + else: + if sepB.linkAvion(avion, carte): + curseur_aliSep = False + pygame.mouse.set_cursor(pygame.cursors.arrow) + else: for avion in dictAvionsAff.values(): # pour chaque avion @@ -267,6 +287,9 @@ def main(server_ip: str): alidad = False curseur_alidad = False pygame.mouse.set_cursor(pygame.cursors.arrow) + elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3 and curseur_aliSep: + curseur_aliSep = False + pygame.mouse.set_cursor(pygame.cursors.arrow) manager.process_events(event) @@ -284,7 +307,7 @@ def main(server_ip: str): drag = [pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1]] else: drag = [pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1]] - if not curseur_alidad: + if not curseur_alidad and not curseur_aliSep: pygame.mouse.set_cursor(pygame.cursors.arrow) """Keys""" @@ -307,6 +330,19 @@ def main(server_ip: str): pygame.mouse.set_cursor(pygame.cursors.broken_x) pressing = True delaiPressage = pygame.time.get_ticks() + if keys[pygame.K_g]: # alidad start + sepA.kill() + curseur_aliSep = 'A' + pygame.mouse.set_cursor(pygame.cursors.diamond) + pressing = True + delaiPressage = pygame.time.get_ticks() + if keys[pygame.K_h]: # alidad start + sepB.kill() + curseur_aliSep = 'B' + pygame.mouse.set_cursor(pygame.cursors.diamond) + pressing = True + delaiPressage = pygame.time.get_ticks() + if keys[pygame.K_f] and flightDataWindow is None: # Flight Data Window flightDataWindow = interface.flightDataWindow() pressing = True diff --git a/geometry.py b/geometry.py index ed090b4..add4ce4 100644 --- a/geometry.py +++ b/geometry.py @@ -1,6 +1,6 @@ import math import numpy as np - +from scipy.optimize import minimize def calculateHeading(x: int, y: int, xPoint: int, yPoint: int): if y > yPoint: @@ -127,17 +127,31 @@ def calculateAngle(principal, secondaire): def distanceMinie(pos1: tuple[float, float], vitesse1: float, heading1: float, - pos2: tuple[float, float], vitesse2: float, heading2: float): + pos2: tuple[float, float], vitesse2: float, heading2: float) -> float: """ Calcule la position future de deux avions où la distance sera minimale entre les deux. - :param pos1: Position actuelle de l'avion 1 - :param vitesse1: Vitesse actuelle de l'avion 1 + :param pos1: Position actuelle de l'avion 1 en px + :param vitesse1: Vitesse actuelle de l'avion 1 en px/sec :param heading1: Heading actuelle de l'avion 1 en radiants - :param pos2: Position actuelle de l'avion 2 - :param vitesse2: Vitesse actuelle de l'avion 2 + :param pos2: Position actuelle de l'avion 2 en px + :param vitesse2: Vitesse actuelle de l'avion 2 en px/sec :param heading2: Heading actuelle de l'avion 2 en radiants - :return: + :return: Temps dans lequel la distance sera la plus faible """ - + x0 = 1.0 + + caca = minimize( + distanceEnFduTemps, x0, args=(pos1, vitesse1, heading1, pos2, vitesse2, heading2), + method='Nelder-Mead', tol=1e-4 + ) + return caca.x[0] + + +def distanceEnFduTemps(temps, pos1: tuple[float, float], vitesse1: float, heading1: float, + pos2: tuple[float, float], vitesse2: float, heading2: float): + return math.sqrt( + ((pos1[0] + vitesse1 * temps * math.cos(heading1)) - (pos2[0] + vitesse2 * temps * math.cos(heading2))) ** 2 + + ((pos1[1] + vitesse1 * temps * math.sin(heading1)) - (pos2[1] + vitesse2 * temps * math.sin(heading2))) ** 2 + ) \ No newline at end of file diff --git a/interface.py b/interface.py index 3fc7272..5e8ed5a 100644 --- a/interface.py +++ b/interface.py @@ -1,5 +1,7 @@ import pygame import pygame_gui +import math +import geometry import horloge from valeurs_config import * @@ -1262,4 +1264,84 @@ def checkAlive(self): return self.window.alive() +class aliSep: + + def __init__(self, lettre): + self.lettre = lettre + self.avion1 = None + self.avion2 = None + self.distance = None + self.temps = None + + def linkAvion(self, avion, carte) -> bool: + + """ + Associe un avion. Si un avion est déjà associé alors celà déclenche le calcul de la sep + :param avion: l'avion à associer + :param carte: les données de la carte + :return: si les deux avions ont été associés, renvoies True + """ + + if self.avion2: + return True + + if not self.avion1: + self.avion1 = avion + return False + + self.avion2 = avion + + self.avion1.sep = True + self.avion2.sep = True + + self.calculation(carte) + + return True + + def calculation(self, carte): + + if not self.avion2: + return None + + self.temps = geometry.distanceMinie( + (self.avion1.papa.x, self.avion1.papa.y), self.avion1.papa.speedPx / radarRefresh, + self.avion1.papa.headingRad, + (self.avion2.papa.x, self.avion2.papa.y), self.avion2.papa.speedPx / radarRefresh, + self.avion2.papa.headingRad, + ) + + self.distance = math.sqrt( + ((self.avion1.papa.x + self.avion1.papa.speedPx / radarRefresh * self.temps * math.cos( + self.avion1.papa.headingRad)) - + (self.avion2.papa.x + self.avion2.papa.speedPx / radarRefresh * self.temps * math.cos( + self.avion2.papa.headingRad))) ** 2 + + ((self.avion1.papa.y + self.avion1.papa.speedPx / radarRefresh * self.temps * math.sin( + self.avion1.papa.headingRad)) - + (self.avion2.papa.y + self.avion2.papa.speedPx / radarRefresh * self.temps * math.sin( + self.avion2.papa.headingRad))) ** 2) + + self.avion1.sepSetting.update({self.lettre: [self.temps, self.distance * carte['mapScale']]}) + self.avion2.sepSetting.update({self.lettre: [self.temps, self.distance * carte['mapScale']]}) + + def kill(self): + + if not self.avion2 and self.avion1: + self.avion1 = None + return None + + if not self.avion1: + return None + + self.avion1.sepSetting.pop(self.lettre) + self.avion2.sepSetting.pop(self.lettre) + + if len(self.avion1.sepSetting) == 0: + self.avion1.sep = False + if len(self.avion2.sepSetting) == 0: + self.avion2.sep = False + + self.avion1 = None + self.avion2 = None + + diff --git a/player.py b/player.py index 4820b68..7252ae9 100644 --- a/player.py +++ b/player.py @@ -55,6 +55,8 @@ def __init__(self, Id: int, papa, zoom: float, scroll: list[float, float]): self.predictionPoint = None # point pour la prédiction de route self.drawRouteBool = False self.locWarning = False + self.sep = False + self.sepSetting = {} # [temps à dessiner, distance minie en nm] self.etiquetteExtended = False self.lastHoveredTime = 0 self.pointDessinDirect = None @@ -102,6 +104,48 @@ def drawVector(self, color, window, vecteurSetting, zoom): self.affY + plotSize + self.papa.speedPx * 60 / radarRefresh * vecteurSetting * zoom * math.sin( self.papa.headingRad)), 2) + def drawSep(self, window, zoom): + """ + Dessine la sep avec un autre avion + :param window: + :param zoom: + :return: + """ + sep = (0, 9999999) + + for lettre, sepSetting in self.sepSetting.items(): + if sepSetting[1] <= sep[1] and 0 <= sepSetting[0]: + sep = sepSetting + + sepSetting = sep + + coords = [self.affX + plotSize + self.papa.speedPx / radarRefresh * sepSetting[0] * zoom * math.cos( + self.papa.headingRad), + self.affY + plotSize + self.papa.speedPx / radarRefresh * sepSetting[0] * zoom * math.sin( + self.papa.headingRad) + ] + + if sepSetting[1] <= 6: + color = (255, 0, 0) + elif sepSetting[1] <= 9: + color = (241, 237, 57) + else: + color = (157, 193, 126) + + pygame.draw.line(window, color, (self.affX + plotSize, self.affY + plotSize), coords, 2) + + font = pygame.font.SysFont('arial', 15) + + coords[0] += 2 + for lettre, sepSetting in self.sepSetting.items(): + if 0 <= sepSetting[0]: + img = font.render(lettre + str(round(sepSetting[1], 1)), True, color) + window.blit(img, coords) + coords[1] += 15 + else: + img = font.render(lettre, True, (255, 255, 255)) + window.blit(img, coords) + def draw(self, win, zoom, scroll, vecteurs, vecteurSetting, points): # updates @@ -133,34 +177,39 @@ def draw(self, win, zoom, scroll, vecteurs, vecteurSetting, points): width = 1 # Dessin - if self.visible: - if self.papa.warning: - color = (255, 120, 60) - elif self.locWarning: - color = (100, 200, 100) - elif self.etiquetteExtended: - color = (30, 144, 255) - width = 3 - else: - color = (255, 255, 255) - - pygame.draw.circle(win, color, (self.affX + plotSize, self.affY + plotSize), plotSize, 1) - pygame.draw.circle(win, color, (self.affX + plotSize, self.affY + plotSize), plotSize / 1.5, 1) - - if vecteurs or self.papa.warning or self.locWarning: # si on doit dessiner les vecteurs - self.drawVector(color, win, vecteurSetting, zoom) # on appelle la fonction - - radius = 1 - for plot in self.papa.comete: - affPlot = [plot[0] * zoom + scroll[0], - plot[1] * zoom + scroll[1]] - pygame.draw.circle(win, (255, 255, 255), affPlot, int(round(radius)), 1) - radius += 0.3 - - point = self.findEtiquetteAnchorPoint() - if point is not None: - pygame.draw.line(win, color, (self.affX + plotSize, self.affY + plotSize), - (point[0], point[1]), width) + if not self.visible: + return None + + if self.papa.warning: + color = (255, 120, 60) + elif self.locWarning: + color = (100, 200, 100) + elif self.etiquetteExtended: + color = (30, 144, 255) + width = 3 + else: + color = (255, 255, 255) + + pygame.draw.circle(win, color, (self.affX + plotSize, self.affY + plotSize), plotSize, 1) + pygame.draw.circle(win, color, (self.affX + plotSize, self.affY + plotSize), plotSize / 1.5, 1) + + if self.sep: + self.drawSep(win, zoom) + + elif vecteurs or self.papa.warning or self.locWarning: # si on doit dessiner les vecteurs + self.drawVector(color, win, vecteurSetting, zoom) # on appelle la fonction + + radius = 1 + for plot in self.papa.comete: + affPlot = [plot[0] * zoom + scroll[0], + plot[1] * zoom + scroll[1]] + pygame.draw.circle(win, (255, 255, 255), affPlot, int(round(radius)), 1) + radius += 0.3 + + point = self.findEtiquetteAnchorPoint() + if point is not None: + pygame.draw.line(win, color, (self.affX + plotSize, self.affY + plotSize), + (point[0], point[1]), width) def findEtiquetteAnchorPoint(self) -> tuple[float, float]: """ @@ -186,8 +235,8 @@ def findEtiquetteAnchorPoint(self) -> tuple[float, float]: pointBas = geometry.calculateIntersection((rect[0], rect[1] + rect[3]), (rect[0] + rect[2], rect[1] + rect[3]), - (self.etiquette.centre[0], self.etiquette.centre[1]), - (self.affX + plotSize, self.affY + plotSize)) + (self.etiquette.centre[0], self.etiquette.centre[1]), + (self.affX + plotSize, self.affY + plotSize)) if rect[0] <= pointHaut[0] <= rect[0] + rect[2] and self.affY <= self.etiquetteY: return pointHaut @@ -291,6 +340,19 @@ def drawRoute(self, points, win, zoom, scroll): pointUn = pointDeux # on passe au prochain point + def checkClicked(self, event) -> bool: + """ + Renvoies True si un des boutons (avion ou etiquette) correspond à cet event + :param event: + :return: + """ + if event.ui_element == self.bouton: + return True + if event.ui_element.ui_container == self.etiquette.container: + return True + else: + return False + def checkEvent(self, event, pilote): """ diff --git a/requirements.txt b/requirements.txt index ae1e042..fb2aa95 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ -numpy +numpy~=2.1.1 pygame-ce -pygame_gui -python-i18n \ No newline at end of file +pygame_gui~=0.6.12 +python-i18n +scipy~=1.14.1 \ No newline at end of file diff --git a/server.py b/server.py index 2804886..067227a 100644 --- a/server.py +++ b/server.py @@ -467,6 +467,7 @@ def threaded_ping_responder(): dictAvion.pop(avion) for avion in list(dictAvion.values()): # tous les calculs de distances sont ici effectués en pixel, la conversion se fait avec le mapScale + # TODO remplacer ce STCA avec le nouveau dans server_def STCAtriggered = False predictedPos = [] VspeedOne = avion.evolution diff --git a/server_def.py b/server_def.py new file mode 100644 index 0000000..885fe9f --- /dev/null +++ b/server_def.py @@ -0,0 +1,37 @@ +import geometry +import math +from valeurs_config import * + + +def STCA(avion1, avion2, carte) -> bool: + """ + Calcule si on doit mettre le SCTA sur deux avions + :param avion1: l'avion paquet + :param avion2: + :param carte: la carte de la map + :return: + """ + + temps = geometry.distanceMinie((avion1.x, avion1.y), avion1.speedPx / radarRefresh, avion1.headingRad, + (avion2.x, avion2.y), avion2.speedPx / radarRefresh, avion2.headingRad) + + if (math.sqrt( + ((avion1.x + avion1.speedPx / radarRefresh * temps * math.cos(avion1.headingRad)) - + (avion2.x + avion2.speedPx / radarRefresh * temps * math.cos(avion2.headingRad))) ** 2 + + ((avion1.y + avion1.speedPx / radarRefresh * temps * math.sin(avion1.headingRad)) - + (avion2.y + avion2.speedPx / radarRefresh * temps * math.sin(avion2.headingRad))) ** 2 + ) <= 5 / carte['mapScale']): # si la distance est infèrieur à 5 nm + + if avion1.evolution == avion2.evolution == 0 and avion2.altitude == avion1.altitude: + return True + + elif avion1.evolution == avion2.evolution == 0: + return False + + elif abs(avion2.altitude + avion2.evolution / radarRefresh * temps + - (avion1.altitude + avion1.evolution / radarRefresh * temps)) <= 2000: + return True + + return False + + From affe8e00f0d01b0b7f8bdaa1ab3c534e1d88a71f Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Mon, 30 Sep 2024 21:11:40 +0200 Subject: [PATCH 04/15] menu options radar menu option radar, 3 sep alidad, vecteurs, bref giga bg --- client.py | 96 ++++++++++++++--------------- interface.py | 152 ++++++++++++++++++++++++++++++++++++++++------ player.py | 3 +- theme.json | 21 +++++++ valeurs_config.py | 2 +- 5 files changed, 205 insertions(+), 69 deletions(-) diff --git a/client.py b/client.py index 4e81d10..c7acd31 100644 --- a/client.py +++ b/client.py @@ -38,6 +38,7 @@ def main(server_ip: str): menuATC = None menuValeurs = None flightDataWindow = None + menuRadar = interface.menuRadar() # on se connecte au serveur n = Network(server_ip) @@ -66,8 +67,7 @@ def main(server_ip: str): # alisep curseur_aliSep = False - sepA = interface.aliSep('A') - sepB = interface.aliSep('B') + sepDict = {'A': interface.aliSep('A'), 'B': interface.aliSep('B'), 'C': interface.aliSep('C')} # scroll and zoom zoomDef = 0.5 @@ -123,8 +123,8 @@ def main(server_ip: str): game = packet.game dictAvions = packet.dictAvions - sepA.calculation(carte) - sepB.calculation(carte) + for sep in sepDict.values(): + sep.calculation(carte) for event in pygame.event.get(): @@ -159,6 +159,34 @@ def main(server_ip: str): # on vérifie que l'alidade n'est pas actif elif event.type == pygame_gui.UI_BUTTON_PRESSED and not curseur_alidad: empecherDragging = False + + if menuRadar.checkActive(): + action = menuRadar.checkEvent(event) + + if action is not None: + + if type(action) in [list, tuple]: + + if action[0] == 'VecteursToggle': + if vecteurSetting == action[1]: + vecteurs = not vecteurs + else: + vecteurs = True + vecteurSetting = action[1] + + elif action[0] == 'Vecteurs': + vecteurSetting = action[1] + + elif action[0] == 'Sep': + sepDict[action[1]].kill() + curseur_aliSep = action[1] + pygame.mouse.set_cursor(pygame.cursors.diamond) + elif action == 'Alidade': + curseur_alidad = True + pygame.mouse.set_cursor(pygame.cursors.broken_x) + + elif action == 'Cercles': + pass # on regarde si notre menu pour le pilote est actif if menuAvion is not None: @@ -194,16 +222,13 @@ def main(server_ip: str): menuValeurs = interface.menuValeurs(menuValeurs.avion, pygame.mouse.get_pos(), action) if curseur_aliSep: - for avion in dictAvionsAff.values(): - if avion.checkClicked(event): - if curseur_aliSep == 'A': - if sepA.linkAvion(avion, carte): - curseur_aliSep = False - pygame.mouse.set_cursor(pygame.cursors.arrow) - else: - if sepB.linkAvion(avion, carte): - curseur_aliSep = False - pygame.mouse.set_cursor(pygame.cursors.arrow) + for sep in sepDict: + if sep == curseur_aliSep: + for avion in dictAvionsAff.values(): + if avion.checkClicked(event): + if sepDict[sep].linkAvion(avion, carte): + curseur_aliSep = False + pygame.mouse.set_cursor(pygame.cursors.arrow) else: for avion in dictAvionsAff.values(): # pour chaque avion @@ -287,10 +312,15 @@ def main(server_ip: str): alidad = False curseur_alidad = False pygame.mouse.set_cursor(pygame.cursors.arrow) + elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3 and curseur_aliSep: curseur_aliSep = False pygame.mouse.set_cursor(pygame.cursors.arrow) + elif (event.type == pygame.MOUSEBUTTONUP and event.button == 1 and not empecherDragging + and not (curseur_aliSep or curseur_alidad) and mouseDownTime + 150 >= pygame.time.get_ticks()): + menuRadar.show() + manager.process_events(event) if menuAvion is not None: @@ -325,47 +355,12 @@ def main(server_ip: str): affichage_type_avion = not affichage_type_avion pressing = True delaiPressage = pygame.time.get_ticks() - if keys[pygame.K_a]: # alidad start - curseur_alidad = True - pygame.mouse.set_cursor(pygame.cursors.broken_x) - pressing = True - delaiPressage = pygame.time.get_ticks() - if keys[pygame.K_g]: # alidad start - sepA.kill() - curseur_aliSep = 'A' - pygame.mouse.set_cursor(pygame.cursors.diamond) - pressing = True - delaiPressage = pygame.time.get_ticks() - if keys[pygame.K_h]: # alidad start - sepB.kill() - curseur_aliSep = 'B' - pygame.mouse.set_cursor(pygame.cursors.diamond) - pressing = True - delaiPressage = pygame.time.get_ticks() if keys[pygame.K_f] and flightDataWindow is None: # Flight Data Window flightDataWindow = interface.flightDataWindow() pressing = True delaiPressage = pygame.time.get_ticks() - # commandes pour vecteurs - if keys[pygame.K_3]: - vecteurSetting = 3 - pressing = True - delaiPressage = pygame.time.get_ticks() - if keys[pygame.K_6]: - vecteurSetting = 6 - pressing = True - delaiPressage = pygame.time.get_ticks() - if keys[pygame.K_9]: - vecteurSetting = 9 - pressing = True - delaiPressage = pygame.time.get_ticks() - if keys[pygame.K_v]: - vecteurs = not vecteurs - pressing = True - delaiPressage = pygame.time.get_ticks() - # commandes pilote if keys[pygame.K_n] and nouvelAvionWin is None and pilote: nouvelAvionWin = interface.nouvelAvionWindow(carte['routes'], perfos) @@ -415,6 +410,9 @@ def main(server_ip: str): if not nouvelAvionWin.checkAlive(): nouvelAvionWin = None + if menuRadar.checkActive(): + menuRadar.checkMenuHovered() + '''partie affichage''' # on remplit d'abord avec une couleur diff --git a/interface.py b/interface.py index 5e8ed5a..18b478c 100644 --- a/interface.py +++ b/interface.py @@ -14,7 +14,7 @@ def selectButtonInList(liste: list, event): bouton.unselect() -def scrollListGen(valueList, rect, container, sliderBool=True, sliderDroite=False, objectID = None): +def scrollListGen(valueList, rect, container, sliderBool=True, sliderDroite=False, objectID=None): """Fonction qui construit une liste de boutons, avec une scrollbar width 17 :arg valueList: liste des valeurs en txt ou autre peu importe :arg rect: taille des boutons @@ -81,7 +81,10 @@ def __init__(self, routes, avions): # la liste des types avion self.typeAvionContainer = pygame_gui.elements.UIScrollingContainer(pygame.Rect((0, 34), (150, 200)), - container=self.window, anchors={'left': 'left', 'left_target': self.routeContainer}, allow_scroll_x=False) + container=self.window, + anchors={'left': 'left', + 'left_target': self.routeContainer}, + allow_scroll_x=False) self.typeAvionBoutonListe = scrollListGen( list(avions.keys()), pygame.Rect((0, 0), (125, 17)), self.typeAvionContainer, False)[1] @@ -92,7 +95,8 @@ def __init__(self, routes, avions): relative_rect=pygame.Rect((0, 20), (200, 17)), text='Générateur de conflits', container=self.window, - anchors={'top': 'top', 'top_target': self.typeAvionContainer, 'left': 'left', 'left_target': self.routeContainer}) + anchors={'top': 'top', 'top_target': self.typeAvionContainer, 'left': 'left', + 'left_target': self.routeContainer}) self.arrivalBouton = pygame_gui.elements.UIButton( relative_rect=pygame.Rect((0, 5), (200, 17)), @@ -105,7 +109,8 @@ def __init__(self, routes, avions): relative_rect=pygame.Rect((0, 5), (200, 17)), text='Ok', container=self.window, - anchors={'top': 'top', 'top_target': self.arrivalBouton, 'left': 'left', 'left_target': self.routeContainer}) + anchors={'top': 'top', 'top_target': self.arrivalBouton, 'left': 'left', + 'left_target': self.routeContainer}) self.indicatiflabel = pygame_gui.elements.UILabel( relative_rect=pygame.Rect((0, 0), (200, 17)), @@ -116,12 +121,14 @@ def __init__(self, routes, avions): self.indicatifinput = pygame_gui.elements.UITextEntryBox( relative_rect=pygame.Rect((0, 0), (200, 30)), container=self.window, - anchors={'left': 'left', 'left_target': self.typeAvionContainer, 'top': 'top', 'top_target': self.indicatiflabel}) + anchors={'left': 'left', 'left_target': self.typeAvionContainer, 'top': 'top', + 'top_target': self.indicatiflabel}) self.FLlabel = pygame_gui.elements.UILabel( relative_rect=pygame.Rect((0, 0), (200, 17)), container=self.window, - anchors={'left': 'left', 'left_target': self.typeAvionContainer, 'top': 'top', 'top_target': self.indicatifinput}, + anchors={'left': 'left', 'left_target': self.typeAvionContainer, 'top': 'top', + 'top_target': self.indicatifinput}, text='FL') self.FLinput = pygame_gui.elements.UITextEntryBox( @@ -253,8 +260,9 @@ def __init__(self, avion): container=self.window, anchors={'left': 'left', 'left_target': self.altiContainer}) - tempo = scrollListGen(range(round(avion.papa.speedIAS / 10) * 10 - 50, round(avion.papa.speedIAS / 10) * 10 + 60, 10), - pygame.Rect((0, 0), (75, 17)), self.speedContainer) + tempo = scrollListGen( + range(round(avion.papa.speedIAS / 10) * 10 - 50, round(avion.papa.speedIAS / 10) * 10 + 60, 10), + pygame.Rect((0, 0), (75, 17)), self.speedContainer) self.speedBoutonListe = tempo[1] self.speedSlider = tempo[0] @@ -265,7 +273,7 @@ def __init__(self, avion): self.pointContainer = pygame_gui.elements.UIScrollingContainer( pygame.Rect((0, 0), (100, 200)), container=self.window, - anchors={'left': 'left','left_target': self.speedContainer}) + anchors={'left': 'left', 'left_target': self.speedContainer}) tempo = scrollListGen([point['name'] for point in avion.papa.route['points']], pygame.Rect((0, 0), (75, 17)), @@ -429,7 +437,7 @@ def __init__(self, avion): self.AFL = pygame_gui.elements.UIButton( relative_rect=pygame.Rect((0, 0), (-1, -1)), - text=str(round(avion.papa.altitude/100)), + text=str(round(avion.papa.altitude / 100)), generate_click_events_from=clicks, object_id=pygame_gui.core.ObjectID('@etiquetteBold', 'rose'), anchors={'top': 'top', 'top_target': self.indicatif}, @@ -536,7 +544,7 @@ def update(self, avion): self.XPT.set_text(avion.papa.XPT) # alti - self.AFL.set_text(str(round(avion.papa.altitude/100)) + " " + avion.papa.altitudeEvoTxt) + self.AFL.set_text(str(round(avion.papa.altitude / 100)) + " " + avion.papa.altitudeEvoTxt) self.CFL.set_text(str(avion.papa.CFL)[:2]) @@ -622,7 +630,7 @@ def __init__(self, avion, pos): width = 80 height = 120 - x = pos[0] - width/2 + x = pos[0] - width / 2 y = pos[1] - 35 if avion.papa.etatFrequence == 'previousFreq': @@ -825,9 +833,9 @@ def __init__(self, avion, pos: list[float, float], valeur: str): if valeur == 'C_IAS': self.noeud = pygame_gui.elements.UIButton( - pygame.Rect((0, 0), (width / 2, -1)), - container=self.topContainer, - text="K") + pygame.Rect((0, 0), (width / 2, -1)), + container=self.topContainer, + text="K") self.mach = pygame_gui.elements.UIButton( pygame.Rect((0, 0), (width / 2, -1)), @@ -981,12 +989,14 @@ def __init__(self, avion, pos: list[float, float], valeur: str): self.listeBoutons = tempo[1] if valeur in ['XFL', 'PFL', 'CFL']: # on ramène la fenêtre au bon endroit pour la souris (sur le PFL) - y = y - (self.topContainer.get_abs_rect()[3] + self.listeBoutons[0].get_abs_rect()[3] * 2.5 + self.window.title_bar_height) + y = y - (self.topContainer.get_abs_rect()[3] + self.listeBoutons[0].get_abs_rect()[ + 3] * 2.5 + self.window.title_bar_height) self.window.set_position((x, y)) widthListeContainer = self.listeContainer.get_abs_rect()[2] - self.listeContainer.set_dimensions((widthListeContainer, len(self.listeAff) * self.listeBoutons[0].get_abs_rect()[3])) + self.listeContainer.set_dimensions( + (widthListeContainer, len(self.listeAff) * self.listeBoutons[0].get_abs_rect()[3])) self.window.set_minimum_dimensions((width, width)) height = (self.listeContainer.get_abs_rect()[3] + self.topContainer.rect[3] + @@ -1240,7 +1250,7 @@ def linkAvion(self, avion, points: list, heure) -> None: self.ligneDeux.set_text(text) text = (avion.papa.provenance + ' ' + avion.papa.destination + ' R' + str(avion.papa.PFL) - + ' ' + str(round(avion.papa.altitude/100)) + ' ' + str(avion.papa.PFL) + + ' ' + str(round(avion.papa.altitude / 100)) + ' ' + str(avion.papa.PFL) + ' ' + avion.papa.EPT + ' ' + avion.papa.XPT + ' X' + str(avion.papa.XFL)) self.ligneTrois.set_text(text) @@ -1344,4 +1354,110 @@ def kill(self): self.avion2 = None +class menuRadar: + + def __init__(self): + + width = 100 + height = 200 + + self.window = pygame_gui.elements.UIWindow( + pygame.Rect((500, 500), (width, height)), + window_display_title="Flight Data Window", + object_id=pygame_gui.core.ObjectID('@menuRadar', 'blanc'), + + ) + ancres = {} + self.listeVecteurs = [] + indice = 0 + + for b in range(3): + + for bb in range(3): + indice += 1 + self.listeVecteurs.append( + pygame_gui.elements.UIButton(pygame.Rect((0, 0), (width / 3, width / 3)), + text=str(indice) + "'", + container=self.window, + anchors=ancres, + object_id=pygame_gui.core.ObjectID('@menuRadar', 'blanc'), + generate_click_events_from=frozenset( + [pygame.BUTTON_LEFT, pygame.BUTTON_RIGHT]) + )) + ancres.update({'left': 'left', 'left_target': self.listeVecteurs[-1]}) + ancres.pop('left') + ancres.pop('left_target') + ancres.update({'top': 'top', 'top_target': self.listeVecteurs[-1]}) + + self.alidade = pygame_gui.elements.UIButton(pygame.Rect((0, 0), (width, width / 3)), + text="ALIDADE", + container=self.window, + anchors={'top': 'top', 'top_target': self.listeVecteurs[-1]}, + object_id=pygame_gui.core.ObjectID('@menuRadar', 'blanc')) + + self.cercles = pygame_gui.elements.UIButton(pygame.Rect((0, 0), (width, width / 3)), + text="@", + container=self.window, + anchors={'top': 'top', 'top_target': self.alidade}, + object_id=pygame_gui.core.ObjectID('@menuRadar', 'blanc')) + + ancres = {'top': 'top', 'top_target': self.cercles} + self.listeSep = [] + for lettre in ['A', 'B', 'C']: + self.listeSep.append( + pygame_gui.elements.UIButton(pygame.Rect((0, 0), (width / 3, width / 3)), + text=lettre, + container=self.window, + anchors=ancres, + object_id=pygame_gui.core.ObjectID('@menuRadar', 'blanc') + )) + ancres.update({'left': 'left', 'left_target': self.listeSep[-1]}) + + self.lastHovered = pygame.time.get_ticks() + self.window.hide() + + def show(self): + + pos = pygame.mouse.get_pos() + rect = self.window.get_abs_rect() + self.window.set_position((pos[0] - rect[2] / 2, pos[1] - rect[3] / 2)) + self.window.show() + + def checkActive(self): + return self.window.visible + + def checkEvent(self, event): + + if event.ui_element in self.listeVecteurs: + if event.mouse_button == 1: + return 'VecteursToggle', int(event.ui_element.text[0]) + + elif event.mouse_button == 3: + return 'Vecteurs', int(event.ui_element.text[0]) + + elif event.ui_element in self.listeSep: + self.window.hide() + return 'Sep', event.ui_element.text + + elif event.ui_element == self.alidade: + self.window.hide() + return 'Alidade' + + elif event.ui_element == self.cercles: + self.window.hide() + return 'Cercles' + + def checkMenuHovered(self) -> None: + """ + Commence le compteur si n'est plus survolé + :return: + """ + rect = self.window.get_abs_rect() + mouse = pygame.mouse.get_pos() + + if rect[0] <= mouse[0] <= rect[0] + rect[2] and rect[1] <= mouse[1] <= rect[1] + rect[3]: + self.lastHovered = pygame.time.get_ticks() + + elif pygame.time.get_ticks() - self.lastHovered > temps_disparition_menus: + self.window.hide() diff --git a/player.py b/player.py index 7252ae9..b20dce4 100644 --- a/player.py +++ b/player.py @@ -111,6 +111,7 @@ def drawSep(self, window, zoom): :param zoom: :return: """ + sep = (0, 9999999) for lettre, sepSetting in self.sepSetting.items(): @@ -143,7 +144,7 @@ def drawSep(self, window, zoom): window.blit(img, coords) coords[1] += 15 else: - img = font.render(lettre, True, (255, 255, 255)) + img = font.render(lettre, True, (170, 170, 255)) window.blit(img, coords) def draw(self, win, zoom, scroll, vecteurs, vecteurSetting, points): diff --git a/theme.json b/theme.json index 7c6943a..fb06a5b 100644 --- a/theme.json +++ b/theme.json @@ -110,6 +110,27 @@ "active_bg": "#3E3E3E" } }, + "@menuRadar": + { + "misc": { + "border_width": "2", + "shadow_width": "0", + "enable_title_bar": "0" + }, + "colours": + { + "normal_border": "#6B7C91", + "hovered_border": "#6B7C91", + "disabled_border": "#6B7C91", + "selected_border": "#6B7C91", + "active_border": "#6B7C91", + "dark_bg": "#7F94AD", + "normal_text": "#000000", + "hovered_text": "#505050", + "selected_text": "#A0A0A0", + "active_bg":"#5A697A" + } + }, "@etiquette": { "colours": diff --git a/valeurs_config.py b/valeurs_config.py index fd9ed3e..8b28f34 100644 --- a/valeurs_config.py +++ b/valeurs_config.py @@ -11,4 +11,4 @@ listeEtrangers = ['G2', 'M2'] # liste des secteurs ajdacents non interopérables dragDelay = 150 # on utilise cette valeur seuil pour déterminer si on doit cliquer sur un bouton ou drag l'etiquette offsettEtiquetteDefault = 30 # de combien les etiquettes sont décalées en px à quand on les dessine la 1ere fois -temps_disparition_menus = 600 # en combien de milli sec les menus disparaissent après ne plus être survolé +temps_disparition_menus = 300 # en combien de milli sec les menus disparaissent après ne plus être survolé From 0263f97bb24d7c077646b9d4a3519350067c6045 Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:25:45 +0200 Subject: [PATCH 05/15] cercles con sans trique MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ça marche nickel (je suis giga bg en vrai) --- client.py | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/client.py b/client.py index c7acd31..f827b0c 100644 --- a/client.py +++ b/client.py @@ -65,6 +65,10 @@ def main(server_ip: str): alidadPos = (0, 0) curseur_alidad = False + # cercles + curseur_cercles = False + cerclePos = None + # alisep curseur_aliSep = False sepDict = {'A': interface.aliSep('A'), 'B': interface.aliSep('B'), 'C': interface.aliSep('C')} @@ -186,7 +190,9 @@ def main(server_ip: str): pygame.mouse.set_cursor(pygame.cursors.broken_x) elif action == 'Cercles': - pass + cerclePos = None + curseur_cercles = True + pygame.mouse.set_cursor(pygame.cursors.broken_x) # on regarde si notre menu pour le pilote est actif if menuAvion is not None: @@ -307,19 +313,23 @@ def main(server_ip: str): if curseur_alidad: alidad = True alidadPos = pygame.mouse.get_pos() + elif curseur_cercles: + souris = pygame.mouse.get_pos() + cerclePos = ((souris[0] - scroll[0]) / zoom, (souris[1] - scroll[1]) / zoom) - elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3 and curseur_alidad: + elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3 and (curseur_alidad or curseur_cercles or curseur_aliSep): alidad = False curseur_alidad = False - pygame.mouse.set_cursor(pygame.cursors.arrow) - - elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3 and curseur_aliSep: + curseur_cercles = False curseur_aliSep = False pygame.mouse.set_cursor(pygame.cursors.arrow) elif (event.type == pygame.MOUSEBUTTONUP and event.button == 1 and not empecherDragging and not (curseur_aliSep or curseur_alidad) and mouseDownTime + 150 >= pygame.time.get_ticks()): - menuRadar.show() + if curseur_cercles: + curseur_cercles = False + else: + menuRadar.show() manager.process_events(event) @@ -337,7 +347,7 @@ def main(server_ip: str): drag = [pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1]] else: drag = [pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1]] - if not curseur_alidad and not curseur_aliSep: + if not curseur_alidad and not curseur_aliSep and not curseur_cercles: pygame.mouse.set_cursor(pygame.cursors.arrow) """Keys""" @@ -431,6 +441,17 @@ def main(server_ip: str): pygame.draw.line(win, (150, 150, 150), (segment[0][0]*zoom + scroll[0], segment[0][1]*zoom + scroll[1]), (segment[1][0]*zoom + scroll[0], segment[1][1]*zoom + scroll[1]), 1) + # dessin des cercles concentriques + if cerclePos is not None: + + for i in range(15): + + pygame.draw.circle( + win, (120, 120, 120), + (cerclePos[0] * zoom + scroll[0], cerclePos[1] * zoom + scroll[1]), + 10 * i / mapScale * zoom, 1 + ) + # on dessine les points for nom, point in carte['points'].items(): pygame.draw.polygon(win, (155, 155, 155), ((point[0]*zoom + scroll[0], point[1]*zoom - 2 + scroll[1]), (point[0]*zoom + 2 + scroll[0], point[1]*zoom+2 + scroll[1]), (point[0]*zoom-2 + scroll[0], point[1]*zoom+2 + scroll[1])), 1) @@ -438,12 +459,9 @@ def main(server_ip: str): # win.blit(img, (point[0]*zoom + 10 + scroll[0], point[1]*zoom+10 + scroll[1])) # on affiche les avions - if pilote: - for avion in dictAvionsAff.values(): - avion.draw(win, zoom, scroll, vecteurs, vecteurSetting, carte['points']) - else: - for avion in dictAvionsAff.values(): - avion.draw(win, zoom, scroll, vecteurs, vecteurSetting, carte['points']) + + for avion in dictAvionsAff.values(): + avion.draw(win, zoom, scroll, vecteurs, vecteurSetting, carte['points']) # on affiche les boutons manager.update(time_delta) From bc30fe666078a055679f6ff9e155768ab7766e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20de=20la=20Tullaye?= Date: Mon, 30 Sep 2024 23:18:51 +0200 Subject: [PATCH 06/15] =?UTF-8?q?fix:=20=C3=A7a=20tourne=20(un=20peu=20com?= =?UTF-8?q?me=20danieeeeeeeeeelle)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- interface.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/interface.py b/interface.py index 18b478c..a3e21cb 100644 --- a/interface.py +++ b/interface.py @@ -807,11 +807,11 @@ def __init__(self, avion, pos: list[float, float], valeur: str): elif valeur == 'HDG': - cap = round(avion.papa.heading // 5) * 5 + cap = round(avion.papa.heading // 5) * 5 + 5 - self.liste = [*range(0, 365, 5)] + self.liste = [*range(5, 365, 5)] indexDuCap = self.liste.index(cap) - self.listeAff = self.liste[indexDuCap - 3: indexDuCap + 4] + self.listeAff = [self.liste[(indexDuCap - 3 + i) % len(self.liste)] for i in range(7)] objectID = pygame_gui.core.ObjectID('@menuLabel', 'menuBlanc') self.window = pygame_gui.elements.UIWindow(pygame.Rect((x, y), (width, height)), @@ -1100,17 +1100,17 @@ def checkScrolled(self, event): if not rect[0] <= mouse[0] <= rect[0] + rect[2] and rect[1] <= mouse[1] <= rect[1] + rect[3]: return True - if event.y >= 0: # on regarde dans quel sens on scroll - indexDebut = self.liste.index(self.listeAff[0]) # on regarde où commence la liste dans l'autre - if indexDebut - 1 >= 0: # cela vérifie qu'on n'est pas en butée de liste - self.listeAff = self.liste[indexDebut - 1: indexDebut - 1 + len(self.listeAff)] - self.scrollUpdate() + indexDebut = self.liste.index(self.listeAff[0]) + + if event.y >= 0: # on regarde dans quel sens on scroll + newIndex = (indexDebut - 1) % len(self.liste) else: - indexDebut = self.liste.index(self.listeAff[0]) # on regarde où commence la liste dans l'autre - if indexDebut + len(self.listeAff) <= len(self.liste) - 1: # cela vérifie qu'on n'est pas en butée de liste - self.listeAff = self.liste[indexDebut + 1: indexDebut + 1 + len(self.listeAff)] - self.scrollUpdate() + newIndex = (indexDebut + 1) % len(self.liste) + + self.listeAff = [self.liste[(newIndex + i) % len(self.liste)] for i in range(7)] + + self.scrollUpdate() def scrollUpdate(self) -> None: """ From c0180e8b290b51199d9f01012e2a8eccb39480cd Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:47:24 +0200 Subject: [PATCH 07/15] indicateurs emplacement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit les indicateurs d'emplacements fonctionnenet nickel pour arrivées dep --- XML/mapAPS.xml | 63 ++++++++++++++++++++++++++++++++++++++++++------ interface.py | 8 +++--- paquets_avion.py | 12 ++++++--- server.py | 9 ++++--- 4 files changed, 73 insertions(+), 19 deletions(-) diff --git a/XML/mapAPS.xml b/XML/mapAPS.xml index b8cbf92..d5a9a27 100644 --- a/XML/mapAPS.xml +++ b/XML/mapAPS.xml @@ -227,6 +227,7 @@ DEPART SO + LSGG LSGG 120 @@ -298,7 +299,7 @@ TRANSIT - SE + E-SE N BURGO @@ -393,6 +394,7 @@ DEPART SO + LIML LIML 20 @@ -455,7 +457,7 @@ JUVEN - 260 + 260 M2 @@ -489,7 +491,7 @@ SEVET - 250 + 250 G2 @@ -517,7 +519,7 @@ SEVET - 250 + 250 G2 @@ -653,6 +655,7 @@ DEPART + LFVB S BST @@ -683,6 +686,7 @@ DEPART + LFVB SE BST @@ -713,6 +717,7 @@ DEPART + LFVB SO BST @@ -745,34 +750,78 @@ - LOWI + EDDT + EDDF + EKCH + EHAM + ESSB + ENGM + EPWA EGBB EIDW + EGCC + EGGD + EGKK + LFPG + LFPO + LFQQ EGBB + LFPG + LFPO + LFQQ + LFRS + EIDW + EGCC + EGGD + EGKK + BIRK DAAG + DRRN + DTTA + GCTS LPPT + LPPR + LFBD + LFBO + LFBP + LFBT + LFBZ + LEIB + LEMD + LEMG + LEPA + LFKC + LFKJ + + + LGAT LGAV LGIR - + LIMF + LIPZ + - LIML + LOWW + LOWI + LOWS + LHBP diff --git a/interface.py b/interface.py index a3e21cb..83496b2 100644 --- a/interface.py +++ b/interface.py @@ -899,7 +899,7 @@ def __init__(self, avion, pos: list[float, float], valeur: str): self.topContainer.set_dimensions((width, self.headingDCT.get_abs_rect()[3] * 2)) - if self.valeur == 'HDG': # TODO boutons cap abs en blanc + if self.valeur == 'HDG': listeDroite = [] listeGauche = [] @@ -947,14 +947,12 @@ def __init__(self, avion, pos: list[float, float], valeur: str): 'left': 'left', 'left_target': self.containerHdgGauche} ) - tempo = scrollListGen( + self.listeBoutons = scrollListGen( self.listeAff, pygame.Rect((1, 0), (width / 3, -1)), self.listeContainer, sliderBool=False, - objectID=objectID) - - self.listeBoutons = tempo[1] + objectID=objectID)[1] self.containerHdgDroite = pygame_gui.elements.UIScrollingContainer( container=self.window, diff --git a/paquets_avion.py b/paquets_avion.py index 43db78d..de2611a 100644 --- a/paquets_avion.py +++ b/paquets_avion.py @@ -69,8 +69,15 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL= self.callsignFreq = 'Austrian' # TODO ajouter les callsigns - self.provenance = random.choice(gameMap['aeroports'][route['provenance']]) - self.destination = random.choice(gameMap['aeroports'][route['destination']]) + if route['type'] == 'DEPART': + self.provenance = route['provenance'] + else: + self.provenance = random.choice(gameMap['aeroports'][route['provenance']]) + + if self.arrival: + self.destination = route['arrival']['aeroport'] + else: + self.destination = random.choice(gameMap['aeroports'][route['destination']]) # perfo self.turnRate = turnRateDefault @@ -118,7 +125,6 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL= self.XFL = 300 for sortie in self.route['sortie']: - print(sortie['min'] < self.PFL < sortie['max']) if sortie['min'] < self.PFL < sortie['max']: self.nextSector = sortie['name'] diff --git a/server.py b/server.py index 067227a..4307bfb 100644 --- a/server.py +++ b/server.py @@ -156,8 +156,9 @@ y1 = y2 provenance = 'N' destination = 'S' - - if route.find('provenance') is not None: + if routeType == 'DEPART': + provenance = route.find('AD').text + elif route.find('provenance') is not None: provenance = route.find('provenance').text else: print('[Problème] pas de direction de provenance pour la route', nomRoute) @@ -170,7 +171,7 @@ destination = 'S' if route.find('arrival') is not None: - arrival = {'XFL': int(route.find('arrival').text), 'secteur': route.find('arrival').attrib['secteur']} + arrival = {'XFL': int(route.find('arrival').text), 'secteur': route.find('arrival').attrib['secteur'], 'aeroport': route.find('arrival').attrib['AD']} for sortie in route.findall('sortie'): listeSortie.append({'name': sortie.text, 'min': int(sortie.attrib['min']), 'max': int(sortie.attrib['max'])}) gameMap['routes'].update({nomRoute: {'name': nomRoute, @@ -447,7 +448,7 @@ def threaded_ping_responder(): spawn[1]['aircraft'], aircraftType[spawn[1]['aircraft']], spawnRoute, - spawn[1]['arrival'], + spawn[1]['arrival'] == 'True', FL=spawnFL)}) toBeRemovedFromSpawn.append(spawn) planeId += 1 From 920118cadbee166dba0ee4727fccc2fe742f0704 Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:21:10 +0200 Subject: [PATCH 08/15] fix : dessin de la route en direct --- XML/mapAPS.xml | 5 +++ XML/simu.xml | 4 +-- geometry.py | 84 ++++++++++++++++++++++++++++++++++++++++++------ paquets_avion.py | 9 ++---- player.py | 3 +- server.py | 4 ++- 6 files changed, 88 insertions(+), 21 deletions(-) diff --git a/XML/mapAPS.xml b/XML/mapAPS.xml index d5a9a27..20c694f 100644 --- a/XML/mapAPS.xml +++ b/XML/mapAPS.xml @@ -757,10 +757,12 @@ ESSB ENGM EPWA + EGLL EGBB + EGLL EIDW EGCC EGGD @@ -807,6 +809,9 @@ LFKC LFKJ + DAAG + DRRN + DTTA diff --git a/XML/simu.xml b/XML/simu.xml index 0570c15..fb9033f 100644 --- a/XML/simu.xml +++ b/XML/simu.xml @@ -8,8 +8,8 @@ ABISA-BERNI 30000 False - 1375 - 1644 + 1400 + 1300 300 diff --git a/geometry.py b/geometry.py index add4ce4..4920ee7 100644 --- a/geometry.py +++ b/geometry.py @@ -2,6 +2,7 @@ import numpy as np from scipy.optimize import minimize + def calculateHeading(x: int, y: int, xPoint: int, yPoint: int): if y > yPoint: if x > xPoint: @@ -20,17 +21,21 @@ def calculateHeading(x: int, y: int, xPoint: int, yPoint: int): return heading -def calculateDistance(x1: int, y1: int, x2: int, y2: int): +def calculateDistance(x1: int | float, y1: int | float, x2: int | float, y2: int | float): return math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) -def calculateShortestPoint(pointDroite1: list[float, float], pointDroite2: list[float, float], - point: list[float, float]): +def calculateShortestPoint(pointDroite1: list[float, float] | tuple[float, float], + pointDroite2: list[float, float] | tuple[float, float], + point: list[float, float] | tuple[float, float], + segment=False + ): """ Calcule le point sur une droite où la distance ets la plus courte à un point :param pointDroite1: 1er point pour définir la droite, vecteur2 (x, y) :param pointDroite2: 2em point pour définir la droite, vecteur2 (x, y) :param point: point avec lequel on fait le calcul, vecteur2 (x, y) + :param segment: si on doit considérer comme un objet ou comme une droite :return: retourne le point d'intersection du segment et de la droite (x, y) """ @@ -47,13 +52,40 @@ def calculateShortestPoint(pointDroite1: list[float, float], pointDroite2: list[ left_side = np.array([[-coeffdroite1, 1], [-coeffdroitePerp, 1]]) right_side = np.array([ordonnee1, ordonnee2]) else: # si la droite est verticale alors c'est super simple de trouver les coords du point - return pointDroite1[0], point[1] + + solution = pointDroite1[0], point[1] + + if segment: + + if not pointDroite1[1] <= pointDroite2[1]: # on trie les points pour que le 1 ai le y le plus petit + pointDroite1, pointDroite2 = pointDroite2, pointDroite1 + + if point[1] <= pointDroite1[1]: # on vérifie ensuite si le y est ou non compris dans le segment + solution = pointDroite1 + + elif point[1] >= pointDroite2[1]: + solution = pointDroite2 + + return solution # solve for x and y - return np.linalg.inv(left_side).dot(right_side) + solution = np.linalg.inv(left_side).dot(right_side) + + if segment: + if not pointDroite1[0] <= pointDroite2[0]: # on trie les points pour que le 1 ai le x le plus petit + pointDroite1, pointDroite2 = pointDroite2, pointDroite1 + + if solution[0] <= pointDroite1[0]: # on vérifie ensuite si le x est ou non compris dans le segment + solution = pointDroite1 + elif solution[0] >= pointDroite2[0]: + solution = pointDroite2 -def calculateIntersection(point1Droite, point2Droite, point1Droite2, point2Droite2) -> tuple[float, float]: + return solution + + +def calculateIntersection(point1Droite, point2Droite, + point1Droite2, point2Droite2) -> tuple[float, float]: """ Calcule l'intersection entre deux droites @@ -142,16 +174,48 @@ def distanceMinie(pos1: tuple[float, float], vitesse1: float, heading1: float, x0 = 1.0 caca = minimize( - distanceEnFduTemps, x0, args=(pos1, vitesse1, heading1, pos2, vitesse2, heading2), + distanceMiniEnFduTemps, x0, args=(pos1, vitesse1, heading1, pos2, vitesse2, heading2), method='Nelder-Mead', tol=1e-4 ) return caca.x[0] -def distanceEnFduTemps(temps, pos1: tuple[float, float], vitesse1: float, heading1: float, - pos2: tuple[float, float], vitesse2: float, heading2: float): +def distanceMiniEnFduTemps(temps, pos1: tuple[float, float], vitesse1: float, heading1: float, + pos2: tuple[float, float], vitesse2: float, heading2: float): return math.sqrt( ((pos1[0] + vitesse1 * temps * math.cos(heading1)) - (pos2[0] + vitesse2 * temps * math.cos(heading2))) ** 2 + ((pos1[1] + vitesse1 * temps * math.sin(heading1)) - (pos2[1] + vitesse2 * temps * math.sin(heading2))) ** 2 - ) \ No newline at end of file + ) + + +def findClosestSegment(route: list, position: tuple[float, float], points: dict): + """ + Retourne le 2em point du segment de la route le plus proche de notre position + :param route: la route qu'on analyse + :param position: la position qu'on veut comparer + :param points: la carte du jeu + :return: + """ + + closest = route[0] + distance = 99999999 + + for index in range(len(route) - 1): # dans cette boucle, on cherche à quel segment on est le plus proche + point = route[index] + point2 = route[index + 1] + coords1 = (points[point['name']][0], points[point['name']][1]) + coords2 = (points[point2['name']][0], points[point2['name']][1]) + + # d'abord, on trouve le point le plus proche de notre pos sur ce segment + intersection = calculateShortestPoint( + coords1, coords2, position, True) + + disancte = calculateDistance(position[0], position[1], intersection[0], intersection[1]) + + if disancte <= distance: + + closest = point2 + distance = disancte + + return closest diff --git a/paquets_avion.py b/paquets_avion.py index de2611a..1da9c7d 100644 --- a/paquets_avion.py +++ b/paquets_avion.py @@ -1,3 +1,4 @@ +import geometry from geometry import * from valeurs_config import * import random @@ -88,12 +89,8 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL= self.route = route self.headingMode = False - # TODO changer ça pour pouvoir mettre un avion nimporte ou sur la route - if calculateDistance(self.x, self.y, gameMap['points'][self.route['points'][0]['name']][0], - gameMap['points'][self.route['points'][0]['name']][1]) <= 4 * self.speedPx: - self.nextPoint = self.route['points'][1] - else: - self.nextPoint = self.route['points'][0] + + self.nextPoint = geometry.findClosestSegment(route['points'], (self.x, self.y), gameMap['points']) self.evolution = 0 # taux de variation/radar refresh self.altitudeEvoTxt = '-' diff --git a/player.py b/player.py index b20dce4..2a49644 100644 --- a/player.py +++ b/player.py @@ -321,10 +321,9 @@ def drawRoute(self, points, win, zoom, scroll): :param scroll: le scroll format [x, y] :return: """ - # TODO route qui se dessine correctement même quand on est en direct route = self.papa.route['points'] # on n'a besoin que des noms des points - nextPoint = self.papa.nextPoint + nextPoint = geometry.findClosestSegment(route, (self.papa.x, self.papa.y), points) point1 = points[route[route.index(nextPoint) - 1]['name']][:2] point2 = points[nextPoint['name']][:2] diff --git a/server.py b/server.py index 4307bfb..4b74bc0 100644 --- a/server.py +++ b/server.py @@ -449,7 +449,9 @@ def threaded_ping_responder(): aircraftType[spawn[1]['aircraft']], spawnRoute, spawn[1]['arrival'] == 'True', - FL=spawnFL)}) + FL=spawnFL, + x=spawn[1]['x'], + y=spawn[1]['y'])}) toBeRemovedFromSpawn.append(spawn) planeId += 1 From dcd9c077b6a2908eb88b979a9a1b8ac7d079e3ef Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Tue, 1 Oct 2024 20:13:58 +0200 Subject: [PATCH 09/15] frequences les frequences s'affichent nickel --- XML/mapAPS.xml | 42 ++++++++++++++++++++++++++++++++++++++---- client.py | 6 +++--- interface.py | 3 ++- paquets_avion.py | 13 +++++++------ player.py | 4 ++-- server.py | 28 ++++++++++++++++++++-------- valeurs_config.py | 2 -- 7 files changed, 72 insertions(+), 26 deletions(-) diff --git a/XML/mapAPS.xml b/XML/mapAPS.xml index 20c694f..b6b6b84 100644 --- a/XML/mapAPS.xml +++ b/XML/mapAPS.xml @@ -6,6 +6,40 @@ 245 # plancher de notre secteur 365 # plafond + # liste des secteurs adjacents + + 125.830 + + + 127.840 + + + 128.050 + + + 131.175 + + + 132.740 + + + 119.275 + + + 124.080 + + + 134.610 + + + 130.275 + True + + + 127.675 + True + + @@ -162,8 +196,8 @@ - - + + 1109 915 @@ -220,8 +254,8 @@ 1107 1266 - - + + diff --git a/client.py b/client.py index f827b0c..61ae622 100644 --- a/client.py +++ b/client.py @@ -429,12 +429,12 @@ def main(server_ip: str): win.fill((90, 90, 90)) # on dessine les secteurs - for secteur in carte['secteurs']: + for zone in carte['zones']: liste_affichage_secteurs = [] - for point in secteur['contour']: + for point in zone['contour']: pos = positionAffichage(point[0], point[1], zoom, scroll[0], scroll[1]) liste_affichage_secteurs.append((pos[0], pos[1])) - pygame.draw.polygon(win, secteur['couleur'], liste_affichage_secteurs) + pygame.draw.polygon(win, zone['couleur'], liste_affichage_secteurs) # on dessine les routes for segment in carte['segments']['TRANSIT']: diff --git a/interface.py b/interface.py index 83496b2..07d8379 100644 --- a/interface.py +++ b/interface.py @@ -542,6 +542,7 @@ def update(self, avion): self.DCT.set_text("h") self.XPT.set_text(avion.papa.XPT) + self.nextSector.set_text(avion.papa.nextSector) # alti self.AFL.set_text(str(round(avion.papa.altitude / 100)) + " " + avion.papa.altitudeEvoTxt) @@ -1106,7 +1107,7 @@ def checkScrolled(self, event): else: newIndex = (indexDebut + 1) % len(self.liste) - self.listeAff = [self.liste[(newIndex + i) % len(self.liste)] for i in range(7)] + self.listeAff = [self.liste[(newIndex + i) % len(self.liste)] for i in range(len(self.listeAff))] self.scrollUpdate() diff --git a/paquets_avion.py b/paquets_avion.py index 1da9c7d..fb10496 100644 --- a/paquets_avion.py +++ b/paquets_avion.py @@ -128,7 +128,8 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL= if not self.nextSector: # si on n'a pas réussi à mettre un secteur suivant, on met un défaut pour pas crash self.nextSector = secteurDefault - self.nextFrequency = '127.675' # TODO faire les fréquences automatiques + self.nextFrequency = gameMap['secteurs'][self.nextSector]['frequence'] + self.etranger = gameMap['secteurs'][self.nextSector]['etranger'] self.CFL = None @@ -156,19 +157,19 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL= self.clearedHeading = None self.clearedRate = None - def changeXFL(self) -> None: + def changeXFL(self, carte) -> None: """ Change le XFL en fonction du PFL. À utliser quand le PFL change :return: """ - print(self.PFL) if self.PFL > 365 and not self.arrival: self.nextSector = "RU" self.XFL = 360 elif not self.arrival: self.XFL = self.PFL + self.changeSortieSecteur(carte) - def changeSortieSecteur(self) -> None: + def changeSortieSecteur(self, carte) -> None: """ Change le secteur de sortie. À utiliser quand le XFL change :return: @@ -178,6 +179,8 @@ def changeSortieSecteur(self) -> None: if sortie['min'] < self.XFL < sortie['max']: self.nextSector = sortie['name'] break + self.etranger = carte['secteurs'][self.nextSector]['etranger'] + self.nextFrequency = carte['secteurs'][self.nextSector]['frequence'] def updateEtatFreq(self, nouvelEtat=None) -> None: """ @@ -238,8 +241,6 @@ def move(self, gameMap): if ancien['name'] == self.DCT: # si le point clairé est celui qu'on passe self.DCT = self.nextPoint['name'] # alors on passe au point suivant aussi - - self.selectedHeading = calculateHeading(self.x, self.y, gameMap['points'][self.nextPoint['name']][0], gameMap['points'][self.nextPoint['name']][1]) diff --git a/player.py b/player.py index 2a49644..832ac1f 100644 --- a/player.py +++ b/player.py @@ -334,9 +334,9 @@ def drawRoute(self, points, win, zoom, scroll): for point in route: pointDeux = [points[point['name']][0], points[point['name']][1]] - pygame.draw.line(win, (25, 25, 170), + pygame.draw.line(win, (46, 80, 174), (pointUn[0] * zoom + scroll[0], pointUn[1] * zoom + scroll[1]), - (pointDeux[0] * zoom + scroll[0], pointDeux[1] * zoom + scroll[1]), 2) + (pointDeux[0] * zoom + scroll[0], pointDeux[1] * zoom + scroll[1]), 3) pointUn = pointDeux # on passe au prochain point diff --git a/server.py b/server.py index 4b74bc0..245eaad 100644 --- a/server.py +++ b/server.py @@ -50,7 +50,7 @@ dictAvion = {} # dict contenant tous les avions requests = [] # liste des requêtes que le serveur doit gérer segments = {} -gameMap = {'points': {}, 'secteurs': [], 'segments': [], 'routes': {}, 'mapScale': 0} +gameMap = {'points': {}, 'zones': [], 'segments': [], 'routes': {}, 'mapScale': 0} # XML map loading @@ -73,19 +73,32 @@ gameMap['points'].update({name: (x, y, balise)}) -for secteur in root.find('secteurs'): +for zone in root.find('zones'): contour = [] # liste des points délimitant le contour du secteur, dans l'ordre de lecture xml - for limite in secteur.findall('limite'): + for limite in zone.findall('limite'): x = int(limite.find('x').text) y = int(limite.find('y').text) contour.append((x, y)) - gameMap['secteurs'].append({'couleur': [int(x) for x in secteur.attrib['color'].split(',')], 'contour': contour}) + gameMap['zones'].append({'couleur': [int(x) for x in zone.attrib['color'].split(',')], 'contour': contour}) -listeAeroports = {} +dictSecteurs = {} +for secteur in root.find('secteurs'): + + nom = secteur.attrib['name'] + frequence = secteur.find('frequence').text + etranger = False + if secteur.find('etranger') is not None: + if secteur.find('etranger').text == 'True': + etranger = True + dictSecteurs.update({nom: {'frequence': frequence, 'etranger': etranger}}) + +gameMap.update({'secteurs': dictSecteurs}) + +listeAeroports = {} for direction in root.find('Aeroports'): liste_de_cette_direction = [] @@ -365,8 +378,7 @@ def threaded_ping_responder(): dictAvion[req[0]].selectedAlti = req[2] elif req[1] == 'PFL': dictAvion[req[0]].PFL = req[2] - dictAvion[req[0]].changeXFL() - dictAvion[req[0]].changeSortieSecteur() + dictAvion[req[0]].changeXFL(gameMap) elif req[1] == 'CFL': dictAvion[req[0]].CFL = req[2] elif req[1] == 'C_IAS': @@ -381,7 +393,7 @@ def threaded_ping_responder(): dictAvion[req[0]].clearedRate = None elif req[1] == 'XFL': dictAvion[req[0]].XFL = req[2] - dictAvion[req[0]].changeSortieSecteur() + dictAvion[req[0]].changeSortieSecteur(gameMap) elif req[1] == 'XPT': dictAvion[req[0]].XPT = req[2] elif req[1] == 'HDG': diff --git a/valeurs_config.py b/valeurs_config.py index 8b28f34..b56adb9 100644 --- a/valeurs_config.py +++ b/valeurs_config.py @@ -6,9 +6,7 @@ acceldefault = 3 # accélération/decelération de kt par refresh turnRateDefault = 10 # turnrate/refresh par défault liste_etat_freq = ['previousFreq', 'previousShoot', 'inFreq', 'nextCoord', 'nextShoot', 'nextFreq'] -secteurBoundaries = [245, 365] # niveau planché et plafond du secteur plotSize = 5 # taille des plots avions -listeEtrangers = ['G2', 'M2'] # liste des secteurs ajdacents non interopérables dragDelay = 150 # on utilise cette valeur seuil pour déterminer si on doit cliquer sur un bouton ou drag l'etiquette offsettEtiquetteDefault = 30 # de combien les etiquettes sont décalées en px à quand on les dessine la 1ere fois temps_disparition_menus = 300 # en combien de milli sec les menus disparaissent après ne plus être survolé From c7d2aa7a91eac13159a63101a545ed8bd1dfbc93 Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Wed, 2 Oct 2024 23:56:52 +0200 Subject: [PATCH 10/15] =?UTF-8?q?visuel=20cr=C3=A9ateur=20de=20conflits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dsq --- XML/mapAPS.xml | 3 + client.py | 38 ++++++++- geometry.py | 19 ++--- interface.py | 89 ++------------------- outils_radar.py | 198 ++++++++++++++++++++++++++++++++++++++++++++++ paquets_avion.py | 14 +++- player.py | 35 +++++--- valeurs_config.py | 1 + 8 files changed, 292 insertions(+), 105 deletions(-) create mode 100644 outils_radar.py diff --git a/XML/mapAPS.xml b/XML/mapAPS.xml index b6b6b84..c2944ed 100644 --- a/XML/mapAPS.xml +++ b/XML/mapAPS.xml @@ -25,6 +25,9 @@ 119.275 + + 124.2 + 124.080 diff --git a/client.py b/client.py index 61ae622..176ead2 100644 --- a/client.py +++ b/client.py @@ -1,5 +1,6 @@ import pygame import horloge +import outils_radar from network import Network import server_browser from player import * @@ -7,6 +8,7 @@ import interface from paquets_avion import * import math +import outils_radar # recherche de tous les serveurs sur le réseau address = server_browser.serverBrowser() @@ -34,6 +36,8 @@ def main(server_ip: str): distance = 10 # menus + conflitBool = False + conflitGen = None menuAvion = None menuATC = None menuValeurs = None @@ -71,7 +75,7 @@ def main(server_ip: str): # alisep curseur_aliSep = False - sepDict = {'A': interface.aliSep('A'), 'B': interface.aliSep('B'), 'C': interface.aliSep('C')} + sepDict = {'A': outils_radar.aliSep('A'), 'B': outils_radar.aliSep('B'), 'C': outils_radar.aliSep('C')} # scroll and zoom zoomDef = 0.5 @@ -239,7 +243,9 @@ def main(server_ip: str): else: for avion in dictAvionsAff.values(): # pour chaque avion - action = avion.checkEvent(event, pilote) # on vérifie si l'event est associé avec ses boutons + action = avion.checkEvent(event, pilote, conflitBool) + + # on vérifie si l'event est associé avec ses boutons if type(action) in [list, tuple]: # si c'est un tuple alors cela correspond à une requête localRequests.append(action) @@ -262,6 +268,7 @@ def main(server_ip: str): # on vérifie que newPlane n'est pas None (les valeurs ont été renvoyés) if newPlaneData: + # on crée alors un nouvel avion FL = None PFL = None @@ -281,7 +288,11 @@ def main(server_ip: str): FL=FL, PFL=PFL) - localRequests.append((len(dictAvions), "Add", newPlane)) + if newPlaneData['conflit']: + conflitGen = outils_radar.conflictGenerator(win, newPlane) + conflitBool = True + else: + localRequests.append((len(dictAvions), "Add", newPlane)) elif event.type == pygame_gui.UI_TEXT_ENTRY_CHANGED: nouvelAvionWin.checkFields(event) @@ -331,11 +342,18 @@ def main(server_ip: str): else: menuRadar.show() + elif event.type == pygame.MOUSEBUTTONUP and event.button == 2 and not empecherDragging and conflitGen: + mouse = pygame.mouse.get_pos() + conflitGen.computeSpawn(((mouse[0] - scroll[0]) / zoom, (mouse[1] - scroll[1]) / zoom), carte) + manager.process_events(event) if menuAvion is not None: menuAvion.checkSliders() + if conflitGen is not None: + conflitGen.checkScrollBar() + """Dragging""" if (pygame.mouse.get_pressed()[0] and not empecherDragging and @@ -460,6 +478,20 @@ def main(server_ip: str): # on affiche les avions + if conflitGen is not None: + conflitGen.draw(win, zoom, scroll) + color = [10, 10, 10] + for avion in dictAvionsAff.values(): + if color[0] <= 255 - 40: + color[0] += 70 + elif color[1] <= 255 - 40: + color[0] = 255 + color[1] += 70 + elif color[2] <= 255 - 40: + color[1] = 255 + color[2] += 70 + avion.drawEstimatedRoute(carte['points'], conflitGen.temps, color, win, zoom, scroll) + for avion in dictAvionsAff.values(): avion.draw(win, zoom, scroll, vecteurs, vecteurSetting, carte['points']) diff --git a/geometry.py b/geometry.py index 4920ee7..f28905a 100644 --- a/geometry.py +++ b/geometry.py @@ -189,16 +189,17 @@ def distanceMiniEnFduTemps(temps, pos1: tuple[float, float], vitesse1: float, he ) -def findClosestSegment(route: list, position: tuple[float, float], points: dict): +def findClosestSegment(route: list, position: tuple[float, float], points: dict) -> tuple: """ - Retourne le 2em point du segment de la route le plus proche de notre position - :param route: la route qu'on analyse - :param position: la position qu'on veut comparer - :param points: la carte du jeu + Retourne les 2 points du segment de la route le plus proche de notre position dans l'ordre de la route. + :param route: La route qu'on analyse + :param position: La position qu'on veut comparer + :param points: La carte du jeu :return: """ - closest = route[0] + start = route[0] + end = route[0] distance = 99999999 for index in range(len(route) - 1): # dans cette boucle, on cherche à quel segment on est le plus proche @@ -214,8 +215,8 @@ def findClosestSegment(route: list, position: tuple[float, float], points: dict) disancte = calculateDistance(position[0], position[1], intersection[0], intersection[1]) if disancte <= distance: - - closest = point2 + start = point + end = point2 distance = disancte - return closest + return start, end diff --git a/interface.py b/interface.py index 07d8379..5cc59e0 100644 --- a/interface.py +++ b/interface.py @@ -67,7 +67,7 @@ class nouvelAvionWindow: def __init__(self, routes, avions): # le dictionnaire utilisé pour renvoyer les valeurs sélectionnées par nos boutons - self.returnValues = {'indicatif': 'FCACA', 'avion': 'B738', 'arrival': False} + self.returnValues = {'indicatif': 'FCACA', 'avion': 'B738', 'arrival': False, 'conflit': False} # la fenêtre du menu self.window = pygame_gui.elements.UIWindow(pygame.Rect((250, 250), (600, 400))) @@ -172,6 +172,13 @@ def checkEvent(self, event): else: self.arrivalBouton.unselect() + elif event.ui_element == self.conflitsBouton: + self.returnValues['conflit'] = not self.returnValues['conflit'] + if not self.conflitsBouton.is_selected: + self.conflitsBouton.select() + else: + self.conflitsBouton.unselect() + elif event.ui_element == self.validerBouton: self.window.kill() return self.returnValues @@ -1273,86 +1280,6 @@ def checkAlive(self): return self.window.alive() -class aliSep: - - def __init__(self, lettre): - self.lettre = lettre - self.avion1 = None - self.avion2 = None - self.distance = None - self.temps = None - - def linkAvion(self, avion, carte) -> bool: - - """ - Associe un avion. Si un avion est déjà associé alors celà déclenche le calcul de la sep - :param avion: l'avion à associer - :param carte: les données de la carte - :return: si les deux avions ont été associés, renvoies True - """ - - if self.avion2: - return True - - if not self.avion1: - self.avion1 = avion - return False - - self.avion2 = avion - - self.avion1.sep = True - self.avion2.sep = True - - self.calculation(carte) - - return True - - def calculation(self, carte): - - if not self.avion2: - return None - - self.temps = geometry.distanceMinie( - (self.avion1.papa.x, self.avion1.papa.y), self.avion1.papa.speedPx / radarRefresh, - self.avion1.papa.headingRad, - (self.avion2.papa.x, self.avion2.papa.y), self.avion2.papa.speedPx / radarRefresh, - self.avion2.papa.headingRad, - ) - - self.distance = math.sqrt( - ((self.avion1.papa.x + self.avion1.papa.speedPx / radarRefresh * self.temps * math.cos( - self.avion1.papa.headingRad)) - - (self.avion2.papa.x + self.avion2.papa.speedPx / radarRefresh * self.temps * math.cos( - self.avion2.papa.headingRad))) ** 2 + - ((self.avion1.papa.y + self.avion1.papa.speedPx / radarRefresh * self.temps * math.sin( - self.avion1.papa.headingRad)) - - (self.avion2.papa.y + self.avion2.papa.speedPx / radarRefresh * self.temps * math.sin( - self.avion2.papa.headingRad))) ** 2) - - self.avion1.sepSetting.update({self.lettre: [self.temps, self.distance * carte['mapScale']]}) - self.avion2.sepSetting.update({self.lettre: [self.temps, self.distance * carte['mapScale']]}) - - def kill(self): - - if not self.avion2 and self.avion1: - self.avion1 = None - return None - - if not self.avion1: - return None - - self.avion1.sepSetting.pop(self.lettre) - self.avion2.sepSetting.pop(self.lettre) - - if len(self.avion1.sepSetting) == 0: - self.avion1.sep = False - if len(self.avion2.sepSetting) == 0: - self.avion2.sep = False - - self.avion1 = None - self.avion2 = None - - class menuRadar: def __init__(self): diff --git a/outils_radar.py b/outils_radar.py new file mode 100644 index 0000000..bf96906 --- /dev/null +++ b/outils_radar.py @@ -0,0 +1,198 @@ +import pygame +import pygame_gui + +import geometry +import math +from valeurs_config import * + + +class aliSep: + + def __init__(self, lettre): + self.lettre = lettre + self.avion1 = None + self.avion2 = None + self.distance = None + self.temps = None + + def linkAvion(self, avion, carte) -> bool: + + """ + Associe un avion. Si un avion est déjà associé alors celà déclenche le calcul de la sep + :param avion: l'avion à associer + :param carte: les données de la carte + :return: si les deux avions ont été associés, renvoies True + """ + + if self.avion2: + return True + + if not self.avion1: + self.avion1 = avion + return False + + self.avion2 = avion + + self.avion1.sep = True + self.avion2.sep = True + + self.calculation(carte) + + return True + + def calculation(self, carte): + + if not self.avion2: + return None + + self.temps = geometry.distanceMinie( + (self.avion1.papa.x, self.avion1.papa.y), self.avion1.papa.speedPx / radarRefresh, + self.avion1.papa.headingRad, + (self.avion2.papa.x, self.avion2.papa.y), self.avion2.papa.speedPx / radarRefresh, + self.avion2.papa.headingRad, + ) + + self.distance = math.sqrt( + ((self.avion1.papa.x + self.avion1.papa.speedPx / radarRefresh * self.temps * math.cos( + self.avion1.papa.headingRad)) - + (self.avion2.papa.x + self.avion2.papa.speedPx / radarRefresh * self.temps * math.cos( + self.avion2.papa.headingRad))) ** 2 + + ((self.avion1.papa.y + self.avion1.papa.speedPx / radarRefresh * self.temps * math.sin( + self.avion1.papa.headingRad)) - + (self.avion2.papa.y + self.avion2.papa.speedPx / radarRefresh * self.temps * math.sin( + self.avion2.papa.headingRad))) ** 2) + + self.avion1.sepSetting.update({self.lettre: [self.temps, self.distance * carte['mapScale']]}) + self.avion2.sepSetting.update({self.lettre: [self.temps, self.distance * carte['mapScale']]}) + + def kill(self): + + if not self.avion2 and self.avion1: + self.avion1 = None + return None + + if not self.avion1: + return None + + self.avion1.sepSetting.pop(self.lettre) + self.avion2.sepSetting.pop(self.lettre) + + if len(self.avion1.sepSetting) == 0: + self.avion1.sep = False + if len(self.avion2.sepSetting) == 0: + self.avion2.sep = False + + self.avion1 = None + self.avion2 = None + + +class conflictGenerator: + + def __init__(self, win, avion): + + size = win.get_size() + width = size[0] / 3 + height = 40 + + self.slider = pygame_gui.elements.UIHorizontalScrollBar( + pygame.Rect((size[0] / 2 - width / 2, 10), (width, height)), + visible_percentage=0.3, + + ) + self.valider = pygame_gui.elements.UIButton( + pygame.Rect((size[0] / 2 + width / 2 + 10, 10), (height, height)), + text='OK' + ) + + self.avion = None + self.temps = 0 + self.maxTemps = 60 * 60 # temps en sec, donc 40 min au max + self.avion = avion + self.x = None + self.y = None + self.spawnDelay = None + self.drawListe = None + + def checkScrollBar(self): + + """Ajuste la valeur de temps en fonction du slider s'il est scrollé""" + + if self.slider.has_moved_recently: + self.temps = self.slider.start_percentage * self.maxTemps + + def computeSpawn(self, pos: list[float, float] | tuple[float, float], carte): + """ + Change la position, ou le delay de spawn de l'avion en fonction de la position voulue et des perfos + :param pos: La position de conflit choisie + :param carte: La carte du jeu + :return: + """ + points = carte['points'] + route = self.avion.route['points'] + distance = self.temps * self.avion.speedPx / radarRefresh # quelle distance va parcourir l'avion en ce temps + distance_calcule = 0 + + point2 = points[route[0]['name']] + + p = geometry.findClosestSegment(self.avion.route['points'], pos, carte['points'])[0] + + for index in range(len(route[:route.index(p)])): + point1 = points[route[index]['name']] + point2 = points[route[index + 1]['name']] + distance_calcule += geometry.calculateDistance(point1[0], point1[1], point2[0], point2[1]) + + offroadDistance = geometry.calculateDistance(pos[0], pos[1], point2[0], point2[1]) + distance_calcule += offroadDistance + + a = list(range(len(route[:route.index(p) + 1]))) + self.drawListe = [] + + if distance_calcule <= distance: # si on doit parcourir plus que ce qu'on a calculé au spawn + # alors on delay le spawn, temps ici en sec + self.spawnDelay = (distance_calcule - distance) / self.avion.speedPx * radarRefresh + self.x = points[route[0]['name']][0] + self.y = points[route[0]['name']][1] + + for index in a: + self.drawListe.append(points[route[index]['name']]) + + else: # si on doit parcourir moins, alors on fait apparaître l'avion plus proche du secteur + self.spawnDelay = 0 + distanceAparcourir = distance_calcule - distance + index = 0 + found = False + for index in a: + point1 = points[route[index]['name']] + point2 = points[route[index + 1]['name']] + legDistance = geometry.calculateDistance(point1[0], point1[1], point2[0], point2[1]) + + if found: + self.drawListe.append(point1) + + elif legDistance >= distanceAparcourir: # si on doit faire apparaître sur cette branche + ratio = distanceAparcourir / legDistance + self.x = ratio * (point2[0] - point1[0]) + point1[0] + self.y = ratio * (point2[1] - point1[1]) + point1[1] + self.drawListe.append((self.x, self.y)) + found = True + + else: + distanceAparcourir -= legDistance + + self.drawListe.append(pos) + + def draw(self, win, zoom, scroll) -> None: + if self.x is None: + return None + pygame.draw.circle(win, (255, 255, 0), (self.x * zoom + scroll[0], self.y * zoom + scroll[1]), 3) + for index in range(len(self.drawListe) - 1): + point1 = self.drawListe[index] + point2 = self.drawListe[index + 1] + pygame.draw.line(win, (255, 255, 0), + (point1[0] * zoom + scroll[0], point1[1] * zoom + scroll[1]), + (point2[0] * zoom + scroll[0], point2[1] * zoom + scroll[1])) + + def kill(self): + self.valider.kill() + self.slider.kill() + return self.avion diff --git a/paquets_avion.py b/paquets_avion.py index fb10496..a8581d7 100644 --- a/paquets_avion.py +++ b/paquets_avion.py @@ -90,7 +90,7 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL= self.headingMode = False - self.nextPoint = geometry.findClosestSegment(route['points'], (self.x, self.y), gameMap['points']) + self.nextPoint = geometry.findClosestSegment(route['points'], (self.x, self.y), gameMap['points'])[1] self.evolution = 0 # taux de variation/radar refresh self.altitudeEvoTxt = '-' @@ -194,6 +194,8 @@ def updateEtatFreq(self, nouvelEtat=None) -> None: else: i = liste_etat_freq.index(self.etatFrequence) if i != len(liste_etat_freq) - 1: # on vérifie que ce n'est pas le dernier état fréquence + if self.etranger and self.etatFrequence == 'nextCoord': + i += 1 self.etatFrequence = liste_etat_freq[i + 1] def updateAlti(self): @@ -225,6 +227,12 @@ def updateAlti(self): self.evolution = 0 def move(self, gameMap): + + # frequence update + if self.etatFrequence == 'inFreq': + + if self.calculeEstimate(gameMap['points'], self.XPT) <= 60 * valeurCoord: # si on sort dans moins de 6min + self.updateEtatFreq() # heading update if not self.headingMode: # si l'avion est en direct et pas en cap @@ -239,7 +247,7 @@ def move(self, gameMap): ancien = self.nextPoint # pour la comparaison après self.nextPoint = self.route['points'][self.route['points'].index(self.nextPoint) + 1] if ancien['name'] == self.DCT: # si le point clairé est celui qu'on passe - self.DCT = self.nextPoint['name'] # alors on passe au point suivant aussi + self.DCT = self.nextPoint['name'] # alors, on passe au point suivant aussi self.selectedHeading = calculateHeading(self.x, self.y, gameMap['points'][self.nextPoint['name']][0], gameMap['points'][self.nextPoint['name']][1]) @@ -274,7 +282,7 @@ def move(self, gameMap): self.x += self.speedPx * math.cos(self.headingRad) self.y += self.speedPx * math.sin(self.headingRad) - def calculeEstimate(self, points: dict, pointVoulu: str) -> None: + def calculeEstimate(self, points: dict, pointVoulu: str) -> float: """ Calcule le temps à un point sur notre route. Pour avoir l'estimée, il faudra rajouter l'heure courante :param points: dict des points de la carte diff --git a/player.py b/player.py index 832ac1f..c9a14a7 100644 --- a/player.py +++ b/player.py @@ -60,6 +60,7 @@ def __init__(self, Id: int, papa, zoom: float, scroll: list[float, float]): self.etiquetteExtended = False self.lastHoveredTime = 0 self.pointDessinDirect = None + self.conflitSelected = False self.drag = False # if true l'etiquette se fait drag self.dragOffset = (0, 0) # le décalage de l'etiquette par rapport au curseur self.startPressTime = 0 @@ -262,25 +263,29 @@ def drawDirect(self, points, point, win, zoom: float, scroll: list[float, float] coord = [points[point][0] * zoom + scroll[0], points[point][1] * zoom + scroll[1]] pygame.draw.line(win, (0, 206, 209), (self.affX + plotSize, self.affY + plotSize), coord) - def drawEstimatedRoute(self, points, temps, win, zoom, scroll): + def drawEstimatedRoute(self, points, temps, color, win, zoom, scroll): """ Dessine la route future de l'avion jusuq'à un certain point défini par une valeur de temps C'est une bonne approximation de la future position de l'avion, à vitesse constante :param points: la liste des points récupérer les coords - :param temps: combien de temps doit faire la route dessinée + :param temps: combien de temps doit faire la route dessinée en sec + :param color: La couleur du tracé :param win: l'écran pygame :param zoom: le niveau de zoom :param scroll: le scroll format [x, y] :return: """ + if not self.conflitSelected: + return None + route = self.papa.route['points'] # on n'a besoin que des noms des points nextPoint = self.papa.nextPoint ratio = 0 route = route[route.index(nextPoint):] # on ne considère que la route devant l'avion pointUn = [self.papa.x, self.papa.y] # on commence à dessiner à partir de l'avion - distance = temps * self.papa.speedPx # on établit la distance de la route avec notre vitesse + distance = temps * self.papa.speedPx / radarRefresh # on établit la distance de la route avec notre vitesse for point in route: pointDeux = [points[point['name']][0], points[point['name']][1]] @@ -296,18 +301,18 @@ def drawEstimatedRoute(self, points, temps, win, zoom, scroll): pointUn[1] + (pointDeux[1] - pointUn[1]) * ratio] # on dessine alors la dernière branche - pygame.draw.line(win, (0, 255, 0), + pygame.draw.line(win, color, (pointUn[0] * zoom + scroll[0], pointUn[1] * zoom + scroll[1]), - (pointDeux[0] * zoom + scroll[0], pointDeux[1] * zoom + scroll[1])) + (pointDeux[0] * zoom + scroll[0], pointDeux[1] * zoom + scroll[1]), 2) self.predictionPoint = pointDeux break # on casse la boucle for, pas la peine de faire des calculs pour plus loin, la prédi est finie else: # si le trajet s'arrête après la branche, on dessine la branche en entier - pygame.draw.line(win, (0, 255, 0), + pygame.draw.line(win, color, (pointUn[0] * zoom + scroll[0], pointUn[1] * zoom + scroll[1]), - (pointDeux[0] * zoom + scroll[0], pointDeux[1] * zoom + scroll[1])) + (pointDeux[0] * zoom + scroll[0], pointDeux[1] * zoom + scroll[1]), 2) distance -= legDistance # on enlève la distance de la branche parcourue à la distance à parcourir pointUn = pointDeux # on passe au prochain point @@ -323,7 +328,7 @@ def drawRoute(self, points, win, zoom, scroll): """ route = self.papa.route['points'] # on n'a besoin que des noms des points - nextPoint = geometry.findClosestSegment(route, (self.papa.x, self.papa.y), points) + nextPoint = geometry.findClosestSegment(route, (self.papa.x, self.papa.y), points)[1] point1 = points[route[route.index(nextPoint) - 1]['name']][:2] point2 = points[nextPoint['name']][:2] @@ -353,10 +358,11 @@ def checkClicked(self, event) -> bool: else: return False - def checkEvent(self, event, pilote): + def checkEvent(self, event, pilote, conflitBool): """ Vérifie si un bouton associé à l'avion correspond à l'event + :param conflitBool: Si ou non, on est en mode création de conflits :param event: événement à vérifier :param pilote: si l'interface est en mode pilote ou non :return: @@ -364,10 +370,16 @@ def checkEvent(self, event, pilote): # on vérifie que le bouton est bien associé à l'etiquette if event.ui_element.ui_container == self.etiquette.container: + self.startPressTime = 0 if self.drag: self.drag = False return None # comme on était en train de drag, on ne fait aucune action liée au bouton + + if conflitBool: + self.conflitSelected = not self.conflitSelected + return None + if event.mouse_button == 2 and not pilote and event.ui_element is not self.etiquette.DCT: # si c'est un clic milieu, alors on surligne ou non le bouton @@ -384,6 +396,11 @@ def checkEvent(self, event, pilote): return self.Id, 'HighlightBouton', (indexLigne, index) if event.ui_element == self.bouton: + + if conflitBool: + self.conflitSelected = not self.conflitSelected + return None + if event.mouse_button == 2 and not pilote: # clic milieu return self.Id, 'Warning' diff --git a/valeurs_config.py b/valeurs_config.py index b56adb9..b6a6cf1 100644 --- a/valeurs_config.py +++ b/valeurs_config.py @@ -6,6 +6,7 @@ acceldefault = 3 # accélération/decelération de kt par refresh turnRateDefault = 10 # turnrate/refresh par défault liste_etat_freq = ['previousFreq', 'previousShoot', 'inFreq', 'nextCoord', 'nextShoot', 'nextFreq'] +valeurCoord = 8 # combien de minute avant la sortie la coord passe plotSize = 5 # taille des plots avions dragDelay = 150 # on utilise cette valeur seuil pour déterminer si on doit cliquer sur un bouton ou drag l'etiquette offsettEtiquetteDefault = 30 # de combien les etiquettes sont décalées en px à quand on les dessine la 1ere fois From 59dd158d00241f77637be91ed0b56df086ca061a Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:35:57 +0200 Subject: [PATCH 11/15] jhsdfgsdf --- client.py | 15 ++++++++++++++- outils_radar.py | 29 ++++++++++++++++++++++++++--- paquets_avion.py | 7 ++++++- server.py | 22 ++++++++++++++++++++++ 4 files changed, 68 insertions(+), 5 deletions(-) diff --git a/client.py b/client.py index 176ead2..8709406 100644 --- a/client.py +++ b/client.py @@ -221,6 +221,19 @@ def main(server_ip: str): if type(action) in [list, tuple]: # si c'est un tuple alors cela correspond à une requête localRequests.append(action) + if conflitGen is not None: + action = conflitGen.checkEvent(event) + + if action: + if type(action) is tuple: + localRequests.append((len(dictAvions), "DelayedAdd", action)) + else: + localRequests.append((len(dictAvions), "Add", action)) + conflitBool = False + for avion in dictAvionsAff.values(): + avion.conflitSelected = False + conflitGen = None + if menuValeurs is not None: # si on valide les modifs, alors la fonction checkEvent retourne les modifs @@ -289,7 +302,7 @@ def main(server_ip: str): PFL=PFL) if newPlaneData['conflit']: - conflitGen = outils_radar.conflictGenerator(win, newPlane) + conflitGen = outils_radar.conflictGenerator(win, newPlane, carte) conflitBool = True else: localRequests.append((len(dictAvions), "Add", newPlane)) diff --git a/outils_radar.py b/outils_radar.py index bf96906..74f9650 100644 --- a/outils_radar.py +++ b/outils_radar.py @@ -88,12 +88,14 @@ def kill(self): class conflictGenerator: - def __init__(self, win, avion): + def __init__(self, win, avion, carte): size = win.get_size() width = size[0] / 3 height = 40 + self.carte = carte + self.slider = pygame_gui.elements.UIHorizontalScrollBar( pygame.Rect((size[0] / 2 - width / 2, 10), (width, height)), visible_percentage=0.3, @@ -120,6 +122,16 @@ def checkScrollBar(self): if self.slider.has_moved_recently: self.temps = self.slider.start_percentage * self.maxTemps + def checkEvent(self, event): + + """ + Vérifies si les boutons sont appuyés et prend les actions nécessaires. + :param event: + :return: + """ + if event.ui_element == self.valider: + return self.kill() + def computeSpawn(self, pos: list[float, float] | tuple[float, float], carte): """ Change la position, ou le delay de spawn de l'avion en fonction de la position voulue et des perfos @@ -127,6 +139,7 @@ def computeSpawn(self, pos: list[float, float] | tuple[float, float], carte): :param carte: La carte du jeu :return: """ + points = carte['points'] route = self.avion.route['points'] distance = self.temps * self.avion.speedPx / radarRefresh # quelle distance va parcourir l'avion en ce temps @@ -149,7 +162,7 @@ def computeSpawn(self, pos: list[float, float] | tuple[float, float], carte): if distance_calcule <= distance: # si on doit parcourir plus que ce qu'on a calculé au spawn # alors on delay le spawn, temps ici en sec - self.spawnDelay = (distance_calcule - distance) / self.avion.speedPx * radarRefresh + self.spawnDelay = int((distance - distance_calcule) / self.avion.speedPx * radarRefresh) self.x = points[route[0]['name']][0] self.y = points[route[0]['name']][1] @@ -157,7 +170,7 @@ def computeSpawn(self, pos: list[float, float] | tuple[float, float], carte): self.drawListe.append(points[route[index]['name']]) else: # si on doit parcourir moins, alors on fait apparaître l'avion plus proche du secteur - self.spawnDelay = 0 + self.spawnDelay = None distanceAparcourir = distance_calcule - distance index = 0 found = False @@ -174,6 +187,8 @@ def computeSpawn(self, pos: list[float, float] | tuple[float, float], carte): self.x = ratio * (point2[0] - point1[0]) + point1[0] self.y = ratio * (point2[1] - point1[1]) + point1[1] self.drawListe.append((self.x, self.y)) + self.avion.x = self.x + self.avion.y = self.y found = True else: @@ -192,7 +207,15 @@ def draw(self, win, zoom, scroll) -> None: (point1[0] * zoom + scroll[0], point1[1] * zoom + scroll[1]), (point2[0] * zoom + scroll[0], point2[1] * zoom + scroll[1])) + if self.spawnDelay: + font = pygame.font.SysFont('arial', 15) + img = font.render("Délai à l'apparition: " + str(self.spawnDelay) + "s", True, (170, 170, 255)) + win.blit(img, (self.drawListe[0][0] * zoom + scroll[0], self.drawListe[0][1] * zoom + scroll[1])) + def kill(self): self.valider.kill() self.slider.kill() + self.avion.findNextPoint(self.carte) + if self.spawnDelay: + return self.spawnDelay, self.avion return self.avion diff --git a/paquets_avion.py b/paquets_avion.py index a8581d7..628d6e7 100644 --- a/paquets_avion.py +++ b/paquets_avion.py @@ -90,7 +90,8 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL= self.headingMode = False - self.nextPoint = geometry.findClosestSegment(route['points'], (self.x, self.y), gameMap['points'])[1] + self.nextPoint = None + self.findNextPoint(gameMap) self.evolution = 0 # taux de variation/radar refresh self.altitudeEvoTxt = '-' @@ -157,6 +158,10 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL= self.clearedHeading = None self.clearedRate = None + def findNextPoint(self, carte): + + self.nextPoint = geometry.findClosestSegment(self.route['points'], (self.x, self.y), carte['points'])[1] + def changeXFL(self, carte) -> None: """ Change le XFL en fonction du PFL. À utliser quand le PFL change diff --git a/server.py b/server.py index 245eaad..d089877 100644 --- a/server.py +++ b/server.py @@ -371,6 +371,28 @@ def threaded_ping_responder(): xEcriture=req[2].x, yEcriture=req[2].y, PFLEcriture=req[2].PFL) + elif req[1] == 'DelayedAdd': + + avionSpawnListe.append((game.heure + req[2][0], req[2][1])) + + if mode_ecriture: + + heures = str(round(game.heure + req[2][0] // 3600)) + if len(heures) == 1: + heures = '0' + heures + minutes = str(round(game.heure + req[2][0] % 3600 // 60)) + if len(minutes) == 1: + minutes = '0' + minutes + + generateAvionXML(avionsXML, + heures + minutes, + req[2][1].indicatif, + req[2][1].aircraft, + req[2][1].route['name'], + req[2][1].altitude, + xEcriture=req[2][1].x, + yEcriture=req[2][1].y, + PFLEcriture=req[2][1].PFL) elif req[1] == 'Remove': dictAvion.pop(req[0]) From a5feb071ee135a9a35413341e1f337dd9eff02db Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:23:01 +0200 Subject: [PATCH 12/15] spawn en retard fonctionnel --- server.py | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/server.py b/server.py index d089877..b1399d3 100644 --- a/server.py +++ b/server.py @@ -210,7 +210,7 @@ 'ROC': int(aircraft.find('ROC').text), 'ROD': int(aircraft.find('ROD').text)}}) - +planeId = 0 try: # on essaye de charger une simu, si elle existe tree = ET.parse('XML/' + SIMU) @@ -232,7 +232,28 @@ heureSpawn = avion.attrib['heure'] heureSpawn = int(heureSpawn[0:2]) * 3600 + int(heureSpawn[2:]) * 60 - avionSpawnListe.append((heureSpawn, avionDict)) + for route in gameMap['routes']: + if route == avionDict['route']: + spawnRoute = gameMap['routes'][route] + break + if 'altitude' in avionDict: + spawnFL = round(avionDict['altitude'] / 100) + else: + spawnFL = None + avionPack = AvionPacket( + gameMap, + planeId, + avionDict['indicatif'], + avionDict['aircraft'], + aircraftType[avionDict['aircraft']], + spawnRoute, + avionDict['arrival'] == 'True', + FL=spawnFL, + x=avionDict['x'], + y=avionDict['y']) + planeId += 1 + + avionSpawnListe.append((heureSpawn, avionPack)) except: # sinon, on demande juste l'heure de début heure = input('Heure de début de simu, format: hhmm') @@ -341,7 +362,6 @@ def threaded_ping_responder(): start_new_thread(threaded_ping_responder, ()) temps = time.time() STCAtriggered = False -planeId = 0 accelerationTemporelle = 1 Running = True while Running: @@ -467,27 +487,8 @@ def threaded_ping_responder(): toBeRemovedFromSpawn = [] for spawn in avionSpawnListe: if spawn[0] <= game.heure: - for route in gameMap['routes']: - if route == spawn[1]['route']: - spawnRoute = gameMap['routes'][route] - break - if 'altitude' in spawn[1]: - spawnFL = round(spawn[1]['altitude']/100) - else: - spawnFL = None - dictAvion.update({planeId: AvionPacket( - gameMap, - planeId, - spawn[1]['indicatif'], - spawn[1]['aircraft'], - aircraftType[spawn[1]['aircraft']], - spawnRoute, - spawn[1]['arrival'] == 'True', - FL=spawnFL, - x=spawn[1]['x'], - y=spawn[1]['y'])}) toBeRemovedFromSpawn.append(spawn) - planeId += 1 + dictAvion.update({spawn[1].Id: spawn[1]}) for avion in toBeRemovedFromSpawn: avionSpawnListe.remove(avion) From a20051b48d841890bc0173e41758e643735551b0 Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:51:26 +0200 Subject: [PATCH 13/15] =?UTF-8?q?Visualisation=20dans=20le=20temps=20cr?= =?UTF-8?q?=C3=A9ation=20conflits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client.py | 2 +- outils_radar.py | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/client.py b/client.py index 8709406..755ce4b 100644 --- a/client.py +++ b/client.py @@ -365,7 +365,7 @@ def main(server_ip: str): menuAvion.checkSliders() if conflitGen is not None: - conflitGen.checkScrollBar() + conflitGen.checkScrollBar(carte) """Dragging""" diff --git a/outils_radar.py b/outils_radar.py index 74f9650..ff9c9f1 100644 --- a/outils_radar.py +++ b/outils_radar.py @@ -115,12 +115,14 @@ def __init__(self, win, avion, carte): self.spawnDelay = None self.drawListe = None - def checkScrollBar(self): + def checkScrollBar(self, carte): """Ajuste la valeur de temps en fonction du slider s'il est scrollé""" if self.slider.has_moved_recently: self.temps = self.slider.start_percentage * self.maxTemps + if self.x: + self.increaseTime(self.temps, carte) def checkEvent(self, event): @@ -212,6 +214,42 @@ def draw(self, win, zoom, scroll) -> None: img = font.render("Délai à l'apparition: " + str(self.spawnDelay) + "s", True, (170, 170, 255)) win.blit(img, (self.drawListe[0][0] * zoom + scroll[0], self.drawListe[0][1] * zoom + scroll[1])) + def increaseTime(self, temps, carte): + + """ + Augmente le temps de dessin sans changer le point de spawn + :param carte: La carte du jeu + :param temps: Le nouveau temps de dessin + :return: + """ + points = carte['points'] + self.temps = temps + distance = (self.temps - self.spawnDelay) * self.avion.speedPx / radarRefresh # quelle distance va parcourir l'avion en ce temps + + startPlot = geometry.findClosestSegment(self.avion.route['points'], (self.x, self.y), points)[1] + liste = self.avion.route['points'][self.avion.route['points'].index(startPlot):] + self.drawListe = [(self.x, self.y)] + + point1 = (self.x, self.y) + self.drawListe.append(point1) + for index in range(len(liste)): + point2 = points[liste[index]['name']] + + legDistance = geometry.calculateDistance(point1[0], point1[1], point2[0], point2[1]) + if distance - legDistance <= 0: + ratio = distance / legDistance + print(ratio) + x = ratio * (point2[0] - point1[0]) + point1[0] + y = ratio * (point2[1] - point1[1]) + point1[1] + self.drawListe.append(point1) + self.drawListe.append((x, y)) + break + + else: + distance -= legDistance + self.drawListe.append(point2) + point1 = point2 + def kill(self): self.valider.kill() self.slider.kill() From fef2572c09a359e87d97ce61ce34322e4b40ec27 Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:00:18 +0200 Subject: [PATCH 14/15] restruituratioon --- -Client_Launch.sh | 5 ---- -Server_Launch.sh | 5 ---- client.py => Python/client.py | 17 +++++------ geometry.py => Python/geometry.py | 0 horloge.py => Python/horloge.py | 0 interface.py => Python/interface.py | 2 -- network.py => Python/network.py | 0 outils_radar.py => Python/outils_radar.py | 6 ++-- paquets_avion.py => Python/paquets_avion.py | 0 player.py => Python/player.py | 12 ++++---- requirements.txt => Python/requirements.txt | 0 server.py => Python/server.py | 22 +++++++++------ server_browser.py => Python/server_browser.py | 2 +- server_def.py => Python/server_def.py | 2 +- valeurs_config.py => Python/valeurs_config.py | 0 XML/{aircrafts.xml => aircraft.xml} | 0 XML/{mapAPS.xml => carteSecteur.xml} | 0 theme.json | 28 +++++++++---------- 18 files changed, 47 insertions(+), 54 deletions(-) delete mode 100644 -Client_Launch.sh delete mode 100644 -Server_Launch.sh rename client.py => Python/client.py (98%) rename geometry.py => Python/geometry.py (100%) rename horloge.py => Python/horloge.py (100%) rename interface.py => Python/interface.py (99%) rename network.py => Python/network.py (100%) rename outils_radar.py => Python/outils_radar.py (97%) rename paquets_avion.py => Python/paquets_avion.py (100%) rename player.py => Python/player.py (97%) rename requirements.txt => Python/requirements.txt (100%) rename server.py => Python/server.py (97%) rename server_browser.py => Python/server_browser.py (94%) rename server_def.py => Python/server_def.py (97%) rename valeurs_config.py => Python/valeurs_config.py (100%) rename XML/{aircrafts.xml => aircraft.xml} (100%) rename XML/{mapAPS.xml => carteSecteur.xml} (100%) diff --git a/-Client_Launch.sh b/-Client_Launch.sh deleted file mode 100644 index 6498fe8..0000000 --- a/-Client_Launch.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -python -m pip install pygame -python -m pip install pygame_gui -python client.py \ No newline at end of file diff --git a/-Server_Launch.sh b/-Server_Launch.sh deleted file mode 100644 index 8252d24..0000000 --- a/-Server_Launch.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -python -m pip install pygame -python -m pip install pygame_gui -python server.py diff --git a/client.py b/Python/client.py similarity index 98% rename from client.py rename to Python/client.py index 755ce4b..35a3ffd 100644 --- a/client.py +++ b/Python/client.py @@ -1,6 +1,4 @@ -import pygame import horloge -import outils_radar from network import Network import server_browser from player import * @@ -20,7 +18,7 @@ height = 1000 win = pygame.display.set_mode((width, height)) -manager = pygame_gui.UIManager((width, height), 'theme.json') +manager = pygame_gui.UIManager((width, height), '../theme.json') pygame.display.set_caption("Client") temps = pygame.time.get_ticks() @@ -89,7 +87,6 @@ def main(server_ip: str): # vecteurs et type vecteurs = False - affichage_type_avion = False vecteurSetting = 6 # fenêtre nouvel avion @@ -165,7 +162,10 @@ def main(server_ip: str): avion.dragOffset = calculateEtiquetteOffset(avion.etiquette.container) # on vérifie que l'alidade n'est pas actif - elif event.type == pygame_gui.UI_BUTTON_PRESSED and not curseur_alidad: + elif event.type == pygame_gui.UI_BUTTON_PRESSED and curseur_alidad: + empecherDragging = False + + elif event.type == pygame_gui.UI_BUTTON_PRESSED: empecherDragging = False if menuRadar.checkActive(): @@ -229,9 +229,9 @@ def main(server_ip: str): localRequests.append((len(dictAvions), "DelayedAdd", action)) else: localRequests.append((len(dictAvions), "Add", action)) - conflitBool = False for avion in dictAvionsAff.values(): avion.conflitSelected = False + conflitBool = False conflitGen = None if menuValeurs is not None: @@ -392,10 +392,6 @@ def main(server_ip: str): scroll = scrollDef pressing = True delaiPressage = pygame.time.get_ticks() - if keys[pygame.K_t]: # type avions - affichage_type_avion = not affichage_type_avion - pressing = True - delaiPressage = pygame.time.get_ticks() if keys[pygame.K_f] and flightDataWindow is None: # Flight Data Window flightDataWindow = interface.flightDataWindow() @@ -426,6 +422,7 @@ def main(server_ip: str): if keys[pygame.K_s]: localRequests.append((0, 'Save')) delaiPressage = pygame.time.get_ticks() + elif True not in pygame.key.ScancodeWrapper() and pygame.time.get_ticks() - delaiPressage >= 150: # on vérifie que plus aucune touche n'est pressée et on remet la variable à son état initial pressing = False diff --git a/geometry.py b/Python/geometry.py similarity index 100% rename from geometry.py rename to Python/geometry.py diff --git a/horloge.py b/Python/horloge.py similarity index 100% rename from horloge.py rename to Python/horloge.py diff --git a/interface.py b/Python/interface.py similarity index 99% rename from interface.py rename to Python/interface.py index 5cc59e0..6ae20f3 100644 --- a/interface.py +++ b/Python/interface.py @@ -1,7 +1,5 @@ import pygame import pygame_gui -import math -import geometry import horloge from valeurs_config import * diff --git a/network.py b/Python/network.py similarity index 100% rename from network.py rename to Python/network.py diff --git a/outils_radar.py b/Python/outils_radar.py similarity index 97% rename from outils_radar.py rename to Python/outils_radar.py index ff9c9f1..96573cf 100644 --- a/outils_radar.py +++ b/Python/outils_radar.py @@ -224,7 +224,10 @@ def increaseTime(self, temps, carte): """ points = carte['points'] self.temps = temps - distance = (self.temps - self.spawnDelay) * self.avion.speedPx / radarRefresh # quelle distance va parcourir l'avion en ce temps + delay = 0 + if self.spawnDelay: + delay = self.spawnDelay + distance = (self.temps - delay) * self.avion.speedPx / radarRefresh # quelle distance va parcourir l'avion en ce temps startPlot = geometry.findClosestSegment(self.avion.route['points'], (self.x, self.y), points)[1] liste = self.avion.route['points'][self.avion.route['points'].index(startPlot):] @@ -238,7 +241,6 @@ def increaseTime(self, temps, carte): legDistance = geometry.calculateDistance(point1[0], point1[1], point2[0], point2[1]) if distance - legDistance <= 0: ratio = distance / legDistance - print(ratio) x = ratio * (point2[0] - point1[0]) + point1[0] y = ratio * (point2[1] - point1[1]) + point1[1] self.drawListe.append(point1) diff --git a/paquets_avion.py b/Python/paquets_avion.py similarity index 100% rename from paquets_avion.py rename to Python/paquets_avion.py diff --git a/player.py b/Python/player.py similarity index 97% rename from player.py rename to Python/player.py index c9a14a7..c70bab8 100644 --- a/player.py +++ b/Python/player.py @@ -227,18 +227,18 @@ def findEtiquetteAnchorPoint(self) -> tuple[float, float]: pointGauche = geometry.calculateIntersection((rect[0], rect[1]), (rect[0], rect[1] + rect[3]), - (self.etiquette.centre[0], self.etiquette.centre[1]), - (self.affX + plotSize, self.affY + plotSize)) + (self.etiquette.centre[0], self.etiquette.centre[1]), + (self.affX + plotSize, self.affY + plotSize)) pointDroite = geometry.calculateIntersection((rect[0] + rect[2], rect[1]), (rect[0] + rect[2], rect[1] + rect[3]), - (self.etiquette.centre[0], self.etiquette.centre[1]), - (self.affX + plotSize, self.affY + plotSize)) + (self.etiquette.centre[0], self.etiquette.centre[1]), + (self.affX + plotSize, self.affY + plotSize)) pointBas = geometry.calculateIntersection((rect[0], rect[1] + rect[3]), (rect[0] + rect[2], rect[1] + rect[3]), - (self.etiquette.centre[0], self.etiquette.centre[1]), - (self.affX + plotSize, self.affY + plotSize)) + (self.etiquette.centre[0], self.etiquette.centre[1]), + (self.affX + plotSize, self.affY + plotSize)) if rect[0] <= pointHaut[0] <= rect[0] + rect[2] and self.affY <= self.etiquetteY: return pointHaut diff --git a/requirements.txt b/Python/requirements.txt similarity index 100% rename from requirements.txt rename to Python/requirements.txt diff --git a/server.py b/Python/server.py similarity index 97% rename from server.py rename to Python/server.py index b1399d3..b0ed4b9 100644 --- a/server.py +++ b/Python/server.py @@ -2,18 +2,23 @@ import sys from _thread import * from queue import Queue -from network import MCAST_GRP, MCAST_PORT, port -from paquets_avion import * +from Python.network import MCAST_GRP, MCAST_PORT, port +from Python.paquets_avion import * import pickle import xml.etree.ElementTree as ET from xml.dom import minidom import time import struct import platform +from pathlib import Path -SIMU = 'simu.xml' -mode_ecriture = True +dossierXML = Path("").absolute().parent / 'XML' +carte = 'carteSecteur.xml' +aircraftFile = 'aircraft.xml' +simu = 'simu.xml' +mode_ecriture = True +open(dossierXML / carte) # On se connecte à internet pour avoir notre adresse IP locale... Oui oui sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.connect(("8.8.8.8", 80)) @@ -54,7 +59,7 @@ # XML map loading -tree = ET.parse('XML/mapAPS.xml') +tree = ET.parse(dossierXML / carte) root = tree.getroot() mapScale = float(root.find('scale').text) # conversion nm-px @@ -200,7 +205,7 @@ gameMap.update({'mapScale': mapScale}) aircraftType = {} -tree = ET.parse('XML/aircrafts.xml') +tree = ET.parse(dossierXML / aircraftFile) root = tree.getroot() for aircraft in root: @@ -212,7 +217,8 @@ planeId = 0 try: # on essaye de charger une simu, si elle existe - tree = ET.parse('XML/' + SIMU) + + tree = ET.parse(dossierXML / simu) heure = tree.find('heure').text heure = int(heure[0:2]) * 3600 + int(heure[2:]) * 60 @@ -481,7 +487,7 @@ def threaded_ping_responder(): accelerationTemporelle -= 0.5 elif req[1] == 'Save' and mode_ecriture: xmlstr = minidom.parseString(ET.tostring(SimuTree)).toprettyxml(indent=" ") - with open("XML/simu.xml", "w") as f: + with open("../XML/simu.xml", "w") as f: f.write(xmlstr) toBeRemovedFromSpawn = [] diff --git a/server_browser.py b/Python/server_browser.py similarity index 94% rename from server_browser.py rename to Python/server_browser.py index 0ebc7fb..21243e3 100644 --- a/server_browser.py +++ b/Python/server_browser.py @@ -1,6 +1,6 @@ import socket -from network import MCAST_GRP, MCAST_PORT +from Python.network import MCAST_GRP, MCAST_PORT def serverBrowser(): """Lan scan et server browser en une fonction diff --git a/server_def.py b/Python/server_def.py similarity index 97% rename from server_def.py rename to Python/server_def.py index 885fe9f..4648675 100644 --- a/server_def.py +++ b/Python/server_def.py @@ -1,4 +1,4 @@ -import geometry +from Python import geometry import math from valeurs_config import * diff --git a/valeurs_config.py b/Python/valeurs_config.py similarity index 100% rename from valeurs_config.py rename to Python/valeurs_config.py diff --git a/XML/aircrafts.xml b/XML/aircraft.xml similarity index 100% rename from XML/aircrafts.xml rename to XML/aircraft.xml diff --git a/XML/mapAPS.xml b/XML/carteSecteur.xml similarity index 100% rename from XML/mapAPS.xml rename to XML/carteSecteur.xml diff --git a/theme.json b/theme.json index fb06a5b..3112b3f 100644 --- a/theme.json +++ b/theme.json @@ -24,8 +24,8 @@ { "name": "regular", "size": "12", - "regular_path": "fonts/LTSuperior-SemiBold.otf", - "bold_path": "fonts/LTSuperior-Black.otf" + "regular_path": "../fonts/LTSuperior-SemiBold.otf", + "bold_path": "../fonts/LTSuperior-Black.otf" } }, "@menu": @@ -38,8 +38,8 @@ "font": { "name": "bold", "size": "12", - "regular_path": "fonts/LTSuperior-SemiBold.otf", - "bold_path": "fonts/LTSuperior-Black.otf" + "regular_path": "../fonts/LTSuperior-SemiBold.otf", + "bold_path": "../fonts/LTSuperior-Black.otf" }, "colours": { @@ -93,8 +93,8 @@ "font": { "name": "bold", "size": "15", - "regular_path": "fonts/LTSuperior-SemiBold.otf", - "bold_path": "fonts/LTSuperior-Black.otf" + "regular_path": "../fonts/LTSuperior-SemiBold.otf", + "bold_path": "../fonts/LTSuperior-Black.otf" }, "colours": { @@ -153,8 +153,8 @@ { "name": "bold", "size": "12", - "regular_path": "fonts/LTSuperior-SemiBold.otf", - "bold_path": "fonts/LTSuperior-Black.otf" + "regular_path": "../fonts/LTSuperior-SemiBold.otf", + "bold_path": "../fonts/LTSuperior-Black.otf" } }, "@etiquetteBold": @@ -177,8 +177,8 @@ "name": "bold", "size": "12", "bold": "1", - "regular_path": "fonts/LTSuperior-SemiBold.otf", - "bold_path": "fonts/LTSuperior-Black.otf" + "regular_path": "../fonts/LTSuperior-SemiBold.otf", + "bold_path": "../fonts/LTSuperior-Black.otf" } }, "@etiquetteBoldBlue": @@ -201,8 +201,8 @@ "name": "bold", "size": "12", "bold": "1", - "regular_path": "fonts/LTSuperior-SemiBold.otf", - "bold_path": "fonts/LTSuperior-Black.otf" + "regular_path": "../fonts/LTSuperior-SemiBold.otf", + "bold_path": "../fonts/LTSuperior-Black.otf" } }, "@etiquetteBlue": @@ -224,8 +224,8 @@ "font": { "name": "bold", "size": "12", - "regular_path": "fonts/LTSuperior-SemiBold.otf", - "bold_path": "fonts/LTSuperior-Black.otf" + "regular_path": "../fonts/LTSuperior-SemiBold.otf", + "bold_path": "../fonts/LTSuperior-Black.otf" } }, "rose": From 6f6c581f50bead574c32548dac83ff362422decb Mon Sep 17 00:00:00 2001 From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com> Date: Fri, 4 Oct 2024 23:22:02 +0200 Subject: [PATCH 15/15] cleanup et mise en forme pour exe --- .gitignore | 3 +- {XML => Python/XML}/aircraft.xml | 0 {XML => Python/XML}/carteSecteur.xml | 0 {XML => Python/XML}/simu.xml | 0 Python/__init__.py | 2 ++ Python/client.py | 26 ++++++++++------ Python/geometry.py | 4 +++ Python/interface.py | 6 ++-- Python/network.py | 2 ++ Python/outils_radar.py | 11 +++++-- Python/paquets_avion.py | 11 ++++--- Python/player.py | 14 ++++++--- .../ressources/fonts}/LTSuperior-Black.otf | Bin .../ressources/fonts}/LTSuperior-Medium.otf | 0 .../ressources/fonts}/LTSuperior-SemiBold.otf | Bin theme.json => Python/ressources/theme.json | 28 +++++++++--------- Python/server.py | 26 +++++++++------- Python/server_browser.py | 3 ++ Python/server_def.py | 8 +++-- Python/requirements.txt => requirements.txt | 0 20 files changed, 94 insertions(+), 50 deletions(-) rename {XML => Python/XML}/aircraft.xml (100%) rename {XML => Python/XML}/carteSecteur.xml (100%) rename {XML => Python/XML}/simu.xml (100%) create mode 100644 Python/__init__.py rename {fonts => Python/ressources/fonts}/LTSuperior-Black.otf (100%) rename {fonts => Python/ressources/fonts}/LTSuperior-Medium.otf (100%) rename {fonts => Python/ressources/fonts}/LTSuperior-SemiBold.otf (100%) rename theme.json => Python/ressources/theme.json (86%) rename Python/requirements.txt => requirements.txt (100%) diff --git a/.gitignore b/.gitignore index 05acda6..b0d2be2 100644 --- a/.gitignore +++ b/.gitignore @@ -183,4 +183,5 @@ fabric.properties .idea/caches/build_file_checksums.ser # idea folder, uncomment if you don't need it -# .idea \ No newline at end of file +# .idea +/output/ diff --git a/XML/aircraft.xml b/Python/XML/aircraft.xml similarity index 100% rename from XML/aircraft.xml rename to Python/XML/aircraft.xml diff --git a/XML/carteSecteur.xml b/Python/XML/carteSecteur.xml similarity index 100% rename from XML/carteSecteur.xml rename to Python/XML/carteSecteur.xml diff --git a/XML/simu.xml b/Python/XML/simu.xml similarity index 100% rename from XML/simu.xml rename to Python/XML/simu.xml diff --git a/Python/__init__.py b/Python/__init__.py new file mode 100644 index 0000000..b111089 --- /dev/null +++ b/Python/__init__.py @@ -0,0 +1,2 @@ + +__package__ = "Python" diff --git a/Python/client.py b/Python/client.py index 35a3ffd..2c61f36 100644 --- a/Python/client.py +++ b/Python/client.py @@ -1,12 +1,18 @@ -import horloge -from network import Network -import server_browser -from player import * -import pygame_gui -import interface -from paquets_avion import * + +# Native import +import time import math -import outils_radar +from pathlib import Path +import os + +# fichiers +import Python.horloge as horloge +from Python.network import Network +import Python.server_browser as server_browser +from Python.player import * +import Python.interface as interface +from Python.paquets_avion import * +import Python.outils_radar as outils_radar # recherche de tous les serveurs sur le réseau address = server_browser.serverBrowser() @@ -18,7 +24,8 @@ height = 1000 win = pygame.display.set_mode((width, height)) -manager = pygame_gui.UIManager((width, height), '../theme.json') +path = Path(os.getcwd()) +manager = pygame_gui.UIManager((width, height), path / 'ressources' / 'theme.json') pygame.display.set_caption("Client") temps = pygame.time.get_ticks() @@ -51,6 +58,7 @@ def main(server_ip: str): while packet is None and i < 200: n = Network(server_ip) packet = n.getP() + time.sleep(0.3) i +=1 perfos = packet.perfos diff --git a/Python/geometry.py b/Python/geometry.py index f28905a..48a6641 100644 --- a/Python/geometry.py +++ b/Python/geometry.py @@ -1,4 +1,8 @@ + +# Native imports import math + +# Module imports import numpy as np from scipy.optimize import minimize diff --git a/Python/interface.py b/Python/interface.py index 6ae20f3..7a8a304 100644 --- a/Python/interface.py +++ b/Python/interface.py @@ -1,7 +1,9 @@ + +# Module imports import pygame import pygame_gui -import horloge -from valeurs_config import * +import Python.horloge as horloge +from Python.valeurs_config import * def selectButtonInList(liste: list, event): diff --git a/Python/network.py b/Python/network.py index f36d5cf..25f0a26 100644 --- a/Python/network.py +++ b/Python/network.py @@ -1,3 +1,5 @@ + +# Native imports import socket import pickle diff --git a/Python/outils_radar.py b/Python/outils_radar.py index 96573cf..f030315 100644 --- a/Python/outils_radar.py +++ b/Python/outils_radar.py @@ -1,9 +1,14 @@ + +# Native imports +import math + +# Module imports import pygame import pygame_gui -import geometry -import math -from valeurs_config import * +# Imports fichiers +import Python.geometry as geometry +from Python.valeurs_config import * class aliSep: diff --git a/Python/paquets_avion.py b/Python/paquets_avion.py index 628d6e7..65c4259 100644 --- a/Python/paquets_avion.py +++ b/Python/paquets_avion.py @@ -1,8 +1,11 @@ -import geometry -from geometry import * -from valeurs_config import * + +# Native imports import random +# Imports fichiers +from Python.geometry import * +from Python.valeurs_config import * + class Game: def __init__(self, heure): @@ -160,7 +163,7 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL= def findNextPoint(self, carte): - self.nextPoint = geometry.findClosestSegment(self.route['points'], (self.x, self.y), carte['points'])[1] + self.nextPoint = findClosestSegment(self.route['points'], (self.x, self.y), carte['points'])[1] def changeXFL(self, carte) -> None: """ diff --git a/Python/player.py b/Python/player.py index c70bab8..5cf8416 100644 --- a/Python/player.py +++ b/Python/player.py @@ -1,9 +1,15 @@ -import pygame + +# Native imports import math + +# Module imports +import pygame import pygame_gui -from valeurs_config import * -import geometry -import interface + +# Imports fichiers +from Python.valeurs_config import * +import Python.geometry as geometry +import Python.interface as interface def positionAffichage(x: int, y: int, zoom: float, scrollX: float, scrollY: float): diff --git a/fonts/LTSuperior-Black.otf b/Python/ressources/fonts/LTSuperior-Black.otf similarity index 100% rename from fonts/LTSuperior-Black.otf rename to Python/ressources/fonts/LTSuperior-Black.otf diff --git a/fonts/LTSuperior-Medium.otf b/Python/ressources/fonts/LTSuperior-Medium.otf similarity index 100% rename from fonts/LTSuperior-Medium.otf rename to Python/ressources/fonts/LTSuperior-Medium.otf diff --git a/fonts/LTSuperior-SemiBold.otf b/Python/ressources/fonts/LTSuperior-SemiBold.otf similarity index 100% rename from fonts/LTSuperior-SemiBold.otf rename to Python/ressources/fonts/LTSuperior-SemiBold.otf diff --git a/theme.json b/Python/ressources/theme.json similarity index 86% rename from theme.json rename to Python/ressources/theme.json index 3112b3f..8a05e3e 100644 --- a/theme.json +++ b/Python/ressources/theme.json @@ -24,8 +24,8 @@ { "name": "regular", "size": "12", - "regular_path": "../fonts/LTSuperior-SemiBold.otf", - "bold_path": "../fonts/LTSuperior-Black.otf" + "regular_path": "ressources/fonts/LTSuperior-SemiBold.otf", + "bold_path": "ressources/fonts/LTSuperior-Black.otf" } }, "@menu": @@ -38,8 +38,8 @@ "font": { "name": "bold", "size": "12", - "regular_path": "../fonts/LTSuperior-SemiBold.otf", - "bold_path": "../fonts/LTSuperior-Black.otf" + "regular_path": "ressources/fonts/LTSuperior-SemiBold.otf", + "bold_path": "ressources/fonts/LTSuperior-Black.otf" }, "colours": { @@ -93,8 +93,8 @@ "font": { "name": "bold", "size": "15", - "regular_path": "../fonts/LTSuperior-SemiBold.otf", - "bold_path": "../fonts/LTSuperior-Black.otf" + "regular_path": "ressources/fonts/LTSuperior-SemiBold.otf", + "bold_path": "ressources/fonts/LTSuperior-Black.otf" }, "colours": { @@ -153,8 +153,8 @@ { "name": "bold", "size": "12", - "regular_path": "../fonts/LTSuperior-SemiBold.otf", - "bold_path": "../fonts/LTSuperior-Black.otf" + "regular_path": "ressources/fonts/LTSuperior-SemiBold.otf", + "bold_path": "ressources/fonts/LTSuperior-Black.otf" } }, "@etiquetteBold": @@ -177,8 +177,8 @@ "name": "bold", "size": "12", "bold": "1", - "regular_path": "../fonts/LTSuperior-SemiBold.otf", - "bold_path": "../fonts/LTSuperior-Black.otf" + "regular_path": "ressources/fonts/LTSuperior-SemiBold.otf", + "bold_path": "ressources/fonts/LTSuperior-Black.otf" } }, "@etiquetteBoldBlue": @@ -201,8 +201,8 @@ "name": "bold", "size": "12", "bold": "1", - "regular_path": "../fonts/LTSuperior-SemiBold.otf", - "bold_path": "../fonts/LTSuperior-Black.otf" + "regular_path": "ressources/fonts/LTSuperior-SemiBold.otf", + "bold_path": "ressources/fonts/LTSuperior-Black.otf" } }, "@etiquetteBlue": @@ -224,8 +224,8 @@ "font": { "name": "bold", "size": "12", - "regular_path": "../fonts/LTSuperior-SemiBold.otf", - "bold_path": "../fonts/LTSuperior-Black.otf" + "regular_path": "ressources/fonts/LTSuperior-SemiBold.otf", + "bold_path": "ressources/fonts/LTSuperior-Black.otf" } }, "rose": diff --git a/Python/server.py b/Python/server.py index b0ed4b9..91cb6f8 100644 --- a/Python/server.py +++ b/Python/server.py @@ -1,10 +1,11 @@ + +# Native imports import socket +import math import sys +import pickle from _thread import * from queue import Queue -from Python.network import MCAST_GRP, MCAST_PORT, port -from Python.paquets_avion import * -import pickle import xml.etree.ElementTree as ET from xml.dom import minidom import time @@ -12,13 +13,18 @@ import platform from pathlib import Path -dossierXML = Path("").absolute().parent / 'XML' +# Import fichiers +from Python.network import MCAST_GRP, MCAST_PORT, port +from Python.paquets_avion import * + + +dossierXML = Path("").absolute() / 'XML' carte = 'carteSecteur.xml' aircraftFile = 'aircraft.xml' simu = 'simu.xml' mode_ecriture = True -open(dossierXML / carte) + # On se connecte à internet pour avoir notre adresse IP locale... Oui oui sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.connect(("8.8.8.8", 80)) @@ -335,11 +341,9 @@ def threaded_client(conn, caca): conn.sendall(pickle.dumps(reply)) nombre = 0 - except: - if nombre >= 200: - break - else: - nombre += 1 + + except error: + print(error) print("Lost connection") conn.close() @@ -487,7 +491,7 @@ def threaded_ping_responder(): accelerationTemporelle -= 0.5 elif req[1] == 'Save' and mode_ecriture: xmlstr = minidom.parseString(ET.tostring(SimuTree)).toprettyxml(indent=" ") - with open("../XML/simu.xml", "w") as f: + with open("XML/simu.xml", "w") as f: f.write(xmlstr) toBeRemovedFromSpawn = [] diff --git a/Python/server_browser.py b/Python/server_browser.py index 21243e3..6dd4201 100644 --- a/Python/server_browser.py +++ b/Python/server_browser.py @@ -1,5 +1,8 @@ + +# Native Imports import socket +# Imports fichiers from Python.network import MCAST_GRP, MCAST_PORT def serverBrowser(): diff --git a/Python/server_def.py b/Python/server_def.py index 4648675..88c01fb 100644 --- a/Python/server_def.py +++ b/Python/server_def.py @@ -1,6 +1,10 @@ -from Python import geometry + +# Native imports import math -from valeurs_config import * + +# Imports fichiers +import Python.geometry as geometry +from Python.valeurs_config import * def STCA(avion1, avion2, carte) -> bool: diff --git a/Python/requirements.txt b/requirements.txt similarity index 100% rename from Python/requirements.txt rename to requirements.txt