diff --git a/src/scenes/game.py b/src/scenes/game.py index 84f2e7a..56dddaa 100644 --- a/src/scenes/game.py +++ b/src/scenes/game.py @@ -183,7 +183,7 @@ class Bonus(Enum): @staticmethod def aleatoire(world: World): - # on creer un maw pour que en 1vIA il n'y a pas de REVERSE. + # on creer un max pour que en 1vIA il n'y a pas de REVERSE. max = 3 if world[GameMode] == GameMode.TWO else 2 type = random.randint(0, max) match type: @@ -209,9 +209,9 @@ class Bonus(Enum): return "reverse.png" -def __spawn_ellements(world: World): +def __spawn_elements(world: World): """ - La fonction permet de initializer les ellements de la scene. + La fonction permet de initializer les elements de la scene. """ world.new_entity().set(SpriteBundle(("background.jpg"), -5)) @@ -325,7 +325,7 @@ def __spawn_ellements(world: World): ), Score(), ) - + # Création du bouton pour retourner au menu world.new_entity().set( SpriteBundle( f"button_menu_icon.png", @@ -342,11 +342,10 @@ def __spawn_ellements(world: World): ) -def __go_to_menu(world: World, _e: Entity): - world[CurrentScene] = menu.MENU - - def __spawn_bonus(world: World): + """ + Fonction qui permet de faire apparaitre un bonus + """ bonus = Bonus.aleatoire(world) world.new_entity().set( SpriteBundle( @@ -389,21 +388,48 @@ def __spawn_ball(world: World): ) -def __collision_with_ball(a: Entity, b: Entity): - if Ball in a: - a.world.new_entity().set(Sound("bound.mp3")) - if Player1 in b or Player2 in b and Ball in a: - for player in a.world.query(LastPlayerTurn): - del player[LastPlayerTurn] - b.set(LastPlayerTurn()) - return __bounce_on_player(a, b) - return True +def __check_bonus_collision(world: World): + """ + Fonction qui permet de voir si un bonus est entrée en collision avec une entité. + """ + + # Si une balle simulée entre en collision avec un bonus on + # Appelle la fonction pour gérer l'effet de celui-ci + def __collision_handler(a: Entity, b: Entity): + if Bonus in b: + __bonus_touched(a, b) + return False + return True + + for entity in world.query(Bonus): + entity.set(Solid()) + # Creation de simulations de balle qui ont un peu d'avance sur la vrai + # Avec pour consigne de si elle rentre en collision avec quelque chose + # Appeler __collision_handler + for entity in world.query(Ball): + simulated_ball = world.new_entity() + simulated_ball.set( + Position(entity[Position]), + Scale(entity[Scale]), + Velocity(entity[Velocity]), + Origin(entity[Origin]), + CollisionHandler(__collision_handler), + ) + physics.move_entity(simulated_ball, entity[Velocity] * world[Delta]) + simulated_ball.destroy() + for entity in world.query(Bonus): + entity.remove(Solid) def __bonus_touched(ball: Entity, bonus: Entity): + """ + Fonction qui qui gère l'effet des bonus une fois touché par une balle + """ player = ball.world.query(LastPlayerTurn).pop() + # On verifie de quel type est le bonus match bonus[Bonus]: case Bonus.MULTI: + # Fait apparaitre une balle qui part dans le sens inverse de la balle principale velo = Vec2(ball[Velocity]) velo.y *= -1 bonus.world.new_entity().set( @@ -418,30 +444,49 @@ def __bonus_touched(ball: Entity, bonus: Entity): Velocity(velo), CollisionHandler(__collision_with_ball), ) + # Demarre la temps avant un nouveau bonus ball.world[TimeUntilBonus].start(ball.world) case Bonus.BIG: + # Doubler la taille du dernier joueur qui a toucher la balle player[Scale] *= 2 player.set(HasBonus(Bonus.BIG, 10, bonus.world)) case Bonus.FAST: + # Augmenter la vitesse du dernier joueur qui a toucher la balle player[Speed] *= 1.5 player.set(HasBonus(Bonus.FAST, 10, bonus.world)) case Bonus.REVERSE: + # Inverser les touche du joueur qui n'est pas le dernier a avoir toucher la balle for entity in ball.world.query(UpKey): if LastPlayerTurn in entity: continue entity[UpKey], entity[DownKey] = entity[DownKey], entity[UpKey] - entity.set(HasBonus(Bonus.REVERSE, 10, bonus.world)) - + # Destruction du bonus bonus.destroy() return False +def __collision_with_ball(a: Entity, b: Entity): + """ + Fonction qui décrit un collision impliquant la balle + """ + if Ball in a: + a.world.new_entity().set(Sound("bound.mp3")) + if Player1 in b or Player2 in b and Ball in a: + # Met a jour le dernier joueur a avoir touché la balle + for player in a.world.query(LastPlayerTurn): + del player[LastPlayerTurn] + b.set(LastPlayerTurn()) + return __bounce_on_player(a, b) + return True + + def __bounce_on_player(a: Entity, b: Entity): """ Fonction qui decrit se qui se passe lorque la ball entre en collision avec un joueur """ # Si l'objet rencontré est un joueur + # On modifie sa velocité et augmente sa vitesse if Player1 in b or Player2 in b: speed = a[physics.Velocity].length a[physics.Velocity] = a[physics.Velocity].normalized @@ -459,7 +504,7 @@ def __bounce_on_player(a: Entity, b: Entity): def __bounce_on_top_or_bot_wall(a: Entity, b: Entity): - # Si une balle touceh un mur du haut ou du bas et que l'on est dans le mode 1 joueur + # Si une balle touche un mur du haut ou du bas et que l'on est dans le mode 1 joueur # Il est important de verifier qu'il s'agit de la balle, # Car des simulation de balle sont faites et ont le meme # Comportment qu'une balle mais n'ont pas le composant Ball @@ -475,12 +520,15 @@ def __bounce_on_left_wall(a: Entity, b: Entity): """ Fonction qui decrit se qui se passe lorque la ball entre en collision avec le mur de gauche """ + # Si un balle vien de toucher le mur de gauche if Ball in b: world = a.world + # Si nous sommes en 2 joueur rajouter 1 point au joueur adequate if world[GameMode] == GameMode.TWO: world[Player2Score] += 1 __update_scores(world, b) else: + # Si nous sommes dans le mode 1 joueur c'est game over world.query(Clickable).pop().destroy() world[CurrentScene] = game_over.GAME_OVER @@ -492,6 +540,7 @@ def __bounce_on_right_wall(a: Entity, b: Entity): """ Fonction qui decrit se qui se passe lorque la ball entre en collision avec le mur de droite """ + # On ajoute le bon nombre de point en fonction du mode de jeu if Ball in b: world = a.world if world[GameMode] == GameMode.TWO: @@ -503,6 +552,45 @@ def __bounce_on_right_wall(a: Entity, b: Entity): return True +def __simulate_wall_position(entity: Entity, component_type: type): + """ + Simule une entité afin de trouver lorsqu'elle entrera en collision avec une entité contenant un certain composant. + """ + simulation_entity = entity.world.new_entity() + + # Si une balle simulée entre en collision avec un bonus on + # Appelle la fonction pour gérer l'effet de celui-ci + def __collision_handler(a: Entity, b: Entity): + entity[CollisionHandler].callback(a, b) + return component_type not in b + + # Creation de simulations de balle qui ont un peu d'avance sur la vrai + # Avec pour consigne de si elle rentre en collision avec quelque chose + # Appeler __collision_handler + simulation_entity.set( + Position(entity[Position]), + Scale(entity[Scale]), + Velocity(entity[Velocity]), + Origin(entity[Origin]), + CollisionHandler(__collision_handler), + ) + physics.move_entity(simulation_entity, entity[Velocity] * 500) + return simulation_entity + + +def __animation(world: World, number: int): + world.new_entity().set( + TextBundle( + str(number), + 10, + 5000, + position=Vec2(render.WIDTH / 2, render.HEIGHT / 2), + origin=Vec2(0.5), + ), + StartAnimation(world[Time]), + ) + + def __move_up(world: World): """ La fonction permet de faire bouger les entitees qui possedent UpKey vers le haut. @@ -537,27 +625,6 @@ def __update_move(world: World): __move_up(world) -def __simulate_wall_position(entity: Entity, component_type: type): - """ - Simule une entité afin de trouver lorsqu'elle entrera en collision avec une entité contenant un certain composant. - """ - simulation_entity = entity.world.new_entity() - - def __collision_handler(a: Entity, b: Entity): - entity[CollisionHandler].callback(a, b) - return component_type not in b - - simulation_entity.set( - Position(entity[Position]), - Scale(entity[Scale]), - Velocity(entity[Velocity]), - Origin(entity[Origin]), - CollisionHandler(__collision_handler), - ) - physics.move_entity(simulation_entity, entity[Velocity] * 500) - return simulation_entity - - def _update_bot(world: World): """ Fonction qui update les mouvement du bot @@ -592,7 +659,7 @@ def _update_bot(world: World): for entity in world.query(LeftWall): entity[Position].x -= 125 - # On teste différentes possitions pour voir laquelle la plus éloigné du joueur + # On teste différentes positions pour voir laquelle la plus éloignée du joueur # Mais seulement si la balle vas vers la droite car sinon elle touchera le mur # de gauche sans intervention du bot if ball[Velocity].x > 0: @@ -627,52 +694,10 @@ def _update_bot(world: World): else: bot[Position].y = target - # On restrict l'entité a la scène + # On restreint l'entité a la scène __restrict_to_scene(world) -def __restrict_to_scene(world: World): - """ - Restrinct dans la scène toutes les entitées ayant le composant RestrictToScene. - """ - for entity in world.query(RestrictToScene): - y = entity[Position].y - (entity[Origin].y * entity[Scale].y) - if y < 0: - entity[Position].y = entity[Origin].y * entity[Scale].y - if y + entity[Scale].y > render.HEIGHT: - entity[Position].y = ( - render.HEIGHT - entity[Scale].y + (entity[Origin].y * entity[Scale].y) - ) - - -def __check_bonus_collision(world: World): - """ - Fonction qui permet de voir si un bonus est entrée en collision avec une entité. - """ - - def __collision_handler(a: Entity, b: Entity): - if Bonus in b: - __bonus_touched(a, b) - return False - return True - - for entity in world.query(Bonus): - entity.set(Solid()) - for entity in world.query(Ball): - simulated_ball = world.new_entity() - simulated_ball.set( - Position(entity[Position]), - Scale(entity[Scale]), - Velocity(entity[Velocity]), - Origin(entity[Origin]), - CollisionHandler(__collision_handler), - ) - physics.move_entity(simulated_ball, entity[Velocity] * world[Delta]) - simulated_ball.destroy() - for entity in world.query(Bonus): - entity.remove(Solid) - - def __update_scores(world: World, ball: Entity): """ La fontion permet de mettre a jour les scores. @@ -694,19 +719,6 @@ def __update_scores(world: World, ball: Entity): __animation(world, 3) -def __animation(world: World, number: int): - world.new_entity().set( - TextBundle( - str(number), - 10, - 5000, - position=Vec2(render.WIDTH / 2, render.HEIGHT / 2), - origin=Vec2(0.5), - ), - StartAnimation(world[Time]), - ) - - def __update_animation(world: World): """ Fonction qui permet de mettre a jour l'animation du compte a rebours. @@ -744,8 +756,29 @@ def __update_bonus_time(world: World): __spawn_bonus(world) +def __restrict_to_scene(world: World): + """ + Restreint dans la scène toutes les entitées ayant le composant RestrictToScene. + """ + for entity in world.query(RestrictToScene): + y = entity[Position].y - (entity[Origin].y * entity[Scale].y) + if y < 0: + entity[Position].y = entity[Origin].y * entity[Scale].y + if y + entity[Scale].y > render.HEIGHT: + entity[Position].y = ( + render.HEIGHT - entity[Scale].y + (entity[Origin].y * entity[Scale].y) + ) + + +def __go_to_menu(world: World, _e: Entity): + """ + Fonction permettant de retourner au menu + """ + world[CurrentScene] = menu.MENU + + __SCENE = Scene( - [__spawn_ellements], + [__spawn_elements], [ __update_move, __check_bonus_collision,