from tkinter import * from logique import LogiqueEchecs class PlateauTk: DECX = 0 DECY = 0 COTE_CASE = 50 MARGE_PIONS = 5 TEMPS_ANIM = 200 INTER_ANIM = 10 def __init__(self, fen, can, statut, logique): self.can = can self.fen = fen self.statut = statut self.chaine = None self.grilleDamier = [] self.imagesOriginales = {} self.imagesRedim = {} self.photos = [] self.grillePions = [] self.animations = [] self.dEtape = True self.dx1 = -1 self.dy1 = -1 self.dx2 = -1 self.dy2 = -1 self.mvtsPossibles = [] self.logique = logique self.redimCan() self.can.bind('', self.clic) self.importerImages() self.redimImages() self.cDamier() self.cGrille() self.remplirGrille(self.logique.grille) self.statutPrendre() def redimCan(self): self.can.config(width=self.COTE_CASE * self.logique.CASES_COTE, height=self.COTE_CASE * self.logique.CASES_COTE) def nomPiece(self, piece): tPiece = self.logique.tPiece(piece) if tPiece == self.logique.PCE_PION: return 'pion' elif tPiece == self.logique.PCE_TOUR: return 'tour' elif tPiece == self.logique.PCE_CAVALIER: return 'cavalier' elif tPiece == self.logique.PCE_FOU: return 'fou' elif tPiece == self.logique.PCE_DAME: return 'dame' elif tPiece == self.logique.PCE_ROI: return 'roi' else: return False def importerImage(self, piece, couleur): nom = 'sprites/'+self.nomPiece(piece)+couleur+'.gif' self.imagesOriginales.update({piece:PhotoImage(file=nom)}) def importerImages(self): for piece in self.logique.BLANCS: self.importerImage(piece, 'B') for piece in self.logique.NOIRS: self.importerImage(piece, 'N') def redimImage(self, piece, sample): self.imagesRedim.update({piece:self.imagesOriginales[piece].subsample(sample)}) def redimImages(self): sample = int(504 / (PlateauTk.COTE_CASE - PlateauTk.MARGE_PIONS)) for piece in self.logique.BLANCS: self.redimImage(piece, sample) for piece in self.logique.NOIRS: self.redimImage(piece, sample) # Dessin @staticmethod def caseCouleur(blanc, contexte): if contexte == 1: # Sélectionné return '#a0cefe' if blanc else '#478bd1' elif contexte == 2: # Possible / Victoire return '#bafea0' if blanc else '#6ed147' elif contexte == 3: # Impossible / Défaite return '#fea0ab' if blanc else '#d14758' else: # Normal return '#ffce9e' if blanc else '#d18b47' def cCase(self, x, y): couleur = self.caseCouleur(self.logique.eCaseBlanche(x, y), 0) return self.can.create_rectangle(x * PlateauTk.COTE_CASE, y * PlateauTk.COTE_CASE, (x + 1) * PlateauTk.COTE_CASE, (y + 1) * PlateauTk.COTE_CASE) def coulCase(self, x, y, contexte): couleur = self.caseCouleur(self.logique.eCaseBlanche(x, y), contexte) self.can.itemconfig(self.grilleDamier[x][y], fill=couleur, outline=couleur) def coulDamier(self): for x in range(0, self.logique.CASES_COTE): for y in range(0, self.logique.CASES_COTE): self.coulCase(x, y, 0) def cDamier(self): self.grilleDamier = [] for x in range(0, self.logique.CASES_COTE): colonne = [] for y in range(0, self.logique.CASES_COTE): colonne.append(self.cCase(x + PlateauTk.DECX, y + PlateauTk.DECY)) self.grilleDamier.append(colonne) self.coulDamier() def cPion(self, x, y, piece): if piece > 0: self.grillePions[x][y] = self.can.create_image((x + .5) * PlateauTk.COTE_CASE, (y + .5) * PlateauTk.COTE_CASE, image=self.imagesRedim[piece]) else: self.grillePions[x][y] = False def cGrille(self): self.grillePions = [] for x in range(0, self.logique.CASES_COTE): # Crée self.grillePions colonne = [] for y in range(0, self.logique.CASES_COTE): colonne.append(False) self.grillePions.append(colonne) def remplirGrille(self, j_grilleF): for x in range(0, self.logique.CASES_COTE): # Remplis self.grillePions for y in range(0, self.logique.CASES_COTE): self.cPion(x, y, j_grilleF[x][y]) # Interaction def nomJoueur(self, joueur, pluriel=True): if joueur == self.logique.BLANC: nom = 'blanc' elif joueur == self.logique.NOIR: nom = 'noir' else: nom = 'inconnu' if pluriel: nom += 's' return nom def statutPrendre(self): self.statut('Prendre (' + self.nomJoueur(self.logique.joueur) + ')') @staticmethod def animationDCoords(i): x = i['x1'] + (i['x2']-i['x1']) * (i['avancement']/i['total']) y = i['y1'] + (i['y2']-i['y1']) * (i['avancement']/i['total']) return [x, y] def animation(self): animationsNv = [] for i in self.animations: if i['avancement'] < i['total']: if i['type'] == 'd': coords = self.animationDCoords(i) self.can.coords(i['pion'], coords[0], coords[1]) # elif i['type'] == 'f': # TODO Opacité de i['pion'] # elif i['type'] == 'c': # TODO Opacité de case i['avancement'] += PlateauTk.INTER_ANIM animationsNv.append(i) else: if i['type'] == 'd': self.can.coords(i['pion'], i['x2'], i['y2']) elif i['type'] == 'f': self.can.delete(i['pion']) elif i['type'] == 'c': self.coulCase(i['x'], i['y'], 0) self.animations = animationsNv if len(animationsNv): self.fen.after(PlateauTk.INTER_ANIM, self.animation) def animer(self, animation): etaitVide = len(self.animations) < 1 self.animations.append(animation) if etaitVide: self.animation() def animerD(self, x1, y1, x2, y2, pion): if len(self.animations): for i in self.animations: if i['pion'] == pion: # Si une animation pour ce pion existe # déjà, on la reprend et on la modifie coords = self.animationDCoords(i) i['x1'] = coords[0] i['y1'] = coords[1] i['x2'] = x2 i['y2'] = y2 # i['total'] = i['total'] - i['avancement'] i['total'] = PlateauTk.TEMPS_ANIM i['avancement'] = 0 return animation = { 'x1': x1, 'y1': y1, 'x2': x2, 'y2': y2, 'pion': pion, 'type': 'd', 'total': PlateauTk.TEMPS_ANIM, 'avancement': 0 } self.can.tag_raise(pion) # Mise au premier plan self.animer(animation) def animerF(self, pion): # Pion fade-out animation = { 'pion': pion, 'type': 'f', 'total': PlateauTk.TEMPS_ANIM, 'avancement': 0 } self.animer(animation) def animerC(self, x ,y): animation = { 'type': 'c', 'x': x, 'y': y, 'total': PlateauTk.TEMPS_ANIM, 'avancement': 0 } self.animer(animation) def victoire(self): self.statut('Victoire des ' + self.nomJoueur(self.logique.victorieux) + ' !') self.coulDamier() for x in range(0, self.logique.CASES_COTE): for y in range(0, self.logique.CASES_COTE): pion = self.logique.grille[x][y] if pion > 0: if self.logique.ePionNoir(pion) ^ self.logique.victorieux: self.coulCase(x, y, 2) else: self.coulCase(x, y, 3) def dPion(self, x1, y1, x2, y2): test = self.logique.dPion(x1, y1, x2, y2) if test['valide'] == True: # Si déplacement possible for s in test['supprimer']: self.animerF(self.grillePions[s[0]][s[1]]) for d in test['deplacer']: self.grillePions[d[2]][d[3]], self.grillePions[d[0]][d[1]] = \ self.grillePions[d[0]][d[1]], False self.animerD((d[0] + .5) * PlateauTk.COTE_CASE, (d[1] + .5) * PlateauTk.COTE_CASE, \ (d[2] + .5) * PlateauTk.COTE_CASE, (d[3] + .5) * PlateauTk.COTE_CASE, \ self.grillePions[d[2]][d[3]]) else: self.statut('Déplacment impossible ! (' + test['message'] + ')') return test['valide'] def dClic(self, x, y): if not self.logique.partieFinie: if self.dEtape: # Prendre self.dx1, self.dy1 = x, y self.coulDamier() # Effacement des surbrillances if self.logique.aSonTour(self.logique.grille[self.dx1][self.dy1]): # Si possible jouer self.coulCase(self.dx1, self.dy1, 1) self.mvtPossibleSansEchecs = self.logique.mvtsPossibles(self.dx1, self.dy1) # Surbrillance bleue for i in self.mvtPossibleSansEchecs: # Surbrillances vertes self.coulCase(i[0], i[1], 2) self.statut('Poser') self.dEtape = not self.dEtape else: # Si pas possible de jouer self.coulCase(self.dx1, self.dy1, 3) self.animerC(self.dx1, self.dy1) else: # Poser self.dx2, self.dy2 = x, y if self.dPion(self.dx1, self.dy1, self.dx2, self.dy2) or (self.dx1 == self.dx2 and self.dy1 == self.dy2): # Si déplacement fait / Annule dépalcement self.coulDamier() # Effacer Surbrillance self.dEtape = not self.dEtape if self.logique.partieFinie: self.victoire() else: self.statutPrendre() else: # Si mauvais déplacement self.coulCase(self.dx2, self.dy2, 3) self.animerC(self.dx2, self.dy2) def clic(self, event): x = event.x // self.COTE_CASE y = event.y // self.COTE_CASE self.dClic(x, y) class fenetreTk: PLACEHOLDER_DIMENSIONS = 300 def __init__(self): self.fen = None self.can = None self.chaine = '' self.plateau = None self.creerFen() self.fen.mainloop() def creerFen(self): self.fen = Tk() self.fen.title("Jeu de plateau") self.can = Canvas(self.fen, width=self.PLACEHOLDER_DIMENSIONS, height=self.PLACEHOLDER_DIMENSIONS, bg="ivory") self.can.grid(row=0, column=1, columnspan=3) self.chaine = Label(self.fen, text="Bienvenue !") self.chaine.grid(row=2, column=2, padx=3, pady=3) Button(self.fen, text="Nv. Partie", command=self.nvPartie).grid(row=2, column=1, padx=3, pady=3) Button(self.fen, text="Quitter", command=self.fen.destroy).grid(row=2, column=3, padx=3, pady=3) def statut(self, texte, delai=0): self.chaine.config(text=texte) # TODO Timeout effacer si parametre / Liste def nvPartie(self): self.plateau = PlateauTk(self.fen, self.can, self.statut, LogiqueEchecs())