import tkinter as tk from tkinter import ttk import tkinter.messagebox from random import randint class Snake: """ cree un serpent Entree : int Sortie : None """ def __init__(self, v, s, cs): """ Parametre le serpent Entree : self, int Sortie : None """ self.__cells_to_wait = 0 self.__velocity = v self.__cells_size = cs self.__direction = "Down" self.__snake = [ canvas.create_rectangle( 245 + i, 150, 245 + i + cs, 150 + cs, width=2, outline="#081820", fill="#E0F8D0", ) for i in range(0, s * v, v) ] canvas.itemconfigure( self.__snake[0], fill="#081820" ) # change la couleur de la tete def __getitem__(self, item): """ renvoit certaines informations sur la liste __snake Entree : self, int Sortie : list, int, class, None """ if item == 0: return canvas.coords(self.__snake[0]) if item == 1: return len(self.__snake) if item == 3: return self.__snake[0] if item == 4: return self.__snake if item == 5: return self.__snake[-1] return None def diy(self, x, color): """ change la couleur du serpent Entree : self, int, str Sortie : None """ if x >= 1: canvas.itemconfig(self.__snake[x], fill=color) canvas.after(50, lambda: self.diy(x - 1, color)) # prochaine cellule return None def move(self, color): """ fait avancer le serpent et informe si le serpent sort du cadre Entree : self Sortie : bool """ # for i in range(len(self.__snake) - 1, 0, -1): # bouge le corp du serpent # canvas.move(self.__snake[i], canvas.coords(self.__snake[i - 1])[0] - canvas.coords(self.__snake[i])[0], # canvas.coords(self.__snake[i - 1])[1] - canvas.coords(self.__snake[i])[1]) if self.__cells_to_wait <= 0: canvas.delete(self.__snake.pop(-1)) else: self.__cells_to_wait -= 1 # bouge la tête du serpent head_coo = canvas.coords(self.__snake[0]) canvas.itemconfig(self.__snake[0], fill="#E0F8D0") if self.__direction == "Up": # canvas.move(self.__snake[0], 0, -self.__velocity) self.__snake = [ canvas.create_rectangle( head_coo[0], head_coo[1] - self.__velocity, head_coo[2], head_coo[3] - self.__velocity, width=2, outline=color, fill="#081820", ) ] + self.__snake elif self.__direction == "Down": # canvas.move(self.__snake[0], 0, self.__velocity) self.__snake = [ canvas.create_rectangle( head_coo[0], head_coo[1] + self.__velocity, head_coo[2], head_coo[3] + self.__velocity, width=2, outline=color, fill="#081820", ) ] + self.__snake elif self.__direction == "Left": # canvas.move(self.__snake[0], -self.__velocity, 0) self.__snake = [ canvas.create_rectangle( head_coo[0] - self.__velocity, head_coo[1], head_coo[2] - self.__velocity, head_coo[3], width=2, outline=color, fill="#081820", ) ] + self.__snake elif self.__direction == "Right": # canvas.move(self.__snake[0], self.__velocity, 0) self.__snake = [ canvas.create_rectangle( head_coo[0] + self.__velocity, head_coo[1], head_coo[2] + self.__velocity, head_coo[3], width=2, outline=color, fill="#081820", ) ] + self.__snake return None def change_dir(self, event): """ change la direction de la tête et empeche le retour arriere Entree : self, event Sortie : None """ head = canvas.coords(self[3]) cells = self.__snake if event.keysym == "Up" and cells[1] in canvas.find_overlapping( head[0], head[1] - self.__velocity, head[2], head[3] - self.__velocity ): return None if event.keysym == "Down" and cells[1] in canvas.find_overlapping( head[0], head[1] + self.__velocity, head[2], head[3] + self.__velocity ): return None if event.keysym == "Left" and cells[1] in canvas.find_overlapping( head[0] - self.__velocity, head[1], head[2] - self.__velocity, head[3] ): return None if event.keysym == "Right" and cells[1] in canvas.find_overlapping( head[0] + self.__velocity, head[1], head[2] + self.__velocity, head[3] ): return None self.__direction = event.keysym # sinon, on applique le changement de direction return None def add_cells(self, x): """ ajoute x cellules au serpent Entree : self, int Sortie : None """ # for i in range(x): # self.__snake.append(canvas.create_rectangle(canvas.coords(self.__snake[-1])[0], # canvas.coords(self.__snake[-1])[1], # canvas.coords(self.__snake[-1])[2], # canvas.coords(self.__snake[-1])[3], # width=2, outline='#081820', fill="#E0F8D0")) self.__cells_to_wait = x return None def self_eater(self, pomme): """ verifie que le serpent ne rentre pas en contact avec lui même Entree : self, instance de apple Sortie : bool """ c_s = canvas.coords(self[3]) tup = canvas.find_overlapping(c_s[0], c_s[1], c_s[2], c_s[3]) if len(tup) > 2: if pomme[3] in tup: return False return True return False class Apple: """ cree une pomme aux coordonnée x, y et lui donne un type """ def __init__(self, s): """ parametre la class Entree : self, int Sortie : None """ if randint(1, 10) == 10: self.__color = "yellow" else: self.__color = "red" y = randint(20, 450) x = randint(20, 450) while len(canvas.find_overlapping(x, y, x + 10, y + 10)) > 1: y = randint(20, 450) x = randint(20, 450) self.__apple = canvas.create_oval( x, y, x + s, y + s, fill=self.__color, width=2, outline="#081820" ) def __getitem__(self, item): """ revoit des informations sur l'instance Entree : self, int Sortie : list, instance, str """ if item == 0: return canvas.coords(self.__apple) if item == 1: return self.__color if item == 3: return self.__apple return None def delete_a(self): """ suprime la pomme Entree : self Sortie : None """ canvas.delete(self.__apple) return None def info(): """ affiche une boite d'information Entree : None Sortie : None """ tkinter.messagebox.showinfo( title=None, message="Blockade, créé par Gremlin en 1976, est le premier jeu de type snake connu. " "Rapidement aprés sa création, il est devenu un succés sur les bornes " "d'arcade. Les premières" "apparitions du terme 'snake' remonte plutôt à 1982 avec des clones tels que " "'Snake Byte'.\n\nLe clone ci-présent a été fait par Joachim Rey.", ) return None def main(): """ gere le jeu Entree : None Sortie : None """ def start(diff): """ commence le jeu Entree : int Sortie : None """ # reset le canva canvas.delete("all") canvas.create_image(0, 0, image=fond, anchor="nw") canvas.create_window(260, 565, window=label) canvas.create_rectangle(20, 20, 520, 520, outline="red") # cree les parametre du jeu if diff == 1 or diff == 0: serpent = Snake(6, 6, 5) diff = "facile" elif diff == 2: serpent = Snake(11, 6, 10) diff = "normal" else: serpent = Snake(21, 6, 20) diff = "HARDCORE" pomme = Apple(10) score = 0 # attache les touches aux actions root.bind("", serpent.change_dir) root.bind("", serpent.change_dir) root.bind("", serpent.change_dir) root.bind("", serpent.change_dir) label.config(text=f"score: {score} Taille: {serpent[1]}") # lance le jeu game(serpent, pomme, score, diff) return None def game(serpent, pomme, score, diff): """ gere les deplacement du serpent, l'apparition de la pomme et la fin du jeu Entree : instance de serpent, de pomme, int Sortie : None """ c_p = canvas.coords(pomme[3]) h_color = "#081820" if serpent[3] in canvas.find_overlapping(c_p[0], c_p[1], c_p[2], c_p[3]): if pomme[1] == "red": score += 1 serpent.add_cells(serpent[1] * 20 // 100) h_color = "red" else: score += 5 serpent.add_cells(serpent[1] * 50 // 100) h_color = "yellow" pomme.delete_a() pomme = Apple(10) label.config(text=f"score: {score} Taille: {serpent[1]}") if serpent.self_eater(pomme): serpent.diy(serpent[1] - 1, "red") rep = tkinter.messagebox.askretrycancel( title=None, message="Oups, vous êtes devenu de la purée de serpent." ) with open("data/save.txt", "r") as file: save = file.read() if save.split(";")[0] == "" or int(save.split(";")[0]) < score: with open("data/save.txt", "w") as file: file.write(f"{str(score)};{diff}") if rep: main() return None else: root.destroy() return None else: serpent.move(h_color) canvas.after(60, lambda: game(serpent, pomme, score, diff)) return None def diff_change(*args): # scale met par defaut un parametre """ change le texte de diff_affi Entree : event Sortie : None """ if round(diff.get()) == 1 or round(diff.get()) == 0: diff_affi.configure(text="Difficulté: Facile", foreground="green") elif round(diff.get()) == 2: diff_affi.configure(text="Difficulté: Normal", foreground="black") else: diff_affi.configure(text="Difficulté: HARDCORE", foreground="red") return None # reset la canva canvas.delete("test") # tente de recuperer l'ancien meilleur score try: with open("data/save.txt", "r") as file: save_s = file.read() text_score = ( "Meilleur score:\n" + f"{save_s.split(';')[0]} en difficulté {save_s.split(';')[1]}" ) except FileNotFoundError: with open("data/save.txt", "w") as file: file.write("0;None") text_score = "Meilleur score:\nVous n'avez pas de scores pour le moment\n lancez une partie :) !" # configure les boutons best_score = ttk.Label( canvas, text=text_score, font=("Helvetica", 14), background="#E0F8D0", justify="center", ) label = ttk.Label( root, text="Bienvenu sur Blockade Py !", font=("Helvetica", 14), background="#E0F8D0", ) diff = tk.DoubleVar() diff_selec = ttk.Scale( canvas, from_=1, to=3, orient="horizontal", command=diff_change, variable=diff ) start_button = ttk.Button( canvas, text="Commencer", command=lambda: start(round(diff.get())), style="my.TButton", ) info_button = ttk.Button( canvas, text="?", command=info, style="info.TButton", width=3 ) diff_affi = ttk.Label( root, text="Difficulté: Facile", font=("Helvetica", 14), background="#E0F8D0", foreground="green", ) # affiche les widgets canvas.create_window(270, 70, window=best_score) canvas.create_window(270, 565, window=label) canvas.create_window(499, 563, window=info_button) canvas.create_window(270, 220, window=diff_affi) canvas.create_window(270, 250, window=diff_selec) canvas.create_window(270, 300, window=start_button) canvas.create_image(0, 0, image=fond, anchor="nw") return None if __name__ == "__main__": # création de la fenetre root = tk.Tk() root.title("Snack") root.iconphoto(False, tk.PhotoImage(file="data/logo.png")) root.resizable(False, False) # definition du canva fond = tk.PhotoImage(file="data/fond.png") canvas = tk.Canvas(root, width=540, height=600, bg="black") canvas.pack(fill="both", expand=True) # style des boutons (ttk) style = ttk.Style(root) style.theme_use("clam") style.configure("my.TButton", bordercolor="#081820", bg="#e0f8d0") style.configure("info.Tbutton", borderwidth=0, bordercolor="#081820", bg="#e0f8d0") # demarre le jeu main() # boucle de la fenetre root.mainloop()