import pyxel,random,math
from fonction import*   
from sound import*     
class Joueur:
    def __init__(self,x,y):
        self.x=x*8
        self.y=y*8
        #constante de gravité
        self.G=10
        self.dt=1/30
        #vitesse verticale et vitesse de deplacement
        self.vy=0
        self.vitesse=3
        self.vitesse_en_l_aire=2
        self.vitesse_sol=3
        self.son=Sounds()
        #camera
        self.camera_x=0
        self.camera_y=0
        #booleens verifiant si au sol et sur  echelle
        self.on_ground=False
        self.sur_echelle=False
        #force verticale du saut
        self.force_saut=-6
        #pv
        self.pv=100
        #calcul chute
        self.impact=0
        self.degat_chute=False
        #plateforme
        self.peut_aller_en_dessous=False
        #score
        self.score=0
        #sprite
        self.en_mouvement=False
        self.direction="gauche"
        self.u=0
        self.v=0
        #walljump
        self.vx=0
        self.mur_gauche=False
        self.mur_droite=False
        self.colle_au_mur=False
        self.cooldown=0
        
        #infos
        self.nb_saut=0
        self.nb_saut_muraux=0
        self.nb_saut_sur_tremplin=0
        self.nb_sous_plateforme=0
        #defis
        self.defis_walljump_reussi=False
        #interaction
        self.contact_coffre=False
        self.tile_remplacante=(6,0)
        #defis
        self.defis={"defi walljump":False,
                    "only up":False,
                    }
        #zone
        self.zone1=False
        self.zone2=False
        self.zone2=False
        self.atteint_zone3=False
        #invulnerable
        self.touchable=True
        self.frame_invulnerabilité=0
        #tile remplacante
        self.a=6
        self.b=0
        #cle
        self.nb_cles=0
    def deplacement(self):
        """deplace le joueur"""
        saute=pyxel.btnp(pyxel.KEY_SPACE)
        #on applique vx pour eviter les erreur de collisions
        new_x=self.x+self.vx
        if pyxel.btn(pyxel.KEY_RIGHT) :
            new_x+=self.vitesse
        if pyxel.btn(pyxel.KEY_LEFT) :
            new_x-=self.vitesse
        #detection horizontale des colision droite,gauche
        if not(collision_mur(new_x,self.y)):
            self.x=new_x
        else:
            self.vx=0
        #gestion mouvement sur echelle
        if self.sur_echelle:
            self.en_mouvement=False
            if pyxel.btn(pyxel.KEY_UP):
                self.y-=self.vitesse
            elif pyxel.btn(pyxel.KEY_DOWN):
                self.y+=self.vitesse
            if saute:
                self.son.play_son_saut()
                self.nb_saut+=1
                self.vy=self.force_saut
                self.on_ground=False
            
        #saut au sol avec espace 
        if self.on_ground:
            if saute:
                self.nb_saut+=1
                self.vy=self.force_saut
                self.on_ground=False
                self.son.play_son_saut()
            if pyxel.btnp(pyxel.KEY_DOWN):
                if self.peut_aller_en_dessous:
                    self.y+=10
                    self.nb_sous_plateforme+=1
            #verification du mouvement
            if pyxel.btn(pyxel.KEY_LEFT) or pyxel.btn(pyxel.KEY_RIGHT) :
                self.en_mouvement=True
            else:
                self.en_mouvement=False
            #direction mouvement
            if pyxel.btn(pyxel.KEY_LEFT):
                self.direction="gauche"
            elif pyxel.btn(pyxel.KEY_RIGHT):
                self.direction="droite"
        #saut sur le mur
        if self.colle_au_mur and not(self.on_ground) and self.cooldown==0: 
            if saute:
                self.son.play_son_saut()
                if self.mur_gauche:
                    self.vx=int(abs(self.impact)+4)
                    
                elif self.mur_droite:
                    self.vx=int(-abs(self.impact)-4)
                
                self.nb_saut_muraux+=1
                self.vy=-6
                #on met un cooldown pour éviter les walljump infinis
                self.cooldown=30
    def collision_wall_jump(self):
        corps_droit_x=int((self.x+10)//8)
        corps_y=int((self.y)//8)
        corps_gauche_x=int((self.x-2)//8)
        tile_corps_droit=pyxel.tilemap(1).pget(corps_droit_x,corps_y)
        tile_corps_gauche=pyxel.tilemap(1).pget(corps_gauche_x,corps_y)
        #condition pour pouvoir walljump
        if tile_corps_droit in MUR or tile_corps_gauche in MUR:
            self.colle_au_mur=True
        else:
            self.colle_au_mur=False
        #coté du mur
        if tile_corps_droit in MUR:
            self.mur_droite=True
            self.mur_gauche=False
        elif tile_corps_gauche in MUR:
            self.mur_gauche=True
            self.mur_droite=False
        
    def collision_tile_special(self):
        tete_x=int((self.x+3)//8)
        tete_y=int((self.y)//8)
        foot_x_gauche=int((self.x+1)//8)
        foot_x_droite=int((self.x+5)//8)
        foot_y=int((self.y+8)//8)
        tile_pied_gauche=pyxel.tilemap(1).pget(foot_x_gauche,foot_y)
        tile_pied_droit=pyxel.tilemap(1).pget(foot_x_droite,foot_y)
        corps_droit_x=int((self.x+10)//8)
        corps_y=int((self.y)//8)
        corps_gauche_x=int((self.x-2)//8)
        tile_tete=pyxel.tilemap(1).pget(tete_x,tete_y)
        tile_corps_droit=pyxel.tilemap(1).pget(corps_droit_x,corps_y)
        tile_corps_gauche=pyxel.tilemap(1).pget(corps_gauche_x,corps_y)
        if tile_corps_gauche in TRESOR :
            pyxel.tilemap(1).pset(corps_gauche_x,corps_y,self.tile_remplacante)
        elif tile_corps_droit in TRESOR:
            pyxel.tilemap(1).pset(corps_droit_x,corps_y,self.tile_remplacante)
        if tile_corps_gauche in TRESOR or tile_corps_droit in TRESOR:
            self.contact_coffre=True
        else:
            self.contact_coffre=False   
        #interaction avec mur invisible
        if tile_pied_droit in MUR_INVISIBLE:
            pyxel.tilemap(1).pset(foot_x_droite,foot_y,(self.a,self.b))
        elif tile_corps_droit in MUR_INVISIBLE:
            pyxel.tilemap(1).pset(corps_droit_x,corps_y,(self.a,self.b))
        elif tile_corps_gauche in MUR_INVISIBLE:
            pyxel.tilemap(1).pset(corps_gauche_x,corps_y,(self.a,self.b))
        elif tile_pied_gauche in MUR_INVISIBLE:
            pyxel.tilemap(1).pset(foot_x_gauche,corps_y,(self.a,self.b))
        elif tile_pied_droit in MUR_INVISIBLE:
            pyxel.tilemap(1).pset(foot_x_droite,corps_y,(self.a,self.b))
        
        #porte
        if tile_corps_droit in PORTE.keys() and self.defis[PORTE[tile_corps_droit]]:
            pyxel.tilemap(1).pset(corps_droit_x,corps_y,(6,0))
        elif tile_corps_gauche in PORTE.keys() and self.defis[PORTE[tile_corps_gauche]]:
            pyxel.tilemap(1).pset(corps_gauche_x,corps_y,(6,0))
        elif tile_pied_gauche in PORTE.keys() and self.defis[PORTE[tile_pied_gauche]]:
            pyxel.tilemap(1).pset(foot_x_gauche,foot_y,(6,0))
        elif  tile_pied_droit in PORTE.keys() and self.defis[PORTE[tile_pied_droit]]:
            pyxel.tilemap(1).pset(foot_x_droite,foot_y,(6,0))
        
        #bloc invisibles
        if tile_pied_droit in BLOC_INVISIBLE:
            pyxel.tilemap(1).pset(foot_x_droite,foot_y,(12,19))
        elif tile_pied_gauche in BLOC_INVISIBLE:
            pyxel.tilemap(1).pset(foot_x_gauche,foot_y,(12,19))
        #casse tete
        if tile_tete in CASSE_QUE_AVEC_TETE:
            pyxel.tilemap(1).pset(tete_x,tete_y,(self.a,self.b))
                
    def collision_sol_mur(self):
        """detecte la colision entre le joueur et la plateforme"""
        foot_x_gauche=int((self.x+1)//8)
        foot_x_droite=int((self.x+7)//8)
        foot_y=int((self.y+8)//8)
        tete_x=int((self.x+3)//8)
        tete_y=int((self.y)//8)
        corps_droit_x=int((self.x+10)//8)
        corps_y=int((self.y)//8)
        corps_gauche_x=int((self.x-2)//8)

        tile_pied_gauche=pyxel.tilemap(1).pget(foot_x_gauche,foot_y)
        tile_pied_droit=pyxel.tilemap(1).pget(foot_x_droite,foot_y)
        tile_tete=pyxel.tilemap(1).pget(tete_x,tete_y)
        tile_corps_droit=pyxel.tilemap(1).pget(corps_droit_x,corps_y)
        tile_corps_gauche=pyxel.tilemap(1).pget(corps_gauche_x,corps_y)
         #reglage tile remplacante
        if tile_corps_gauche==TRESOR[0] or tile_corps_droit==TRESOR[0]:
            self.tile_remplacante=(2,20)
        else:
            self.tile_remplacante=(6,0)
        #le joueur se cogne contre le plafond dur 
        if tile_tete in MUR or tile_tete in SOL_PLATEFORME or tile_tete in SOL:
            self.vy=0.5
        
        #teleporteur
        if tile_corps_droit in TELEPORTEUR or tile_corps_gauche in TELEPORTEUR or tile_pied_gauche in TELEPORTEUR or tile_pied_droit in TELEPORTEUR or tile_tete in TELEPORTEUR:
            self.y-=50
        #detection d'une echelle
        if tile_pied_gauche in ECHELLE or tile_pied_droit in ECHELLE or tile_tete in ECHELLE:
            self.sur_echelle=True
        else:
            self.sur_echelle=False
        #verifie si le joueur est sur une plateforme classique ou un bloc mur ici
        if tile_pied_gauche in SOL_PLATEFORME or tile_pied_droit in SOL_PLATEFORME or( tile_pied_gauche in SOL or tile_pied_droit in SOL) or( tile_pied_gauche in MUR and tile_pied_droit in MUR) or tile_pied_droit in BLOC_INVISIBLE or tile_corps_gauche in BLOC_INVISIBLE or tile_pied_droit in CASSE_QUE_AVEC_TETE or tile_pied_gauche in CASSE_QUE_AVEC_TETE:
            self.y=(foot_y*8)-8
            self.on_ground=True
        else: 
            self.on_ground=False
        if tile_pied_gauche in TREMPLIN or tile_pied_droit in TREMPLIN or tile_tete in TREMPLIN:
            #calcul de la propulsion du joueur sur le tremplin en fonction de sa vitesse d'arrivée dessus
            self.vy=-1.3*abs(self.impact)
            self.impact=0
            if not(self.on_ground):
                self.nb_saut_sur_tremplin+=1
        
        
    def camera(self):
        # -64 pour centrer le joueur
        self.camera_x=self.x-64
        self.camera_y=self.y-64
          
    def update(self):
        """maj des variables du joueur"""
        self.deplacement()
        if self.vy>=7:
            self.vy=7
        if self.sur_echelle:
            self.vy = 0
            self.impact = 0
        else:
            # on applique la gravité à chaque frame à vy
            self.vy += self.G * self.dt
            self.vitesse = self.vitesse_en_l_aire
            self.impact = int(self.vy)

        self.vx *= 0.85
        self.y += self.vy
        self.collision_sol_mur()
        self.collision_tile_special()
        self.collision_wall_jump()
        

        if self.on_ground:
            self.vy = 0
            self.vx = 0
            self.vitesse=self.vitesse_sol
                # degat de chute avec impact
            if self.degat_chute:
                
                if self.impact > 7:
                    self.pv -= self.impact * 1.2
                elif  self.impact ==7:
                    self.pv -= self.impact * 1
                self.impact = 0
        
                
        self.gestion_frame_invulnerable()
        self.regles()
        self.gestion_sprite()
        self.camera()
        localisation(self)
    def regles(self):
        if self.vy>=8:
            self.vy=8
        if self.y >2000:
            self.pv=0
            self.vy=0
        if self.pv>=100:
            self.pv=100
        if self.cooldown<=0:
            self.cooldown=0
        if self.y<=-8 and 560<self.x<580:
            self.defis['defi walljump']=True
        if 143*8<=int(self.x)<=165*8 and 3*8<=int(self.y)<=4*8:
            self.defis['only up']=True
       
            
        #permet de faire en sorte que le joueur puisse passer en dessous d'une plateforme mais pas d'un bloc mur   
        foot_x=int((self.x+3)//8)
        foot_y=int((self.y+8)//8)
        tile_pied=pyxel.tilemap(1).pget(foot_x,foot_y)
        if tile_pied in SOL_PLATEFORME:
            self.peut_aller_en_dessous=True
        else:
            self.peut_aller_en_dessous=False
    def set_position(self,x,y):
        self.x=x*8
        self.y=y*8
    def gestion_frame_invulnerable(self):
        if self.frame_invulnerabilité>0:
            self.frame_invulnerabilité-=1
            self.touchable=False
        else:
            self.touchable=True
    def gestion_sprite(self):
        if not(self.colle_au_mur):
            if self.on_ground:
                if self.direction=="droite":
                    if self.en_mouvement:
                        if pyxel.frame_count%20<=10:
                            self.u=16
                            self.v=32
                        else:
                            self.u=8
                            self.v=40
                    else:
                        self.u=0
                        self.v=40
                else:
                    if self.en_mouvement:
                        if pyxel.frame_count%20<=10:
                            self.u=40
                            self.v=32
                        else:
                            self.u=8
                            self.v=48
                    else:
                        self.u=0
                        self.v=40
            else:
                self.u=16
                self.v=40
        elif self.colle_au_mur and self.mur_droite==True:
            self.u=8
            self.v=40
        elif self.colle_au_mur and not(self.mur_droite):
            self.u=8
            self.v=48
            
    def draw(self):
        pyxel.blt(self.x-self.camera_x,self.y-self.camera_y,0,self.u,self.v,8,8,5)        
        pyxel.rect(self.x-self.camera_x-5,self.y-self.camera_y-3,20,1,10)
        pyxel.rect(self.x-self.camera_x-5,self.y-self.camera_y-3,self.pv/5,1,8)
        pyxel.text(80,0,f"score: {(self.score)}",10)
        pyxel.text(0,0,f"vy: {(int(self.vy))}",10)
        
       
       
        
