import pyxel 

pyxel.init(128, 128,title= "Super Mushroom Bros",fps = 30)
pyxel.load("4.pyxres")

# Variables
game_state = 0
camera_x = 0
camera_y = 0


# Joueur
player_speed = 2.5
player_x = 60 
player_y = 60
player_u = 0 
player_v = 16
velocity_y = 0
gravity = 1
jump_force = -8
on_ground = False
bladeliste = []
blade_speed = 1
charge = 0
sprite_liste = [0,8]

# - tiles bloc (tout)

BLOC_JAUNE = (10,20)

PETITE_PLANCHE = (0,26)
LONGUE_PLANCHE_R = (3,26)
LONGUE_PLANCHE = (2,26)
LONGUE_PLANCHE_L = (1,26)

tiles_sol_dur = [
    BLOC_JAUNE,
    PETITE_PLANCHE,LONGUE_PLANCHE,LONGUE_PLANCHE_L,LONGUE_PLANCHE_R
]

# Décor - tiles solides (sols)
SOL_HERBE_L = (10, 27) 
SOL_HERBE = (11, 27)
SOL_HERBE_R = (12, 27)
SOL_BOIS_L = (1, 27) 
SOL_BOIS = (2, 27)
SOL_BOIS_R = (3, 27) 
PLANCHE_L = (1, 25)
PLANCHE = (2, 25)
PLANCHE_R = (3, 25)

tiles_sol = [
    SOL_HERBE_L, SOL_HERBE, SOL_HERBE_R,
    SOL_BOIS_L, SOL_BOIS, SOL_BOIS_R,
    PLANCHE_L, PLANCHE, PLANCHE_R,
    
]

# - tiles solide (murs)
TERRE_L = (10,28)
TERRE_L_DOWN = (10,29)
TERRE_CENTER = (11,28)
TERRE_CENTER_DOWN = (11,29)
TERRE_R = (12,28)
TERRE_R_DOWN = (12,29)

tiles_mur = [
    TERRE_L,TERRE_L_DOWN,
    TERRE_CENTER,TERRE_CENTER_DOWN,
    TERRE_R,TERRE_R_DOWN,
    BLOC_JAUNE, PETITE_PLANCHE,
    LONGUE_PLANCHE_R,LONGUE_PLANCHE,LONGUE_PLANCHE_L 
    ]

# - tiles solide (plafonds)

tiles_plafond = [
    TERRE_CENTER_DOWN,TERRE_L_DOWN,TERRE_R_DOWN,
    BLOC_JAUNE, PETITE_PLANCHE,
    LONGUE_PLANCHE_L,LONGUE_PLANCHE,LONGUE_PLANCHE_R
    ]



# Fonctions
def blade_reloaded(recharge):
    if pyxel.frame_count % 60 == 0 and recharge == 0:
        recharge += 1
    return recharge


def blade_creation(x,y,bladeliste,recharge):
    if pyxel.btnr(pyxel.KEY_ALT) and recharge == 1:
        bladeliste.append([x,y])
        recharge = 0
    return bladeliste

def blade_deplacement(bladeliste):
    for blade in bladeliste:
        blade[0] += blade_speed 
        if blade[0] > 256:
            bladeliste.remove(blade) 
    return bladeliste 

def change_state(state):
    if state == 0:
        if pyxel.btn(pyxel.KEY_SPACE) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_A):
            state = 1
    return state

def est_solide(x_pixel, y_pixel):
    tile_x = int(x_pixel // 8)
    tile_y = int(y_pixel // 8)
    tile = pyxel.tilemap(0).pget(tile_x, tile_y)
    return tile in tiles_sol

def est_mur(x_pixel, y_pixel):
    tile_x = int(x_pixel // 8)
    tile_y = int(y_pixel // 8)
    tile = pyxel.tilemap(0).pget(tile_x, tile_y)
    return tile in tiles_mur

def est_plafond(x_pixel, y_pixel):
    tile_x = int(x_pixel // 8)
    tile_y = int(y_pixel // 8)
    tile = pyxel.tilemap(0).pget(tile_x,tile_y)
    return tile in tiles_plafond

def on_floor(x, y):
    """Vérifie si le joueur est sur un sol solide ou un bloc non traversable"""
    tile = pyxel.tilemap(0).pget((x + 3) // 8, (y + 8) // 8)
    return tile in tiles_sol or tile in tiles_sol_dur


def player_deplacement(x, y):
    new_x = x
    new_y = y 
    if pyxel.btn(pyxel.KEY_RIGHT) or pyxel.btn(pyxel.KEY_D) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_RIGHT):
        if x < 10000:
            # Vérifie collision à droite (devant le joueur)
            if not est_mur(x + 8, y) and not est_mur(x + 8, y + 7):
                new_x += player_speed
    if pyxel.btn(pyxel.KEY_LEFT) or pyxel.btn(pyxel.KEY_Q) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_LEFT):
        if x > 0:
            # Vérifie collision à gauche (devant le joueur)
            if not est_mur(x - 1, y) and not est_mur(x - 1, y + 7):
                new_x -= player_speed
    return new_x, new_y



def collision_sol_precise(x, y, vy):
    foot_x = int((x + 3) // 8)
    foot_y = int((y + 8) // 8)
    tile = pyxel.tilemap(0).pget(foot_x, foot_y)

    if tile in tiles_sol and vy >= 0:
        y = foot_y * 8 - 8
        vy = 0
    return y, vy


def collision_sol_dur(x, y, vy):
    foot_x = int((x + 3) // 8)
    foot_y = int((y + 8) // 8)
    head_y = int((y - 1) // 8)

    tile_foot = pyxel.tilemap(0).pget(foot_x, foot_y)
    tile_head = pyxel.tilemap(0).pget(foot_x, head_y)

    if tile_foot in tiles_sol_dur and vy >= 0:
        y = foot_y * 8 - 8
        vy = 0
    elif tile_head in tiles_sol_dur and vy < 0:
        y = (head_y + 1) * 8
        vy = 0
    return y, vy




def sprite_balance(sprite_liste):
    if pyxel.btn(pyxel.KEY_RIGHT) or pyxel.btn(pyxel.KEY_D) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_RIGHT):
        sprite_liste[1] = 16
        sprite_liste[0] += 8
        if sprite_liste[0] == 40 or sprite_liste[0] == 0:
            sprite_liste[0] = 0
    if pyxel.btnr(pyxel.KEY_RIGHT) or pyxel.btnr(pyxel.KEY_D) or pyxel.btnr(pyxel.GAMEPAD1_BUTTON_DPAD_RIGHT):
        sprite_liste[0] = 0
        sprite_liste[1] = 16
    if pyxel.btn(pyxel.KEY_LEFT) or pyxel.btn(pyxel.KEY_Q) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_LEFT):   
        sprite_liste[1] = 24
        sprite_liste[0] += 8
        if sprite_liste[0] == 40 or sprite_liste[0] == 0:
            sprite_liste[0] = 0
    if pyxel.btnr(pyxel.KEY_LEFT) or pyxel.btnr(pyxel.KEY_Q) or pyxel.btnr(pyxel.GAMEPAD1_BUTTON_DPAD_LEFT):
        sprite_liste[0] = 0
        sprite_liste[1] = 24
    if (pyxel.btn(pyxel.KEY_ALT) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_B)) and not ((pyxel.btn(pyxel.KEY_RIGHT) or pyxel.btn(pyxel.KEY_D) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_RIGHT)) or (pyxel.btn(pyxel.KEY_LEFT) or pyxel.btn(pyxel.KEY_Q) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_LEFT))):
        if sprite_liste[1] == 16:
            sprite_liste[0] = 0
            sprite_liste[1] = 8
        elif sprite_liste[1] == 24:
            sprite_liste[0]= 24
            sprite_liste[1] = 8
    if pyxel.btnr(pyxel.KEY_ALT) or pyxel.btnr(pyxel.GAMEPAD1_BUTTON_B):
        if sprite_liste[1] == 8 and sprite_liste[0] == 0:
            sprite_liste[0] = 0
            sprite_liste[1] = 16
        elif sprite_liste[0] == 24 and sprite_liste[1] == 8:
            sprite_liste[0] = 0
            sprite_liste[1] = 24
    return sprite_liste


def update_game():
    global player_x, player_y, player_u, player_v, velocity_y, on_ground, camera_x,camera_y, bladeliste, charge, sprite_liste

    sprite_liste = sprite_balance(sprite_liste)
    player_x, player_y = player_deplacement(player_x, player_y)
    player_y, velocity_y = collision_sol_precise(player_x, player_y, velocity_y)
    player_y, velocity_y = collision_sol_dur(player_x, player_y, velocity_y)
    on_ground = on_floor(player_x, player_y) and velocity_y == 0


    bladeliste = blade_creation(player_x,player_y,bladeliste,charge) 
    bladeliste = blade_deplacement(bladeliste)
    charge =  blade_reloaded(charge)

    if on_floor(player_x, player_y):
        on_ground = True 
        velocity_y = 0
        if pyxel.btnp(pyxel.KEY_SPACE) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_A):
            velocity_y = jump_force
            on_ground = False
    elif est_plafond(player_x, player_y - 1) and  est_plafond(player_x +7, player_y -1):
        velocity_y = 2.5
    else:
        if velocity_y < 9:
            velocity_y += gravity
        else:
            velocity_y = 8
    

    player_y += velocity_y
    


    # Taille de l'écran
    screen_width = 128
    screen_height = 128

    # Taille de la map en pixels
    map_width = pyxel.tilemap(0).width * 8
    map_height = pyxel.tilemap(0).height * 8

    # --- CIBLE HORIZONTALE : toujours centrée ---
    target_camera_x = int(player_x - screen_width // 2 + 4)
    target_camera_x = max(0, min(target_camera_x, map_width - screen_width))
    camera_x += (target_camera_x - camera_x) * 0.1

    # --- CIBLE VERTICALE : seulement si le joueur sort d'une zone centrale ---
    margin = 32  # zone de confort verticale

    top_limit = camera_y + margin
    bottom_limit = camera_y + screen_height - margin

    if player_y < top_limit:
        camera_y -= (top_limit - player_y) * 0.2
    elif player_y > bottom_limit:
        camera_y += (player_y - bottom_limit) * 0.2

    # Empêcher la caméra de sortir de la map verticalement
    camera_y = max(0, min(camera_y, map_height - screen_height))


    # Interpolation fluide vers la position cible
    camera_x += (target_camera_x - camera_x) * 0.2
    


    

    #réapprition du joueur si il tombe dans le vide :
    if player_y > 10000 or pyxel.btn(pyxel.KEY_R):
        player_x = 10
        player_y = 56

    if pyxel.btnp(pyxel.KEY_ESCAPE):
        pyxel.quit()

def draw_game():
    pyxel.cls(6)
    pyxel.bltm(0, 0, 0, camera_x , camera_y , 128, 128, 5)
    pyxel.blt(player_x - camera_x, player_y - camera_y, 0, sprite_liste[0], sprite_liste[1], 8, 8, 5)
    for blade in bladeliste:
        pyxel.blt(blade[0],blade[1],0,48,88,8,8,5) 
    
    if on_floor(player_x, player_y):
        pyxel.text(5, 5, "AU SOL", 7)
    else:
        pyxel.text(5, 5, "EN L'AIR", 8)

    pyxel.text(5, 15, f"Cam: {camera_x}, {camera_y}", 7)
    pyxel.text(5, 25, f"Player: {player_x}, {player_y}", 7)



def update():
    global game_state
    if game_state == 1:
        update_game()
    game_state = change_state(game_state)

def draw():
    if game_state == 1:
        draw_game()
    else:
        pyxel.cls(0)
        pyxel.text(40, 64, "PRESS SPACE !", 7)

pyxel.run(update, draw)