from tkinter import *
from tkinter.ttk import Style, Treeview
from random import randint
from tkinter.messagebox import *
from PIL import Image, ImageTk, ImageEnhance


import time, pickle, pygame.mixer
import configparser



#variables principales de jeu
V_DEATH_FISH_POTION_HEAL = 10
V_DEATH_FISH_POTION_PROBA = 0.30
V_PLAYER_SPEED = 10.0
V_DIFFICULTY = 2 #1, 2 ou 3 (facile, normal, difficile)
V_PROBAS = {"Chinchard" : [78,62,45], "Piranha" : [15,20,30], "Requin" : [5,15,20], "Megalodon" : [2,3,5]} #"Poisson" : [facile,normal,difficile]
for i in range(0,3):
    V_PROBAS["Piranha"][i] += V_PROBAS["Chinchard"][i]
    V_PROBAS["Requin"][i] += V_PROBAS["Piranha"][i]
    V_PROBAS["Megalodon"][i] += V_PROBAS["Requin"][i]


#Définitions des variables principales
players = []
entities = []
items = []
canvasScoreContent = []
lastLoop = 0
tempsDebut = 0
tempsChronoSaved = 0
total_niveaux = 0
niveau = 1
niveauActuelAffichage = None
MenuScores = None
MenuRegle = None

lastCanvas = 300

grotteItems = ["X","B","C","D","F","Y","Z"]

#chargement des sons:
pygame.init()
cri1 = pygame.mixer.Sound("sons/cri1.ogg")
cri2 = pygame.mixer.Sound("sons/cri2.ogg")
fail = pygame.mixer.Sound("sons/fail.ogg")
win = pygame.mixer.Sound("sons\win.ogg")
potion = pygame.mixer.Sound("sons\potion.ogg")

def Intercepte(): #permet d'arrêter la musique lors de la fermeture de la fenêtre
    print("Interception de la fermeture de la fenetre")
    pygame.mixer.music.stop()
    fenetre.destroy()
def compteNiveaux(path): #compte le nombre de niveaux présent dans le dossier path, et prévient d'une erreur de nomenclature
    filesN = 3
    return filesN

def createConfig():
    config = configparser.ConfigParser()
    config['Paramètres'] = {}
    config['Paramètres']['V_DEATH_FISH_POTION_HEAL'] = str(V_DEATH_FISH_POTION_HEAL)
    config['Paramètres']['V_DEATH_FISH_POTION_PROBA'] = str(V_DEATH_FISH_POTION_HEAL)
    config['Paramètres']['V_PLAYER_SPEED'] = str(V_PLAYER_SPEED)
    config['Paramètres']['V_DIFFICULTY'] = str(V_DIFFICULTY)



    with open('config.ini', 'w') as configfile:
        config.write(configfile)

def chargeConfig():
    global V_DEATH_FISH_POTION_PROBA,V_DEATH_FISH_POTION_HEAL,V_DIFFICULTY,V_PLAYER_SPEED
    config = configparser.ConfigParser()
    config.read('config.ini')
    if(config.sections() == []):
        createConfig()
        chargeConfig()
        return

    try:
        V_DEATH_FISH_POTION_PROBA = float(config['Paramètres']['V_DEATH_FISH_POTION_PROBA'])
    except:
        print("error configFile")

    try:
        V_DEATH_FISH_POTION_HEAL = int(config['Paramètres']['V_DEATH_FISH_POTION_HEAL'])
    except:
        print("error configFile")

    try:
        V_PLAYER_SPEED = float(config['Paramètres']['V_PLAYER_SPEED'])
    except:
        print("error configFile")
    try:
        V_DIFFICULTY = int(config['Paramètres']['V_DIFFICULTY'])
    except:
        print("error configFile")





chargeConfig()

total_niveaux = compteNiveaux("niveaux/")


#classe game => noyan principal du jeu
class Game:
  STATE = "MENU"
  difficulty = "easy"
  tableau = None

  def startGame(self, pl):
    Menu.destroy()
    global players,tempsDebut,niveauActuelAffichage
    self.STATE = "STARTED"
    tempsDebut = time.time()


    Fond.place(x = CanvasX, y = CanvasY)
    dessineGrotte()
    canvasScore.place(x = 0, y = 680)
    #création du tableaux des scores

    try:
        fichierScores = open("scores","rb")
        self.scores = pickle.load(fichierScores)
        fichierScores.close()
    except:
        self.scores = ["Aucune donnée"]

    canvasScoreContent.append(canvasScore.create_text(100,20,text="Temps J1:",font=("comic sans ms","15"),fill="black", tags="TPS1", justify = LEFT))
    canvasScoreContent.append(canvasScore.create_text(175,60,text="HP:",font=("comic sans ms","10"),fill="black", tags="HP1"))
    canvasScoreContent.append(canvasScore.create_rectangle(35,40,200,70,fill="#7FFF00",width=2, outline= "purple", tags="Jauge1"))#jauge d'HP
    canvasScoreContent.append(canvasScore.create_rectangle(35,40,200,70,fill="white",width=2, outline= "black"))
    canvasScore.create_text(1250,60,text="Temps à battre "+ str(self.scores[0]) + " s",font=("comic sans ms","10"),fill="black", tags="HP1")
    canvasScore.tag_raise("Jauge1")
    canvasScore.tag_raise("TPS1")
    canvasScore.tag_raise("HP1")

    Player("images/player0/plongeur_r.gif",70,40)
    if(pl == 2):
      Player("images/player1/plongeur_r.gif",70,30)
      canvasScoreContent.append(canvasScore.create_text(300,20,text="Temps J2:",font=("comic sans ms","15"),fill="black", tags="TPS2", justify = LEFT))
      canvasScoreContent.append(canvasScore.create_text(375,60,text="HP:",font=("comic sans ms","10"),fill="black", tags="HP2", justify = LEFT))
      canvasScoreContent.append(canvasScore.create_rectangle(240,40,400,70,fill="#7FFF00",width=2, outline= "purple", tags="Jauge2"))#jauge d'HP
      canvasScoreContent.append(canvasScore.create_rectangle(240,40,400,70,fill="white",width=2, outline= "black"))
      canvasScore.tag_raise("Jauge2")
      canvasScore.tag_raise("TPS2")
      canvasScore.tag_raise("HP2")

    niveauActuelAffichage = canvasScore.create_text(1250,30,text="Niveau  "+ str(niveau),font=("comic sans ms","28"),fill="black")
    for i in range(1,40):
      dessine(i)

    game.add_fish(False)
    game.update_image()
    game.loop()
    pygame.init()
    pygame.mixer.init()
    pygame.mixer.music.load("sons\musique.ogg")
    pygame.mixer.music.play()
    pygame.mixer.music.set_volume(10)




  def aff_menu(self, e=""):
    global menu,choix,nombre, Menu
    Menu = Canvas(fenetre, width=fenetreWidth, height=fenetreHeight, bg="#318CE7")

    self.i_fond = PhotoImage(file="images/menu/fond.png")
    self.i_1j = PhotoImage(file="images/menu/1_joueur.png")
    self.i_2j = PhotoImage(file="images/menu/2_joueur.png")
    self.i_rules = PhotoImage(file="images/menu/regles.png")
    self.i_fondrules = PhotoImage(file="images/menu/fondregles.png")
    self.i_quit = PhotoImage(file="images/menu/quitter.png")
    self.i_reprendre = PhotoImage(file="images/menu/reprendre.png")
    self.i_retour = PhotoImage(file="images/menu/retour.png")
    self.i_scores = PhotoImage(file="images/menu/scores.png")
    self.i_retour_menu = PhotoImage(file="images/menu/menu.png")
    self.i_niveauSuiv = PhotoImage(file="images/menu/niveau_suivant.png")


    Menu.place(x = 0, y = 0)
    Menuimg=Menu.create_image(0,0,image=self.i_fond,anchor=NW)
    Menu.create_image(1163,185,image=self.i_1j, tags=["toggle_cursor","button_1"])
    Menu.create_image(1163,300,image=self.i_2j, tags=["toggle_cursor","button_2"])
    Menu.create_image(1252,415,image=self.i_rules, tags=["toggle_cursor","button_rules"])
    Menu.create_image(1252,530,image=self.i_scores, tags=["toggle_cursor","button_scores"])
    Menu.create_image(1222,630,image=self.i_quit, tags=["toggle_cursor","button_quit"])

    Menu.tag_bind('toggle_cursor', '<Enter>', lambda e: Menu.configure(cursor = 'hand2'))
    Menu.tag_bind('toggle_cursor', '<Leave>', lambda e: Menu.configure(cursor=''))

    Menu.tag_bind('button_1', '<Button-1>', self.startGame1p)
    Menu.tag_bind('button_2', '<Button-1>', self.startGame2p)
    Menu.tag_bind('button_rules', '<Button-1>', self.openRules)
    Menu.tag_bind('button_quit', '<Button-1>', self.closeWindow)
    Menu.tag_bind('button_scores', '<Button-1>', self.openScores)


    choix=1
    nombre=0

  #events
  def startGame1p(self,e=""):
    self.startGame(1)
  def startGame2p(self,e=""):
    self.startGame(2)

  def openRules(self,e=""):
    Menu.destroy()
    global MenuRegle
    MenuRegle = Canvas(fenetre, width=1376, height=780, bg="#318CE7")
    MenuRegle.place(x = 0, y = 0)

    Regleimg=MenuRegle.create_image(0,0,image=self.i_fondrules,anchor=NW)



    MenuRegle.create_image(1200,600,image=self.i_retour, tags=["toggle_cursor","button_1"])

    MenuRegle.tag_bind('toggle_cursor', '<Enter>', lambda e: MenuRegle.configure(cursor = 'hand2'))
    MenuRegle.tag_bind('toggle_cursor', '<Leave>', lambda e: MenuRegle.configure(cursor=''))


    MenuRegle.tag_bind('button_1', '<Button-1>', self.RetourMenu)


  def openScores(self,e=""):
    Menu.destroy()
    global MenuScores
    MenuScores = Canvas(fenetre, width=1376, height=780, bg="black")
    MenuScores.place(x = 0, y = 0)

    Scoresimg=MenuScores.create_image(0,0,image=self.i_fond,anchor=NW)

    MenuScores.create_image(1200,600,image=self.i_retour, tags=["toggle_cursor","button_1"])

    MenuScores.tag_bind('toggle_cursor', '<Enter>', lambda e: MenuScores.configure(cursor = 'hand2'))
    MenuScores.tag_bind('toggle_cursor', '<Leave>', lambda e: MenuScores.configure(cursor=''))


    MenuScores.tag_bind('button_1', '<Button-1>', self.RetourMenu)

    style = Style()
    style.configure("Custom.Treeview", highlightthickness=0, bd=0, font=('Calibri', 11)) # Modify the font of the body
    style.configure("Custom.Treeview.Heading", font=('Calibri', 13,'bold'),background="#949494", foreground="white", relief="flat") # Modify the font of the headings
    try:
        style.element_create("Custom.Treeheading.border", "from", "default")
    except:
        a=1
    style.layout("Custom.Treeview.Heading", [("Custom.Treeheading.cell", {'sticky': 'nswe'}),("Custom.Treeheading.text", {'sticky':'we'})])

    self.tableau = Treeview(fenetre, columns=('nom', 'temps'), style="Custom.Treeview", height=5)
    self.tableau.heading('nom', text='Nom')
    self.tableau.heading('temps', text='Temps')
    self.tableau['show'] = 'headings'
    self.tableau.pack(side = RIGHT, padx=50)

    try:
        fichierScores = open("scores","rb")
        self.scores = pickle.load(fichierScores)
        fichierScores.close()
    except:
        self.scores = [-1,-1,-1,-1,-1]

    try:
        fichierNoms = open("noms","rb")
        self.noms = pickle.load(fichierNoms)
        fichierNoms.close()
    except:
        self.noms = [" "," ","Aucune donnée"," "," "]

    scores2 = []

    for i in range(len(self.scores)):
        if(self.scores[i] == -1):
            scores2.append(" ")
        else:
            scores2.append(str(self.scores[i])+" s")
        self.tableau.insert('', 'end', values=(self.noms[i], scores2[i]),tags = (str(i),))

    self.tableau.tag_configure('0', background='#E8E8E8')
    self.tableau.tag_configure('1', background='#DFDFDF')
    self.tableau.tag_configure('2', background='#E8E8E8')
    self.tableau.tag_configure('3', background='#DFDFDF')
    self.tableau.tag_configure('4', background='#E8E8E8')

    self.tableau.column("nom",minwidth=0,width=150, stretch=NO, anchor="center")
    self.tableau.column("temps",minwidth=0,width=100, stretch=NO, anchor="center")



  #autres
  def RetourMenu(self,e=""):
    global MenuRegle,MenuScores
    try:
        MenuRegle.destroy()
        MenuRegle = None
    except:
        self.tableau.destroy()
        self.tableau = None
        MenuScores.destroy()
        MenuScores =None
    game.aff_menu()
    game.aff_menu()

  def reprendre(self,e=""):
    self.STATE = "STARTED"
    MenuPause.destroy()
    pygame.mixer.music.unpause()

  #autres
  def pause(self):
    pygame.mixer.music.pause()
    global MenuPause
    MenuPause = Canvas(fenetre, width=458, height=330, bg="white")
    self.STATE = "PAUSE"
    MenuPause.place(x = 475, y = 200)
    MenuPause.create_text(230,50,text="Vous avez mis le jeu en pause",font=("comic sans ms","20"),fill="black", tags="text", justify = LEFT)
    MenuPause.create_image(230,120,image=self.i_reprendre, tags=["toggle_cursor","button_1"])
    MenuPause.create_image(320,200,image=self.i_retour_menu, tags=["toggle_cursor","button_menu"])
    MenuPause.create_image(284,274,image=self.i_quit, tags=["toggle_cursor","button_quit"])

    MenuPause.tag_bind('button_1', '<Button-1>', self.reprendre)
    MenuPause.tag_bind('button_menu', '<Button-1>', self.goToMenuPrincip)
    MenuPause.tag_bind('button_quit', '<Button-1>', self.closeWindow)

    MenuPause.tag_bind('toggle_cursor', '<Enter>', lambda e: MenuPause.configure(cursor = 'hand2'))
    MenuPause.tag_bind('toggle_cursor', '<Leave>', lambda e: MenuPause.configure(cursor=''))

  def closeWindow(self, e=""):
    fenetre.destroy()
    pygame.mixer.music.pause()



  def add_fish(self,param):
    global entities, CanvasX, V_DIFFICULTY, V_PROBAS

    if not(game.STATE == "STARTED"):
      return
    a = randint(0,100)
    x = 1500-CanvasX
    y = randint(180,420)
    if a < V_PROBAS["Chinchard"][V_DIFFICULTY-1] :
        Chinchard("fish.png",x,y)
    elif a < V_PROBAS["Piranha"][V_DIFFICULTY-1] :
        Piranha("piranha.png",x,y)
    elif a < V_PROBAS["Requin"][V_DIFFICULTY-1] :
        Requin("shark.png",x,y)
    else:
        is_meg=False
        for f in entities:
            if "meg" in f.ID:
                is_meg=True
        if is_meg:
            Requin("shark.png",x,y)
        else:
            Megalodon("meg.gif",abs(CanvasX)-250,280)
    if param:
        return
    fenetre.after(2000, self.add_fish, False)

  def update_image(self):
    if not(game.STATE == "STARTED"):
      return
    for p in players:
      if (p.canMove and not p.finish):
        if (p.pos.d1 == "u" or p.pos.d1 == "d") and (p.pos.d2 == "l" or p.pos.d2 == "r"):
            if "plongeur_ul" in p.itemI.cget("file") or "plongeur_dl" in p.itemI.cget("file"):
                p.itemI.configure(file="images/"+p.ID+"/plongeur_"+p.pos.d1+"2.gif", format="gif -index " + str(p.index))
            elif "plongeur_ur" in p.itemI.cget("file") or "plongeur_dr" in p.itemI.cget("file"):
                p.itemI.configure(file="images/"+p.ID+"/plongeur_"+p.pos.d1+".gif", format="gif -index " + str(p.index))
            else :
                p.itemI.configure(file="images/"+p.ID+"/plongeur_"+p.pos.d1+p.pos.d2+".gif", format="gif -index " + str(p.index))
        else :
            p.itemI.configure(file="images/"+p.ID+"/plongeur_"+p.pos.d1+".gif", format="gif -index " + str(p.index))
        if p.index == 2 :
            p.index = 0
        else :
            p.index +=1
        global Fond
        Fond.tag_raise(p.ID)
    fenetre.after(240, self.update_image)

  def niveau_fin(self, joueur):
    global players, niveau, fenetre
    pygame.mixer.music.play()
    nbfinish = 0
    self.joueur = joueur
    joueur.finish = True
    joueur.canMove = False
    for p in players:
        if p.finish :
            nbfinish += 1
    if nbfinish == len(players):
        game.STATE = "FINISH"
        if niveau == total_niveaux:
            self.MenuNom = Canvas(fenetre, width=0, height=0, bg="white")
            self.MenuNom.place(x = 620, y = 300)
            frame = Frame(self.MenuNom, borderwidth=2, relief=FLAT, bg="#0c4a8a")
            frame.pack()

            self.entree = StringVar()
            Label(frame, text="Entrez votre nom", font=('Comic Sans MS', 15), bg="#0c4a8a").pack()
            Entry(frame, textvariable=self.entree, width=15, font=('Comic Sans MS', 15)).pack(padx=10, pady=10)
            Button(frame, text="Valider", command=self.time, font=('Comic Sans MS', 15), bg="#0c4a8a").pack(pady=5)
        else:
            pygame.mixer.music.stop()
            win.play()
            self.pauseEntreNiveaux()


  def time(self):
    global players, fenetre
    self.joueur.name = (self.entree.get())
    try:
        fichierScores = open("scores","rb")
        self.scores = pickle.load(fichierScores)
        fichierScores.close()
    except:
        self.scores = [-1,-1,-1,-1,-1]

    try:
        fichierNoms = open("noms","rb")
        self.noms = pickle.load(fichierNoms)
        fichierNoms.close()
    except:
        self.noms = [" "," "," "," "," "]



    for i in range(len(self.scores)):
        if self.joueur.temps <= self.scores[i] or self.scores[i] == -1:
            for j in range(len(self.scores)-1, i, -1):
                self.scores[j] = self.scores[j-1]
                self.noms[j] = self.noms[j-1]
            self.scores[i] = self.joueur.temps
            self.noms[i] = self.joueur.name
            if(i== 0):
                #on bats le meilleur score
                print("tu as gagné et a le meileur score")

            break

    #Enregistrement des variables dans le fichier
    fichierScores = open("scores","wb")
    pickle.dump(self.scores, fichierScores)
    fichierScores.close()

    fichierNoms = open("noms","wb")
    pickle.dump(self.noms, fichierNoms)
    fichierNoms.close()

    #Affichage de la liste
    """print(self.scores)
    print(self.noms)"""

    self.MenuNom.destroy()
    self.winMenu()


  def niveau_suivant(self, e = ""):
    #chargement du niveau suivant
    global niveau,Decors,fond_imgs,index_mini,Fond,CanvasX,CanvasY,entities,keys,fondWidth,MenuEntreNiv,niveauActuelAffichage
    MenuEntreNiv.destroy()
    pygame.mixer.music.play()
    niveau += 1
    Decors = lisDecors('niveaux/'+str(niveau)+'.txt')
    fondWidth = 40*len(Decors[0])
    fond_imgs = {}
    index_mini = 0
    CanvasX = 0
    CanvasY = 0
    lastCanvas = 300
    entities = []
    keys = []
    Fond.place(x = CanvasX, y = CanvasY)
    Fond.delete("all")
    Fond.configure(width=fondWidth)
    dessineGrotte()
    for i in range(1,40):
        dessine(i)

    for p in players:
        p.finish = False
        p.canMove = True
        p.pos.x = 70
        p.pos.y = 20
        p.vx = 0
        p.vy = 0
        p.item = Fond.create_image(p.pos.x,p.pos.y,image=p.itemI, tags=(p.ID))
    canvasScore.itemconfigure(niveauActuelAffichage,text = "Niveau  "+ str(niveau))
    game.STATE = "STARTED"
    self.update_image()
    self.add_fish(False)




  def loop(self):
    global lastLoop,CanvasX,players,tempsDebut,tempsChronoSaved,lastCanvas

    if abs(CanvasX)>lastCanvas:
        lastCanvas += 300
        self.add_fish(True)

    delay = (time.time() - lastLoop)*1000
    if(delay < 20 or game.STATE == "PAUSE"):
      fenetre.after(1, self.loop)
      return
    if(game.STATE == "PAUSE" or game.STATE == "FINISH"):
      if not(tempsDebut == 0):
        tempsChronoSaved = 10 * (time.time() - tempsDebut) + tempsChronoSaved
        tempsDebut = 0
      fenetre.after(1, self.loop)
      return
    if(game.STATE == "FINISH_LOOSE"):
      self.looseMenu()
      return

    lastLoop = time.time()
    if(tempsDebut == 0):
      tempsDebut = time.time()
    for p in players:
      if (p.canMove and not p.finish):
        p.updatePos()


    posplayers = {}
    posfish = {}
    positems = {}
    requin = {}
    tokill = []
    for p in players:
      if (p.canMove and not p.finish):
        posplayers[p] = Fond.bbox(p.ID)
    for f in entities:
        f.incPos(-1,0)
        f.moveY()
    for i in items:
        i.incPos(0, 1)
        positems[i] = Fond.bbox(i.ID)
    for f in entities:
      posfish[f] = Fond.bbox(f.ID)
      if("Requin" in f.ID):
        requin[f] = Fond.bbox(f.ID)

    for f in entities :
      b = posfish[f]
      if not (b == None):
        for r in requin.keys():
            c = requin[r]
            if (c[0] in range(b[0],b[2]) or c[2] in range(b[0],b[2])) and (c[1] in range(b[1],b[3]) or c[3] in range(b[1],b[3])):
                if not("Requin" in f.ID or "potion" in f.ID or "Anguille" in f.ID):
                    tokill.append(f)
        for p in players :
            if (p.canMove and not p.finish):
                a = posplayers[p]
                if (a[0] in range(b[0],b[2]) or a[2] in range(b[0],b[2])) and (a[1] in range(b[1],b[3]) or a[3] in range(b[1],b[3])):
                    f.attack(p)
    for i in items:
        b = positems[i]
        if not (b == None):
            for p in players:
                if (p.canMove and not p.finish):
                    a = posplayers[p]
                    if (a[0] in range(b[0],b[2]) or a[2] in range(b[0],b[2])) and (a[1] in range(b[1],b[3]) or a[3] in range(b[1],b[3])):
                        if("Potion" in i.ID):
                            i.heal(p)
                        elif("Cadavre" in i.ID):
                            print("ceci est un cadavre")




    for p in players :
      if (p.canMove and not p.finish):
        a = posplayers[p]
        for f in entities :
          b = posfish[f]
          if not (b == None):
            if (a[0] in range(b[0],b[2]) or a[2] in range(b[0],b[2])) and (a[1] in range(b[1],b[3]) or a[3] in range(b[1],b[3])):
              if "potion" not in f.ID:
                f.attack(p)
              else:
                f.heal(p)
    for e in tokill:
        if(e in entities):
            e.kill()
    if(len(players) > 0):


    #deplacement fond
      v = CanvasX + players[0].pos.x
      if(v > 800):
        global index_mini
        if (len(players) == 2):
            if not(players[1].pos.x < -CanvasX+10):
                moveFond(-10,0)
                if(-CanvasX > (index_mini + 1)*40):
                    dessine(index_mini+40)
        else:
            moveFond(800-v,0)
            if(-CanvasX > (index_mini + 1)*40):
                dessine(index_mini+40)


      #affichage chrono
      temps = 10 * (time.time() - tempsDebut) + tempsChronoSaved
      temps = int(temps) /10
      if players[0].hp != 0  and not players[0].finish:
        players[0].temps = temps
        canvasScore.itemconfigure(canvasScoreContent[0],text = "Temps J1: " + str(players[0].temps))
        canvasScore.itemconfigure(canvasScoreContent[1],text = str(players[0].hp) + " hp")

        if players[0].hp<20:
          canvasScore.itemconfigure(canvasScoreContent[2], fill = "#FF0000")
        elif players[0].hp<50:
          canvasScore.itemconfigure(canvasScoreContent[2], fill = "#FF8C00")
        else:
          canvasScore.itemconfigure(canvasScoreContent[2], fill = "#7FFF00")

      canvasScore.coords(canvasScoreContent[2], 35, 40, players[0].hp/100*165+35, 70)


      if len(players)==2:
        if players[1].hp != 0  and not players[1].finish:
            players[1].temps = temps
            canvasScore.itemconfigure(canvasScoreContent[4],text = "Temps J2: " + str(players[1].temps))
            canvasScore.itemconfigure(canvasScoreContent[5],text = str(players[1].hp) + " hp")

        if players[1].hp<20:
          canvasScore.itemconfigure(canvasScoreContent[6], fill = "#FF0000")
        elif players[1].hp<50:
          canvasScore.itemconfigure(canvasScoreContent[6], fill = "#FF8C00")
        else:
          canvasScore.itemconfigure(canvasScoreContent[6], fill = "#7FFF00")

        canvasScore.coords(canvasScoreContent[6], 240, 40, players[1].hp/100*165+240, 70)

    fenetre.after(1, self.loop)


  def looseMenu(self):
    global LooseMenu
    LooseMenu = Canvas(fenetre, width=458, height=260, bg="white")
    LooseMenu.place(x = 475, y = 200)
    LooseMenu.create_text(230,50,text="Vous avez perdu...",font=("comic sans ms","20"),fill="black", tags="text", justify = LEFT)
    LooseMenu.create_image(230,120,image=self.i_retour, tags=["toggle_cursor","button_1"])
    LooseMenu.tag_bind('button_1', '<Button-1>', self.goToMenuPrincip)
    LooseMenu.create_image(230,210,image=self.i_quit, tags=["toggle_cursor","button_quit"])
    LooseMenu.tag_bind('button_quit', '<Button-1>', self.closeWindow)
    LooseMenu.tag_bind('toggle_cursor', '<Enter>', lambda e: LooseMenu.configure(cursor = 'hand2'))
    LooseMenu.tag_bind('toggle_cursor', '<Leave>', lambda e: LooseMenu.configure(cursor=''))


  def winMenu(self):
    global WinMenu
    WinMenu = Canvas(fenetre, width=458, height=260, bg="white")
    WinMenu.place(x = 475, y = 200)
    WinMenu.create_text(230,50,text="Vous avez fini le jeu ! Bravo !",font=("comic sans ms","20"),fill="black", tags="text", justify = LEFT)
    WinMenu.create_image(230,120,image=self.i_retour_menu, tags=["toggle_cursor","button_1"])
    WinMenu.tag_bind('button_1', '<Button-1>', self.goToMenuPrincip)
    WinMenu.create_image(230,210,image=self.i_quit, tags=["toggle_cursor","button_quit"])
    WinMenu.tag_bind('button_quit', '<Button-1>', self.closeWindow)
    WinMenu.tag_bind('toggle_cursor', '<Enter>', lambda e: WinMenu.configure(cursor = 'hand2'))
    WinMenu.tag_bind('toggle_cursor', '<Leave>', lambda e: WinMenu.configure(cursor=''))



  def goToMenuPrincip(self, e=""):
    global Fond,game,CanvasX,CanvasY,players,entities,canvasScoreContent,lastLoop,tempsDebut,niveau,LooseMenu,WinMenu,MenuPause,fenetre,Decors,index_mini
    pygame.mixer.music.stop()
    if not(MenuPause == None):
        MenuPause.destroy()
        MenuPause = None
    if not(LooseMenu == None):
        LooseMenu.destroy()
        LooseMenu = None
    if not(WinMenu == None):
        WinMenu.destroy()
        WinMenu = None

    Fond.delete("all")

    canvasScore.delete("all")
    game = Game()

    CanvasX = 0
    CanvasY = 0
    players = []
    entities = []
    index_mini = 0

    canvasScoreContent = []
    lastLoop = 0
    tempsDebut = 0
    niveau = 1
    Decors = lisDecors('niveaux/'+str(niveau)+'.txt')

    game.aff_menu()


  def pauseEntreNiveaux(self,e=""):
    global MenuEntreNiv,niveau
    MenuEntreNiv = Canvas(fenetre, width=458, height=260, bg="white")
    MenuEntreNiv.place(x = 475, y = 200)
    MenuEntreNiv.create_text(230,50,text="Vous avez fini le niveau "+str(niveau)+", Bravo !",font=("comic sans ms","20"),fill="black", tags="text", justify = LEFT)
    MenuEntreNiv.create_image(230,120,image=self.i_niveauSuiv, tags=["toggle_cursor","button_1"])
    MenuEntreNiv.tag_bind('button_1', '<Button-1>', self.niveau_suivant)
    MenuEntreNiv.create_image(230,210,image=self.i_quit, tags=["toggle_cursor","button_quit"])
    MenuEntreNiv.tag_bind('button_quit', '<Button-1>', self.closeWindow)
    MenuEntreNiv.tag_bind('toggle_cursor', '<Enter>', lambda e: MenuEntreNiv.configure(cursor = 'hand2'))
    MenuEntreNiv.tag_bind('toggle_cursor', '<Leave>', lambda e: MenuEntreNiv.configure(cursor=''))

#définition des différentes Classes principales
class Tourbillon:

    def __init__(self, lien,x=0,y=0):
        self.lien = lien
        self.itemI=PhotoImage(file=lien, format="gif -index 0")
        self.item=Fond.create_image(x,y,image=self.itemI)
        self.pos = Position(x,y)
        self.index = 0
        self.update_gif()

    def update_gif(self):
        self.itemI.configure(file=self.lien, format="gif -index " + str(self.index))
        if self.index == 5 :
            self.index = 0
        else :
            self.index +=1
        fenetre.after(160, self.update_gif)
class Position:
  x = 0
  y = 0
  d1 = "r"
  d2 = "r"
  def __init__(self,x,y):
    self.x = x
    self.y = y

  def direct(self,nouv_d1):
    if (self.d1 == "l" or self.d1 == "r"):
      self.d2 = self.d1
    self.d1 = nouv_d1


class Item:
  def __init__(self, x=0,y=0):
    self.item=Fond.create_image(x,y,image=self.itemI, tags=(self.ID))
    self.pos = Position(x,y)
    items.append(self)

  def incPos(self,x,y):
      xH = self.pos.x + x + 20
      yH = self.pos.y + y + 20
      xB = self.pos.x + x - 30
      yB = self.pos.y + y - 30
      caseH = Perso.getCase("",xH,yH)
      caseB = Perso.getCase("",xB,yB)
      if not(caseH in grotteItems) and not(caseB in grotteItems):
        self.pos.x += x
        self.pos.y += y
        Fond.coords(self.item, self.pos.x, self.pos.y)
      if(self.pos.x  < CanvasX -50):
        Fond.delete(self.item)
        items.remove(self)

class Cadavre(Item):
  def __init__(self, x=0,y=0):
    self.ID = "cadavre" + str(randint(0,999999))
    self.itemI=PhotoImage(file="images/cadavre.png")
    super().__init__(x,y)


class Potion(Item):
  def __init__(self, x=0,y=0, bonus = 40):
    self.ID = "Potion" + str(randint(0,999999))
    self.itemI=PhotoImage(file="images/potion.png")
    self.bonus = bonus
    super().__init__(x,y)

  def heal(self, perso):
    potion.play()
    perso.hp += self.bonus
    items.remove(self)

class Plante:
  hp= 100
  canMove = False

class Perso:
  hp = 100
  name = "unknown"
  ID = ""
  pos = None

  vx = 0
  vy = 0

  item = None
  itemI = None
  canMove = True

  #constructeur =>
  def __init__(self, lien,x=0,y=0):
    if "player" in self.ID :
        self.itemI=PhotoImage(file=lien, format="gif -index 0")
    else :
        self.itemI=PhotoImage(file=lien)
    self.item=Fond.create_image(x,y,image=self.itemI, tags=(self.ID))
    self.pos = Position(x,y)

  #Fonctions pour gérer les hp du perso
  def set_hp(self, hp):
    self.hp = hp
  def inc_hp(self, hp):
    self.hp += hp
  def kill(self):
    self.hp = 0
    pygame.mixer.music.pause()
    fail.play()
    canvasScore.itemconfigure(canvasScoreContent[1],text = "HP: " + str(players[0].hp))
    if (len(players) == 2) :
        canvasScore.itemconfigure(canvasScoreContent[5],text = "HP: " + str(players[1].hp))
    self.canMove = False
    Fond.delete(self.item)
    notMove=0
    for p in players:
        if not p.canMove :
            notMove+=1
        if notMove == len(players):
            game.STATE = "FINISH_LOOSE"
            print("t'es mort bg")






  def getCase(self, x, y):
      col=int(x)//40
      lig=int(y)//40
      try:
        val = Decors[lig][col]
      except:
        val = " "
      return val
  def incPos(self,x,y):
    if(self in players and self.canMove and not self.finish):
      xH = self.pos.x + x * self.speed + 20
      yH = self.pos.y + y * self.speed + 20
      xB = self.pos.x + x * self.speed - 20
      yB = self.pos.y + y * self.speed - 20
      caseH = self.getCase(xH,yH)
      caseB = self.getCase(xB,yB)

      if not(caseH in grotteItems) and not(caseB in grotteItems) and (self.pos.x + x * self.speed) >= -CanvasX+5 and (self.pos.x + x * self.speed) < -CanvasX+1370:
        self.pos.x += x * self.speed
        self.pos.y += y * self.speed
        Fond.coords(self.item, self.pos.x, self.pos.y)
      if caseH == "H" or caseB == "H":
        game.niveau_fin(self)

    elif(self in entities and self.canMove):
      if self.type != "Megalodon":
        self.pos.x += x * self.speed
        self.pos.y += y * self.speed
        Fond.coords(self.item, self.pos.x, self.pos.y)
        if(self.pos.x  < CanvasX -50):
          Fond.delete(self.item)
          entities.remove(self)
      else:
        self.pos.x -= x * self.speed
        self.pos.y -= y * self.speed
        Fond.coords(self.item, self.pos.x, self.pos.y)


  def updatePos(self):
    if(self.canMove and not self.finish):
      case = self.getCase(self.pos.x,self.pos.y)
      if(case == "T"):
        self.incPos(0,0.5)
        print("tourbillonnnn")
      self.incPos(self.vx,self.vy)
      self.incPos(0,0.25)


#classes secondaires
class Player(Perso):
  last_attack_receiv = 0
  def __init__(self, lien,x=0,y=0):
    self.ID = "player" + str(len(players))
    self.index = 0
    self.finish = False
    super().__init__(lien,x,y)
    players.append(self)
    self.speed = V_PLAYER_SPEED
class Fish(Perso):
  damage = 10
  hp = 5
  speed = V_DIFFICULTY

  move = 0

  def __init__(self, lien,x=0,y=0):
    if "meg" not in self.ID:
        self.ID = self.type + str(randint(0,999999))
    super().__init__("images/poissons/"+lien,x,y)
    if "meg" in self.ID:
        self.update_gif()
    entities.append(self)



  #Fonction pour attaquer le perso
  def attack(self, perso):
    delay_fish = (time.time() - perso.last_attack_receiv)
    if(delay_fish > 1 or (self.type == "Piranha" and delay_fish > 0.1)):
      num = randint(1,2)
      if num==1:
        cri1.play()
      else:
        cri2.play()

      if(perso.hp - self.damage > 0):
        perso.hp -= self.damage
        perso.last_attack_receiv = time.time()
      else:
        perso.hp = 0
        perso.kill()

  def moveY(self):
    if self.canMove:
        v = self.move * 0.8


        if(self.move == 0):

            if(randint(0,10) > 6):
                self.move = 1
                return
            else:
                self.move = -1
                return


        if randint(0,50) > 55:
            self.move = -self.move

        caseH = self.getCase(self.pos.x,self.pos.y + self.speed * v+30)
        caseB = self.getCase(self.pos.x,self.pos.y + self.speed * v-30)
        caseLH = self.getCase(self.pos.x - 60 ,self.pos.y + self.speed * v+30)
        caseLB = self.getCase(self.pos.x - 60 ,self.pos.y + self.speed * v-30)

        if(caseH in grotteItems or caseB in grotteItems):
            self.move = -self.move
        if(caseH == " " and caseB == " " and randint(0,40) > 30):
            self.move = -self.move
        if(self.move == 2 or self.move == -2):
            self.move /= 2

        if(caseLH in grotteItems):
            self.move = -2
        if(caseLB in grotteItems):
            self.move = 2



        self.incPos(0,v/self.speed)
  def kill(self):
    self.hp = 0
    self.canMove = False
    Fond.delete(self.item)
    self.spawnCadavre(self.pos.x,self.pos.y)
  def spawnCadavre(self,x,y):
    if(randint(0,100)/100 <= V_DEATH_FISH_POTION_PROBA):
        Potion(x, y, V_DEATH_FISH_POTION_HEAL)
    else:
        Cadavre(x, y)



#définition des capacités des poissons
class Megalodon(Fish):
  type = "Megalodon"
  damage = 100
  speed = 1.2

  def __init__(self,lien,x=0,y=0):
    self.lien = "images/poissons/"+lien
    self.ID = "meg" + str(randint(0,999999))
    self.index = 0
    super().__init__(lien,x,y)

  def update_gif(self):
    self.itemI.configure(file=self.lien, format="gif -index " + str(self.index))
    if self.index == 5 :
        self.index = 0
    else :
        self.index +=1
    global Fond
    Fond.tag_raise(self.ID)

    fenetre.after(100, self.update_gif)

class Requin(Fish):
  type = "Requin"
  damage = 50
  speed = 4.0
class Anguille(Fish):
  type = "Anguille"
  canMove = False
  damage = 20
  speed = 2.0
class Piranha(Fish):
  type = "Piranha"
  damage = 2
  speed = 2.5
class Chinchard(Fish):
  type = "Chinchard"
  damage = 5
  speed = 1.5





#mise en place du décor
def lisDecors(fichier):  #convertit les données du fichier en liste
    filin = open(fichier, 'r')  #r=read
    liste = [list(line.replace('\n', '')) for line in filin]
    filin.close()
    return liste
def cleanEntities():
  for e in entities:
    Fond.delete(e.item)
    entities.remove(e)
def deleteFond():
  global index_mini,fond_imgs,index_last_charged
  while index_mini < index_last_charged:
    for img in fond_imgs[index_mini*40]:
      Fond.delete(img)
    index_mini += 1

  fond_imgs = {}
  index_mini = 0
  index_last_charged = 0
#variables qui servent à l'élaboration du décor
fond_imgs = {}
index_mini = 0
index_last_charged = 0

def dessineGrotte():
  Fond.create_image(0, 0, image=ImageFondGrotte, anchor=NW)
  Fond.create_image(0, 349, image=ImageFondGrotte, anchor=NW)
  Fond.create_image(1768, 0, image=ImageFondGrotte, anchor=NW)
  Fond.create_image(1768, 349, image=ImageFondGrotte, anchor=NW)
  Fond.create_image(3536, 0, image=ImageFondGrotte, anchor=NW)
  Fond.create_image(3536, 349, image=ImageFondGrotte, anchor=NW)

#dessine le fond du jeu (eau ou autres objets)
def dessine(index):
    global index_last_charged
    ligne = 0
    colonne = index-1
    #print(len(Decors)-1," lignes",len(Decors[0])-1,"colonnes")
    if(index > len(Decors[0])):
      return
    if(index >= 40):
      global index_mini
      for img in fond_imgs[index_mini*40]:
        Fond.delete(img)
      index_mini += 1
    index_last_charged = index

    while ligne <= len(Decors)-1:
        if Decors[ligne][colonne] == 'X':  #motif de la grotte
          #dessineFond(colonne * 40, ligne * 40, X)
          a=1
        elif Decors[ligne][colonne] == 'T':  #motif tourbillon
            dessineFond(colonne * 40, ligne * 40, E)
            Tourbillon("images/bulles.gif",colonne * 40, ligne * 40+20)
        elif Decors[ligne][colonne] == 'H':  #motif echelle
            dessineFond(colonne * 40, ligne * 40, E)
            dessineFond(colonne * 40, ligne * 40, H)
        elif Decors[ligne][colonne] == ' ':  #motif eau
            dessineFond(colonne * 40, ligne * 40, E)
        elif Decors[ligne][colonne] == 'A':  #anguille
            dessineFond(colonne * 40, ligne * 40, E)
            Anguille("anguille.png",colonne * 40, ligne * 40+13)
        elif Decors[ligne][colonne] == 'P':  #potion
            dessineFond(colonne * 40, ligne * 40, E)
            Potion(colonne * 40, ligne * 40+10)
        #création de la bordure de la grotte
        elif Decors[ligne][colonne] == 'B':  #en haut décroissant
            dessineFond(colonne * 40, ligne * 40, B)

        elif Decors[ligne][colonne] == 'C':  #en haut croissant
            dessineFond(colonne * 40, ligne * 40, C)

        elif Decors[ligne][colonne] == 'D':  #en bas croissant
            dessineFond(colonne * 40, ligne * 40, D)

        elif Decors[ligne][colonne] == 'F':  #en haut décroissant
            dessineFond(colonne * 40, ligne * 40, F)
        elif Decors[ligne][colonne] == 'G':  #motif Plante
            dessineFond(colonne * 40, ligne * 40, E)
            dessineFond(colonne * 40, ligne * 40+5, G)
        elif Decors[ligne][colonne] == 'Y':  #en haut
            h = randint(0,3)
            dessineFond(colonne * 40, ligne * 40, haut[h])#haut
        elif Decors[ligne][colonne] == 'Z':  #en bas
            h = randint(0,3)
            dessineFond(colonne * 40, ligne * 40, bas[h])#bas
        elif Decors[ligne][colonne] == 'R':
            dessineFond(colonne * 40, ligne * 40, E)
            dessineFond(colonne * 40, (ligne-10) * 40, ImageFondPlante)#algues debut et fin niveau

        colonne = colonne + 1
        if colonne == index:
            colonne = index-1
            ligne = ligne + 1
    Fond.tag_raise(players[0].ID)
    if(len(players) > 1):
      Fond.tag_raise(players[1].ID)

#dessine le fond du jeu (grotte)
def dessineFond(x,y,i):
  img = Fond.create_image(x, y, image=i, anchor=NW)
  if(x in fond_imgs.keys()):
    fond_imgs[x].append(img)
  else:
    fond_imgs[x] = [img]
#déplacement du fond du jeu quand le joueur avance
def moveFond(x,y):
    global CanvasX,CanvasY
    if(-CanvasX - x + int(fenetreWidth) < fondWidth):
      CanvasX += x
      CanvasY += y
      Fond.place(x = CanvasX, y = CanvasY)



#gestion des entrées clavier
keys = []
def press(event):
    #ZQSD => joueur 1
    #fleches => joueur 2
    global game,choix
    key = event.keysym
    if game.STATE == "MENU":
      if ("Return" == key):
        game.startGame(1)


    elif (game.STATE == "STARTED"):
        if(not(key in keys)):
          keys.append(key)
        if(len(players) > 0):
          p = players[0]
          vy,vx = 0, 0
          if ("Escape" in keys):
            game.pause()
          if ("z" in keys):
            vy += -1
            p.pos.direct("u")
          if ("q" in keys):
            vx += -1
            p.pos.direct("l")
          if ("s" in keys):
            vy += 1
            p.pos.direct("d")
          if ("d" in keys):
            vx += 1
            p.pos.direct("r")
          if ("f" in keys):
            moveFond(-10,0)
          p.vx = vx
          p.vy = vy

        if (len(players) == 2):
          p = players[1]
          vy,vx = 0, 0
          if ("Up" in keys):
            vy += -1
          if ("Down" in keys):
            vy += 1
          if ("Right" in keys):
            vx += 1
          if ("Left" in keys):
            vx += -1

          p.vx = vx
          p.vy = vy
def release(event):
    key = event.keysym
    if(key in keys):
      keys.remove(key)
    if not(game.STATE == "STARTED"):
      return
    if(len(players) > 0):
      p = players[0]
      if ("z" == key):
        p.vy = 0
      if ("q" == key):
        p.vx = 0
      if ("s" == key):
        p.vy = 0
      if ("d" == key):
        p.vx = 0

      if (len(players) == 2):
        p = players[1]
        if ("Up" == key):
          p.vy = 0
        if ("Down" == key):
          p.vy = 0
        if ("Right" == key):
           p.vx = 0
        if ("Left" == key):
          p.vx = 0




#lancement du jeu et création de la fenêtre
game = Game()
fenetre = Tk()
fenetre.resizable(width=False, height=False)
fenetre.title("Le jeu")
fenetreWidth = "1376"
fenetreHeight = "780"
fenetre.geometry(fenetreWidth+"x"+fenetreHeight)

LooseMenu = None
WinMenu = None
# Chargement des fichiers :
T = PhotoImage(file="images/bulles.gif")
H = PhotoImage(file="images/FondH.gif")
X = PhotoImage(file="images/algues2.png")
E = PhotoImage(file="images/FondE.png")
P = PhotoImage(file="images/potion.png")
G = PhotoImage(file="images/algue.png")

B = PhotoImage(file="images/grotte/hautDec.png")
C = PhotoImage(file="images/grotte/hautCro.png")
D = PhotoImage(file="images/grotte/basDec.png")
F = PhotoImage(file="images/grotte/basCro.png")
haut = [PhotoImage(file="images/grotte/haut1.png"), PhotoImage(file="images/grotte/haut2.png"), PhotoImage(file="images/grotte/haut3.png"), PhotoImage(file="images/grotte/haut4.png")]
bas = [PhotoImage(file="images/grotte/bas1.png"), PhotoImage(file="images/grotte/bas2.png"), PhotoImage(file="images/grotte/bas3.png"), PhotoImage(file="images/grotte/bas4.png")]

ImageFondGrotte = PhotoImage(file="images/grotte.png")

ImageFondPlante = PhotoImage(file="images/algues2.png")

Decors = lisDecors('niveaux/1.txt')

fondWidth = 40*len(Decors[0])
Fond = Canvas(fenetre, width=fondWidth, height=str(int(fenetreHeight)-100))
canvasScore = Canvas(fenetre, width=fenetreWidth, height=100, bg="white")
Menu = None
MenuPause = None

CanvasX = 0
CanvasY = 0

game.aff_menu()
fenetre.bind_all("<KeyPress>", press)
fenetre.bind_all("<KeyRelease>", release)
fenetre.protocol("WM_DELETE_WINDOW", Intercepte)
fenetre.mainloop()







