anonymoon

Breakout AI Code

Sep 9th, 2025
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.14 KB | None | 0 0
  1. import pygame #Importe la bibliothèque pygame pour créer le jeu et l'initialiser
  2. import numpy as np #Importe numpy en tant que np
  3. import random
  4. from paddle import Paddle #Importe la class Paddle dans paddle.py
  5. from balle import Balle #Importe la class Balle dans balle.py
  6. from mur import Mur #Importe la class Mur dans mur.py
  7. from simple_ai import SimpleAI #Importe la class SimpleAI dans simple_ai.py
  8.  
  9. #Définir les couleurs à utiliser
  10. BLANC = (255,255,255)
  11. NOIR = (0, 0, 0)
  12. BLEUFONCE = (36 ,90 ,140)
  13. BLEU = (0, 190, 242)
  14. ROUGE = (204, 53, 53)
  15. VERT = (80, 162, 45)
  16. VIOLET = (156, 60, 185)
  17. ORANGE = (255, 150, 31)
  18. JAUNE = (245, 210, 10)
  19.  
  20. #Dimensions écran
  21. screen_width = 800
  22. screen_height = 600
  23.  
  24. #Actions possibles par l'IA
  25. actions = ['GAUCHE', 'DROITE', 'RIEN']
  26.  
  27. # Q-learning avec états simplifiés
  28. #Discrétiser pour l'IA
  29. nb_pos_paddle = 10
  30. nb_pos_x_balle = 12
  31. nb_pos_y_balle = 12
  32. nb_vx = 2 # gauche/0/droite
  33. nb_vy = 2 # haut/0/bas
  34.  
  35. # Q-learning avec états simplifiés
  36. Q = np.zeros((nb_pos_paddle,
  37. nb_pos_x_balle,
  38. nb_pos_y_balle,
  39. nb_vx,
  40. nb_vy,
  41. len(actions)))
  42.  
  43. alpha = 0.2
  44. gamma = 0.9
  45.  
  46. #Reduire la taille de l'écran pour moins de possibilités
  47. def get_state(balle, paddle, screen_width, screen_height):
  48. x = int(balle.rect.x / (screen_width / nb_pos_x_balle))
  49. y = int(balle.rect.y / (screen_height / nb_pos_y_balle))
  50. vx = 0 if balle.velocity[0] < 0 else 1
  51. vy = 0 if balle.velocity[1] < 0 else 1
  52. r = int(paddle.rect.x / (screen_width / nb_pos_paddle))
  53.  
  54. #Eviter les dépassements
  55. x = min(nb_pos_x_balle - 1, x)
  56. y = min(nb_pos_y_balle - 1, y)
  57. r = min(nb_pos_paddle - 1, r)
  58.  
  59. return (r, x, y, vx, vy)
  60.  
  61. # Choisir une action
  62. def choose_action(state, epsilon):
  63. if random.uniform(0,1) < epsilon:
  64. return random.choice(actions)
  65. else:
  66. action_index = np.argmax(Q[state + (slice(None),)])
  67. return actions[action_index]
  68.  
  69. # Mise à jour Q-learning
  70. def update_Q(state, action, reward, next_state):
  71. action_index = actions.index(action)
  72. old_value = Q[state + (action_index,)]
  73. next_max = np.max(Q[next_state + (slice(None),)])
  74. Q[state + (action_index,)] = (1 - alpha) * old_value + alpha * (reward + gamma * next_max)
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81. #Fonction principale
  82. def run_game(total_games):
  83.  
  84. vies = 1
  85. score = 0
  86. game_speed = 10000000 # vitesse par défaut
  87.  
  88. enCours = True
  89. pygame.init() #Initialise le jeu pygame
  90.  
  91. #Initialiser le paddle et ses caractéristiques
  92. paddle = Paddle(BLANC, 100, 20)
  93. paddle.rect.x = 350
  94. paddle.rect.y = 560
  95.  
  96. ##Initialiser la balle et ses caractéristiques
  97. balle = Balle(BLANC, 15, 15)
  98. balle.rect.x = 345
  99. balle.rect.y = 300
  100.  
  101. #Créer une liste qui contiendra tout les sprites du jeu
  102. sprites_liste = pygame.sprite.Group()
  103.  
  104. #Ajouter les sprites seuls à la liste des sprites
  105. sprites_liste.add(paddle)
  106. sprites_liste.add(balle)
  107.  
  108. #Créer 3 lignes de briques et les ajouter au groupe mur_briques pour créer un mur
  109. mur_briques = pygame.sprite.Group()
  110. for i in range(10):
  111. brique = Mur(VIOLET,80,30)
  112. brique.rect.x = i* 80
  113. brique.rect.y = 70
  114. sprites_liste.add(brique)
  115. mur_briques.add(brique)
  116. for i in range(10):
  117. brique = Mur(ROUGE,80,30)
  118. brique.rect.x = i* 80
  119. brique.rect.y = 100
  120. sprites_liste.add(brique)
  121. mur_briques.add(brique)
  122. for i in range(10):
  123. brique = Mur(ORANGE,80,30)
  124. brique.rect.x = i* 80
  125. brique.rect.y = 130
  126. sprites_liste.add(brique)
  127. mur_briques.add(brique)
  128. for i in range(10):
  129. brique = Mur(JAUNE,80,30)
  130. brique.rect.x = i* 80
  131. brique.rect.y = 160
  132. sprites_liste.add(brique)
  133. mur_briques.add(brique)
  134.  
  135.  
  136. #Réglages de la fenêtre
  137. tailleEcran = (800, 600)
  138. ecran = pygame.display.set_mode(tailleEcran)
  139. pygame.display.set_caption("BreakIA")
  140.  
  141. #L'horloge pour contrôler la fréquence de rafraichissement
  142. horloge = pygame.time.Clock()
  143.  
  144. #Boucle principale
  145. while enCours:
  146. #Variables de vies, score, enCours et vitesse du jeu pour la boucle princiaple
  147.  
  148.  
  149. pygame.display.flip()
  150.  
  151. for event in pygame.event.get():
  152. if event.type == pygame.QUIT:
  153. pygame.quit()
  154. return None # signal pour arrêter complètement le programme
  155.  
  156. #Mode basse vitesse (à corriger)
  157. if event.type == pygame.KEYDOWN:
  158. if event.key == pygame.K_f:
  159. # Toggle entre lent et rapide
  160. if game_speed == 10000000:
  161. game_speed = 60 # mode très lent
  162. else:
  163. game_speed = 10000000 # revenir à normal
  164.  
  165. #Mode pause quand on appuye sur ECHAP
  166. if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
  167. while True: #Boucle infinie tant qu'on appuye pas sur ESC
  168. event = pygame.event.wait()
  169. police = pygame.font.Font("C:/Users/alexw/Desktop/Code/Python/Projet_BreakAI/ressources/font/dogica.otf", 64)
  170. texte = police.render("PAUSE", 1, BLANC)
  171. ecran.blit(texte, (248,300))
  172. pygame.display.flip()
  173. if event.type == pygame.QUIT:
  174. pygame.quit()
  175. return None # signal pour arrêter complètement le programme
  176. if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
  177. break #Retourner au jeu
  178.  
  179.  
  180. #Updater les différents sprites chaque frame
  181. sprites_liste.update()
  182.  
  183. if balle.rect.x >= 790:
  184. balle.velocity[0] = -balle.velocity[0]
  185. if balle.rect.x <= 10:
  186. balle.velocity[0] = -balle.velocity[0]
  187. if balle.rect.y <= 40:
  188. balle.velocity[1] = -balle.velocity[1]
  189. if balle.rect.y >= 595: #Mur du bas
  190. balle.velocity[1] = -balle.velocity[1]
  191. vies -= 1 #Quand la balle tombe en dessous du paddle, on perd une vie
  192. #S'il n'y a plus de vies ou si on a cassé toutes les briques on relance
  193. if vies <= 0 or len(mur_briques) == 0:
  194. return score #On sort proprement de run_game et on renvoie le score
  195.  
  196.  
  197. #Gérer la collision balle paddle, et faire rebondir la balle
  198. if pygame.sprite.collide_mask(balle, paddle):
  199. balle.rect.x -= balle.velocity[0]
  200. balle.rect.y -= balle.velocity[1]
  201. balle.rebond()
  202.  
  203. #Gérer la collision balle brique, et faire rebondir et disparaître une brique
  204. collision_briques = pygame.sprite.spritecollide(balle, mur_briques, False) #Liste de tout les sprites qui entrent en collision avec la balle
  205. for brique in collision_briques:
  206. balle.rect.x -= balle.velocity[0]
  207. balle.rect.y -= balle.velocity[1]
  208. balle.rebond()
  209. score += 1 #Augmenter le score quand une brique est touchée
  210. brique.kill()
  211.  
  212.  
  213. #Eviter que la balle reste coincée à l'horizontale et à la verticale
  214. if balle.velocity[1] == 0:
  215. balle.velocity[1] += 2
  216. if balle.velocity[0] == 0:
  217. balle.velocity[0] += 2
  218.  
  219.  
  220. #Code d'affichage des éléments
  221. #Mettre une couleur à l'écran
  222. ecran.fill(NOIR)
  223. pygame.draw.line(ecran, BLANC, [0, 40], [800, 40], 2)
  224.  
  225. #Afficher le score et les vies en haut de l'écran
  226. police = pygame.font.Font("C:/Users/alexw/Desktop/Code/Python/Projet_BreakAI/ressources/font/dogica.otf", 32) #Choisir une police
  227. texte = police.render("Score: " + str(score), 0, BLANC)
  228. ecran.blit(texte, (25,9))
  229. texte = police.render("Vies: " + str(vies), 0, BLANC)
  230. ecran.blit(texte, (550,9))
  231.  
  232. #Afficher tout les sprites à l'écran avec cette ligne
  233. sprites_liste.draw(ecran)
  234.  
  235. #Afficher à l'écran ce qu'on vient de définir en haut
  236. pygame.display.flip()
  237.  
  238.  
  239. # État courant
  240. state = get_state(balle, paddle, screen_width, screen_height)
  241. # epsilon décroissant pour plus d’exploitation
  242. epsilon = max(0.05, 1 - (total_games / 1000))
  243. action = choose_action(state, epsilon)
  244.  
  245. if action == 'DROITE':
  246. direction = 'DROITE'
  247. elif action == 'RIEN':
  248. direction = 'RIEN'
  249. elif action == 'GAUCHE':
  250. direction = 'GAUCHE'
  251.  
  252. # Déplacement
  253. if direction == 'DROITE':
  254. paddle.rect.x += 7
  255. elif direction == 'GAUCHE':
  256. paddle.rect.x -= 7
  257. elif direction == 'RIEN':
  258. paddle.rect.x += 0
  259.  
  260. if paddle.rect.x < 0:
  261. paddle.rect.x = 0
  262. if paddle.rect.x > screen_width - paddle.rect.width:
  263. paddle.rect.x = screen_width - paddle.rect.width
  264.  
  265.  
  266. # Récompense
  267. reward = -0.01
  268. if collision_briques:
  269. reward = 1
  270. # Si la balle tombe en bas de l’écran
  271. if balle.rect.y > screen_height:
  272. reward = -5
  273. if len(mur_briques) == 0:
  274. reward = 10
  275.  
  276.  
  277.  
  278. next_state = get_state(balle, paddle, screen_width, screen_height)
  279. update_Q(state, action, reward, next_state)
  280.  
  281. with open("C:/Users/alexw/Desktop/Code/Python/Projet_BreakAI/scores/scores.log", "a") as f:
  282. f.write(f"{total_games},{score}\n")
  283.  
  284.  
  285. #Limite à 60 fps
  286. pygame.display.update()
  287. horloge.tick(game_speed)
  288. pygame.quit
  289.  
  290.  
  291. def main():
  292. total_games = 0
  293. while True:
  294. score = run_game(total_games)
  295. if score is None: # <- si la fenêtre a été fermée
  296. break
  297. print(f"Partie {total_games} terminée - Score: {score}")
  298. total_games += 1
  299. pygame.quit()
  300.  
  301. #Lancer le jeu seulement si le fichier est exécuté directement
  302. if __name__ == "__main__":
  303. main()
Advertisement
Add Comment
Please, Sign In to add comment