import pyxel
from liste_tuiles import *

'''
Il y a 4 possibilités pour les tuiles :
- le personnage peut passer à travers : valeur 0
- le personnage peut monter dessus : valeur 1
- le personnage peut monter dessus mais également les détruire : valeur 2
- le personnage peut passer à travers mais elles sont alors censées disparaître (pensez aux bonus) : valeur 3

Compte-tenu de l'ordre dans lequel les tuiles sont stockées, qui est le même que celui dans lequel vous pouvez les voir dans l'image "sortie.png"
(de gauche à droite et de haut en bas), les valeurs successives à donner sont :
011122121110011301010112200012110000
'''


dict_tile_to_object_type = {0 : "Decor", 1:"World Static", 2:"World Static",3:"World Static",4:"Breakable Block",5:"Breakable Block",6:"World Static",
                            7:"Breakable Block",8:"World Static",9:"World Static",10:"Breakable Block",11 : "Decor",12 : "Decor", 13:"World Static",14:"World Static",
                            15 : "Collectibles", 16 : "Decor", 17:"World Static", 18 : "Decor", 19:"World Static", 20 : "Decor", 21:"World Static", 22:"World Static",
                            23:"Breakable Block",24:"Breakable Block",25 : "Decor",26 : "Decor",27 : "Decor", 28:"World Static", 29:"Breakable Block",30:"World Static",
                            31:"World Static",32 : "Decor",33 : "Decor",34 : "Decor",35 : "Decor"}

pyxel.init(256,256, fps= 60)
pyxel.load("alexkid.pyxres")
cote = 1 + int(len(tuiles)**0.5)
pos = {"x" : 2,
       "y" : 50,
       "w" : 16,
       "h" : 24,
       "vx" : 0,
       "vy" : 0,
       "Gravity" : 0.2,
       "Direction" : 1,
       "Accelx" : 0.15,
       "Name_flipbook" : "Idle",
       "frame_index" : 0,
       "Air_inertia": 0.5,
       "Start_Jumping" : None,
       "Stop_Jumping" : False,
       "Ground_Locomotion" : False,
       "Crouch" : False,
       "IsInAir" : False,
       "jump_strength" : -2,
       "Falling" : False,
       "cg" : False,
       "cd" : False,
       "ch" : False,
       "cb" : False,
       "frame_start_punch" : None,
       "Punch" : False}




  

def update():
    
    if pyxel.btnp(pyxel.KEY_Q):
        pyxel.quit()
    if pyxel.btn(pyxel.KEY_S):
        if not pos["IsInAir"]:
            pos["Crouch"] = True
    elif pyxel.btnr(pyxel.KEY_S):
        pos["Crouch"] = False
    if pyxel.btnp(pyxel.KEY_A):
        if not pos["Crouch"]:
            pos["Punch"] = True
            pos["frame_start_punch"] = pyxel.frame_count
    if pyxel.btn(pyxel.KEY_SPACE) and not pos["Crouch"]:
        if pos["vy"] <= 0:
            if pos["Start_Jumping"] == None and not pos["Falling"]:
                pos["Start_Jumping"] = pos["y"] 
                pos["vy"] += pos["jump_strength"]
            elif abs(pos["y"] - pos["Start_Jumping"]) < 31 and not pos["Stop_Jumping"]:
                pos["vy"] -= 0.21
            else:
                pos["Stop_Jumping"] = True
    pos["vy"] = min(pos["vy"] + pos["Gravity"],2)
    
    if pyxel.btn(pyxel.KEY_LEFT):
        if not pos["Crouch"] :
            if not pos["IsInAir"]:
                if not pos["Punch"]:
                    pos["vx"] = max(pos["vx"]-pos["Accelx"],-2)
                else:
                    pos["vx"] = 0
            else:
                pos["vx"] = max(pos["vx"]-pos["Accelx"]*pos["Air_inertia"],-2)
            pos["Ground_Locomotion"] = True
        pos["Direction"] = -1
    
    elif pyxel.btn(pyxel.KEY_RIGHT):
        if not pos["Crouch"] :
            if not pos["IsInAir"]:
                if not pos["Punch"]:
                    pos["vx"] = min(pos["vx"]+pos["Accelx"],2)
                else:
                    pos["vx"] = 0
            else:
                pos["vx"] = min(pos["vx"]+pos["Accelx"]*pos["Air_inertia"],2)
            pos["Ground_Locomotion"] = True
        pos["Direction"] = 1
    else:
        pos["Ground_Locomotion"] = False
        if not -pos["Accelx"] < pos["vx"] < pos["Accelx"]:
            pos["vx"] = pos["vx"] + (pos["Accelx"]* pos["vx"]/ abs(pos["vx"])*-1)
        else:
            pos["vx"] = 0
    
    if pos["Crouch"]:
        pos["Ground_Locomotion"] = False
        if not -pos["Accelx"] < pos["vx"] < pos["Accelx"]:
            pos["vx"] = pos["vx"] + (pos["Accelx"]* pos["vx"]/ abs(pos["vx"])*-1)
        else:
            pos["vx"] = 0
        
        
    # tests des collisions
    collision_test = []
    collision_oject_type = []
    offset_camera_to_correct_position_x = int()
    offset_camera_to_correct_position_y = int()
    for i in range(len(tuiles)):
        if dict_tile_to_object_type[i] == "Decor":
            continue
        for j in tuiles[i]:
            a = contact([pos["x"],pos["y"],16,24],[j[0],j[1],16,16])
            if a > 0:
                object_type = dict_tile_to_object_type[i]
                if object_type == "Breakable Block" and pos["Punch"] and pos["frame_start_punch"] - pyxel.frame_count == 0:
                    if a in [3,4]:
                        if i == 5:
                            tuiles[i].remove(j), tuiles[0].append(j)
                        else:
                            pos["x"] = [pos["x"] - 2, pos["x"] + 2][a == 3]
                            tuiles[i].remove(j), tuiles[15].append(j)
                    
                if object_type == "Breakable Block" or  object_type == "World Static":
                    if a == 1  and pos["vy"] > 0:
                        pos["y"] = j[1] - 24
                        pos["vy"] = 0
                        pos["Falling"] = False
                        pos["Start_Jumping"] = None
                        pos["Stop_Jumping"] = False
                    elif a == 2 and pos["vy"] < 0:
                        pos["y"] = j[1] + 16
                        pos["vy"] = 0
                        pos["Falling"] = True
                        pos["Stop_Jumping"] = True
                    elif a == 3 and  pos["vx"] < 0:
                        pos["x"] = j[0] + 16
                        pos["vx"] = 0
                    elif a == 4 and pos["vx"] > 0 :
                        pos["x"] = j[0] - 16
                        pos["vx"] = 0
                if object_type == "Collectibles":
                    tuiles[i].remove(j), tuiles[0].append(j)
                    
                collision_test.append([a,dict_tile_to_object_type[i]])
                collision_oject_type.append([dict_tile_to_object_type[i]])
    
    
     
    # déplacement de la caméra de façon à ce que personnage soit à peu près centré
    pyxel.camera(0,min(max(0,pos["y"]-128 + pos["vy"]),1664))
    
    pos["x"] += pos["vx"]
    pos["y"] += pos["vy"]

    
    if abs(pos["vy"]) > 0 or pos["Falling"]:
        pos["IsInAir"] = True
        pos["Crouch"] = False
    else:
        pos["IsInAir"] = False
    
      

def play_flipbook_player(name,u,v,nb_img):
        if pos["Name_flipbook"] != name:
            pos["Name_flipbook"] = name
            pos["frame_index"] = 0
        if pyxel.frame_count % 6 == 0 and nb_img > 2:
                pos["frame_index"] = (pos["frame_index"] + 1) % (nb_img - 1)
        elif nb_img == 2 and pyxel.frame_count % 3 == 0:
            pos["frame_index"] = 1 - pos["frame_index"]
        
        if pos["Punch"] and pos["Direction"] == -1:
            pyxel.blt(pos["x"]-7,pos["y"]-1, 0, u + 16 * pos["frame_index"],v,pos["w"] * pos["Direction"],pos["h"],7)
        else:
             pyxel.blt(pos["x"],pos["y"]-1, 0, u + 16 * pos["frame_index"],v,pos["w"] * pos["Direction"],pos["h"],7)

            
                               
def draw():
    #effacement du terrain
    pyxel.cls(0)
    
    # dessin du niveau
    for i in range(len(tuiles)):
        for j in tuiles[i]:
            pyxel.blt(j[0], j[1], 2, 16*(i%cote), 16*(i//cote), 16, 16)
    
    # dessin du personnage
    if pos["Punch"] :
        pos["w"], pos["h"] = 23,25
        play_flipbook_player("Punch", 19,27, 1)
        if pyxel.frame_count - pos["frame_start_punch"] == 14:
            pos["Punch"] = False
        return None
            
    if pos["Crouch"]:
        play_flipbook_player("Crouch", 60,27, 1)
        return None
    if pos["IsInAir"] or pyxel.btn(pyxel.KEY_SPACE):
        pos["w"], pos["h"] = 16,25
        play_flipbook_player("Jump", 44,27, 1)
    elif not abs(pos["vx"]) == 0 and pos["vy"] == 0 :
        pos["w"], pos["h"] = 17,25
        play_flipbook_player("Ground Locomotion", 1,0, 4)
    else:
        if pos["vx"] == 0:
            pos["w"], pos["h"] = 16,25
            play_flipbook_player("Idle",1, 27, 1)
            
    
def contact(obj_1, obj_2):
    """
    Détermine si deux objets (définis par leur hitbox) sont en contact et sur quelle face.
    
    :param obj_1: Hitbox de l'objet 1 sous la forme [x, y, largeur, hauteur]
    :param obj_2: Hitbox de l'objet 2 sous la forme [x, y, largeur, hauteur]
    :return: Un code indiquant le côté de contact ou 0 s'il n'y a pas de contact
        0: Pas de contact
        1: Contact sous obj_1
        2: Contact au-dessus de obj_1
        3: Contact à droite de obj_1
        4: Contact à gauche de obj_1
        
    Avantage : Si l'on veut simplement savoir s'il y a un contact, un test logique suffit.
    La méthode utilise une détection de collision entre les contours des objets pour déterminer le contact.
    """
    
    if contact2([obj_1[0], obj_1[1] + obj_1[3], obj_1[2], 1], [obj_2[0], obj_2[1], obj_2[2], 5]):
        return 1
    if contact2([obj_1[0], obj_1[1], obj_1[2], 1], [obj_2[0], obj_2[1] + obj_2[3] - 5, obj_2[2], 5]):
        return 2
    if contact2([obj_1[0], obj_1[1], 1, obj_1[3]], [obj_2[0] + obj_2[2], obj_2[1], 2, obj_2[3]]):
        return 3
    if contact2([obj_1[0] + obj_1[2], obj_1[1], 1, obj_1[3]], [obj_2[0], obj_2[1], 2, obj_2[3]]):
        return 4
    return 0


def contact2(A, B):
    #print(A,B)
    """
    Indique si 2 rectangles A et B définis par [x_haut, y_haut, largeur, hauteur] se recouvrent
    """
    maxgauche = max(A[0], B[0])
    mindroit = min(A[0] + A[2], B[0] + B[2])
    if maxgauche < mindroit :
        maxbas = max(A[1], B[1])
        minhaut = min(A[1] + A[3], B[1] + B[3])
        if maxbas < minhaut :
            return True
    return False


pyxel.run(update, draw)

# Created by NANU Albert-Costin; RAYMOND Hugo, RUIVO Aurane.