From 9d9c5835987cf90501da0e18293184af01b44692 Mon Sep 17 00:00:00 2001 From: popkex Date: Sun, 28 Jun 2026 12:51:37 +0200 Subject: [PATCH] - update todo - ajout du mode difficile (fait a la main pour corriger par ia) - correction du speedUp de la balle lors d'une collision --- src/ball.py | 4 +-- src/game.py | 6 ++--- src/main.py | 2 -- src/player.py | 71 +++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/ball.py b/src/ball.py index 54bf7dc..7d44877 100644 --- a/src/ball.py +++ b/src/ball.py @@ -36,8 +36,8 @@ class Ball(Entity): self.screen.blit(self.image, (self.pos.x, self.pos.y)) def speed_up(self): - self.velocity.x = self.velocity.x + .75 if (self.velocity.x > 0) else self.velocity.x - .25 - self.velocity.y = self.velocity.y + .75 if (self.velocity.y > 0) else self.velocity.y - .25 + self.velocity.x = self.velocity.x + .75 if (self.velocity.x > 0) else self.velocity.x - .75 + self.velocity.y = self.velocity.y + .75 if (self.velocity.y > 0) else self.velocity.y - .75 def move(self, deltatime: float): if (self.velocity.x == 0 and self.velocity.y == 0): # si la balle est a l'arret lui donner un mouvement aléatoire diff --git a/src/game.py b/src/game.py index e838cca..6ce905d 100644 --- a/src/game.py +++ b/src/game.py @@ -17,7 +17,7 @@ class Game: def restart(self): self.running = True - self.difficulty = 1 # 0: facile, 1: normal, 2: difficile, change uniquement l'intelligence du bot + self.difficulty = 2 # 0: facile, 1: normal, 2: difficile, change uniquement l'intelligence du bot self.player: Player = Player(self.screen_manager) self.bot: Player = Player(self.screen_manager, difficulty=self.difficulty, is_ai=True) @@ -36,9 +36,9 @@ class Game: dt_ms: int = self.clock.tick(self.FPS_MAX) dt: float = dt_ms / 1000.0 - self.player.move(dt, self.ball) + self.player.move(dt, self.ball, self.player) self.ball.move(dt) - self.bot.move(dt, self.ball) + self.bot.move(dt, self.ball, self.player) self.player.draw() self.bot.draw() self.ball.draw() diff --git a/src/main.py b/src/main.py index e565f5a..aa04832 100644 --- a/src/main.py +++ b/src/main.py @@ -1,7 +1,5 @@ """ TODO - - améliorer l'ia - - rendre plus realiste les rebond - modifier déplacement joueur & balle pour utiliser le deltatime - faire un menu style arcade - rendre le jeu plus arcade diff --git a/src/player.py b/src/player.py index 6aaceba..c025686 100644 --- a/src/player.py +++ b/src/player.py @@ -55,19 +55,54 @@ class Player(Entity): self.pos.x = temps_pos[0] self.pos.y = temps_pos[1] - def determinate_endx(self, ball:Ball, dist_boty:float, coef_dir:float): - """Determine ou se trouvera la balle en x quand elle sera au niveau du bot quand la balle monte vers le bot""" - self.end_ballx = ball.pos.x + (dist_boty / coef_dir) # déterminer ou la ball devrais arriver + def _ball_center(self, ball_pos: Tuple[float, float], ball_size: float) -> Tuple[float, float]: + return ball_pos[0] + ball_size / 2, ball_pos[1] + ball_size / 2 + + def _mirror_x_center(self, x_center: float, radius: float) -> float: + min_x: float = radius + max_x: float = self.screen.get_width() - radius + span: float = max_x - min_x + if span <= 0: + return min_x + + x_rel: float = x_center - min_x + x_mod: float = x_rel % (2 * span) + if x_mod <= span: + return min_x + x_mod + return max_x - (x_mod - span) + + def predict_end_x(self, ball_pos:Tuple[float, float], ball_size:float, velocity_x:float, velocity_y:float, target_center_y:float) -> float: + center_x, center_y = self._ball_center(ball_pos, ball_size) + if velocity_y == 0: + return self._mirror_x_center(center_x, ball_size / 2) + + dt: float = (target_center_y - center_y) / velocity_y + predicted_x: float = center_x + velocity_x * dt + return self._mirror_x_center(predicted_x, ball_size / 2) + + def determinate_endx(self, ball_pos:Tuple[float, float], ball_size:float, dist_boty:float, coef_dir:float, modify_end_ballx: bool = True) -> float: + """ + return le delta x de déplacement de la balle + Determine ou se trouvera la balle en x quand elle sera au niveau du bot quand la balle monte vers le bot + """ + dtx: float = (dist_boty / coef_dir) + if (modify_end_ballx): self.end_ballx = ball_pos[0] + dtx # déterminer ou la ball devrais arriver if (self.end_ballx < 0): # Si la balle devrait collisionner avec le mur de gauche - collisiony: float = ball.pos.y + (coef_dir * (ball.pos.x - (ball.size / 2))) # Calculer a quelle hauteur la balle va collisionner avec le mur - dist_boty = (self.pos.y - self.size[1]) - (collisiony - (ball.size / 2)) - self.end_ballx = ball.pos.x + (dist_boty / -coef_dir) # déterminer ou la ball devrais arriver - elif (self.end_ballx > self.screen.get_width() + (ball.size / 2)): # Si la balle devrait collisionner avec le mur de droite - collisiony: float = ball.pos.y + (coef_dir * (self.screen.get_width() - (ball.pos.x - (ball.size / 2)))) # Calculer a quelle hauteur la balle va collisionner avec le mur - self.end_ballx = ball.pos.x + (dist_boty / -coef_dir) # déterminer ou la ball devrais arriver + collisiony: float = ball_pos[1] + (coef_dir * (ball_pos[0] - (ball_size / 2))) # Calculer a quelle hauteur la balle va collisionner avec le mur + dist_boty = (self.pos.y - self.size[1]) - (collisiony - (ball_size / 2)) + dtx = (dist_boty / -coef_dir) + if (modify_end_ballx): self.end_ballx = ball_pos[0] + dtx # déterminer ou la ball devrais arriver + return dtx + elif (self.end_ballx > self.screen.get_width() + (ball_size / 2)): # Si la balle devrait collisionner avec le mur de droite + collisiony: float = ball_pos[1] + (coef_dir * (self.screen.get_width() - (ball_pos[0] - (ball_size / 2)))) # Calculer a quelle hauteur la balle va collisionner avec le mur + dtx = (dist_boty / -coef_dir) + if (modify_end_ballx): self.end_ballx = ball_pos[0] + (dist_boty / -coef_dir) # déterminer ou la ball devrais arriver + return dtx - def ia_move(self, deltatime:float, ball:Ball): + return dtx + + def ia_move(self, deltatime:float, ball:Ball, player:Player): """ - mode facile : le bot essaye juste de ce mettre ou se trouve la balle en temps reelle @@ -85,9 +120,8 @@ class Player(Entity): # IA en mode normal && difficile if (self.difficulty > 0): if (ball.velocity.y < 0): # Si la balle va vers le bot (en gros, monte) - coef_dir: float = ball.velocity.y / ball.velocity.x # Calculer le coef directeur de la droite qui suit le vecteur mouvement de la balle - dist_boty: float = (self.pos.y - self.size[1]) - (ball.pos.y - (ball.size / 2)) # La distance en yqui séparre le bot et la balle - self.determinate_endx(ball=ball, dist_boty=dist_boty, coef_dir=coef_dir) + target_center_y: float = self.pos.y + self.size[1] + (ball.size / 2) + self.end_ballx = self.predict_end_x(ball_pos=(ball.pos.x, ball.pos.y), ball_size=ball.size, velocity_x=ball.velocity.x, velocity_y=ball.velocity.y, target_center_y=target_center_y) # else: self.end_ballx = round(self.screen.get_size()[0] / 2) if (self.end_ballx < self.pos.x + self.size[0] / 2): self.velocity.x -= self.speed * deltatime @@ -95,7 +129,12 @@ class Player(Entity): if (self.difficulty == 2): # Le mode difficile if (ball.velocity.y > 0): # Quand la balle se dirige vers le joueur - pass + player_contact_center_y: float = player.pos.y - (ball.size / 2) + impact_center_x: float = self.predict_end_x(ball_pos=(ball.pos.x, ball.pos.y), ball_size=ball.size, velocity_x=ball.velocity.x, velocity_y=ball.velocity.y, target_center_y=player_contact_center_y) + + target_center_y: float = self.pos.y + self.size[1] + (ball.size / 2) + impact_top_left: Tuple[float, float] = (impact_center_x - (ball.size / 2), player_contact_center_y - (ball.size / 2)) + self.end_ballx = self.predict_end_x(ball_pos=impact_top_left, ball_size=ball.size, velocity_x=ball.velocity.x, velocity_y=-ball.velocity.y, target_center_y=target_center_y) self.apply_move(deltatime) @@ -115,8 +154,8 @@ class Player(Entity): self.apply_move(deltatime) - def move(self, deltatime: float, ball: Ball): + def move(self, deltatime: float, ball: Ball, player:Player): if (self.is_ai): - self.ia_move(deltatime, ball) + self.ia_move(deltatime, ball, player) else: self.player_move(deltatime) \ No newline at end of file