import pygame
import sys

pygame.init()
pygame.mixer.init()

WIDTH, HEIGHT = 1920, 1080
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Goblin & Knight")

CLOCK = pygame.time.Clock()
BLACK = (0, 0, 0)
GRAVITY = 0.9
GROUND_Y = HEIGHT - 60

FPS = 60

BACKGROUND = pygame.image.load("images/back_main.jpg")
BACKGROUND = pygame.transform.scale(BACKGROUND, (WIDTH, HEIGHT))
BACK_MAIN = pygame.image.load("images/back_main.jpg")
BACK_MAIN = pygame.transform.scale(BACK_MAIN, (WIDTH, HEIGHT))

BG_MUSIC = None
try:
    BG_MUSIC = pygame.mixer.music
    pygame.mixer.music.load('music/musica.mp3')
    pygame.mixer.music.set_volume(1)
    pygame.mixer.music.play(-1)
except Exception:
    BG_MUSIC = None

FONT = pygame.font.SysFont(None, 32)

score_goblin = 0
score_knight = 0

paused = False

floor_score = 1
MAX_FLOOR_SCORE = 8

class Player:
    def __init__(self, x, y, sprites, scale, controls):
        self.start_x = x
        self.start_y = y

        self.x = float(x)
        self.y = float(y)

        self.y_velocity = 0.0
        self.jump_power = 18
        self.jumping = False
        self.facing_right = True
        self.moving = False
        self.speed = 5.5

        self.controls = controls

        self.anim_counter = 0
        self.ANIM_SPEED = 8

        self.stand = pygame.image.load(sprites["stand"]).convert_alpha()
        self.walk_left = pygame.image.load(sprites["walk_left"]).convert_alpha()
        self.walk_right = pygame.image.load(sprites["walk_right"]).convert_alpha()

        jump_entry = sprites.get("jump")
        if isinstance(jump_entry, (list, tuple)) and len(jump_entry) == 3:
            self.jump_start = pygame.image.load(jump_entry[0]).convert_alpha()
            self.jump_mid = pygame.image.load(jump_entry[1]).convert_alpha()
            self.jump_end = pygame.image.load(jump_entry[2]).convert_alpha()
        elif all(k in sprites for k in ("jump_start", "jump_mid", "jump_end")):
            self.jump_start = pygame.image.load(sprites["jump_start"]).convert_alpha()
            self.jump_mid = pygame.image.load(sprites["jump_mid"]).convert_alpha()
            self.jump_end = pygame.image.load(sprites["jump_end"]).convert_alpha()
        else:
            single_path = jump_entry if isinstance(jump_entry, str) else sprites.get("jump", sprites["stand"])
            single = pygame.image.load(single_path).convert_alpha()
            self.jump_start = self.jump_mid = self.jump_end = single

        self.stand = pygame.transform.scale(self.stand, (int(self.stand.get_width() * scale), int(self.stand.get_height() * scale)))
        self.walk_left = pygame.transform.scale(self.walk_left, (int(self.walk_left.get_width() * scale), int(self.walk_left.get_height() * scale)))
        self.walk_right = pygame.transform.scale(self.walk_right, (int(self.walk_right.get_width() * scale), int(self.walk_right.get_height() * scale)))
        self.jump_start = pygame.transform.scale(self.jump_start, (int(self.jump_start.get_width() * scale), int(self.jump_start.get_height() * scale)))
        self.jump_mid = pygame.transform.scale(self.jump_mid, (int(self.jump_mid.get_width() * scale), int(self.jump_mid.get_height() * scale)))
        self.jump_end = pygame.transform.scale(self.jump_end, (int(self.jump_end.get_width() * scale), int(self.jump_end.get_height() * scale)))

        self.surface = self.stand
        self.rect = self.surface.get_rect(midbottom=(self.x, self.y))

        
        self.prev_y = self.y

    def reset(self):
        self.x = self.start_x
        self.y = self.start_y
        self.y_velocity = 0
        self.jumping = False
        self.moving = False
        self.anim_counter = 0
        self.facing_right = True
        self.rect = self.surface.get_rect(midbottom=(self.x, self.y))

    def handle_input(self, keys):
        self.moving = False

        if keys[self.controls["right"]]:
            self.x += self.speed
            self.facing_right = True
            self.moving = True

        if keys[self.controls["left"]]:
            self.x -= self.speed
            self.facing_right = False
            self.moving = True

        if keys[self.controls["jump"]] and not self.jumping:
            self.jumping = True
            self.y_velocity = -self.jump_power

        if self.x < 0:
            self.x = 0
        if self.x > WIDTH:
            self.x = WIDTH

    def apply_gravity(self):
        self.prev_y = self.y
        self.y_velocity += GRAVITY
        self.y += self.y_velocity

        if self.y >= GROUND_Y:
            self.y = GROUND_Y
            self.y_velocity = 0
            self.jumping = False

        if self.y < 0:
            self.y = 0
            self.y_velocity = 0
    def update_animation(self):
        if self.jumping:
            up_thresh = -self.jump_power * 0.4
            down_thresh = self.jump_power * 0.4
            if self.y_velocity < up_thresh:
                self.surface = self.jump_start
            elif self.y_velocity > down_thresh:
                self.surface = self.jump_end
            else:
                self.surface = self.jump_mid
        elif self.moving:
            self.anim_counter += 1
            frame = (self.anim_counter // self.ANIM_SPEED) % 2
            self.surface = self.walk_left if frame == 0 else self.walk_right
        else:
            self.surface = self.stand

        if not self.facing_right:
            self.surface = pygame.transform.flip(self.surface, True, False)

        self.rect = self.surface.get_rect(midbottom=(int(self.x), int(self.y)))

    def draw(self, screen):
        screen.blit(self.surface, self.rect)

goblin = Player(
    200, GROUND_Y,
    {
        "stand": "images/GoblinWorker/spritePics/stand_gob.png",
        "walk_left": "images/GoblinWorker/spritePics/walkleft.png",
        "walk_right": "images/GoblinWorker/spritePics/walkright.png",
        "jump": "images/GoblinWorker/spritePics/Jump.png"
    },
    3,
    {
        "left": pygame.K_a,
        "right": pygame.K_d,
        "jump": pygame.K_SPACE
    }
)

knight = Player(
    500, GROUND_Y,
    {
        "stand": "images/knight-named/stand.png",
        "walk_left": "images/knight-named/walkleft.png",
        "walk_right": "images/knight-named/walkright.png",
        "jump": [
            "images/knight-named/roll1.png",
            "images/knight-named/roll2.png",
            "images/knight-named/roll3.png"
        ]
    },
    3,
    {
        "left": pygame.K_KP4,
        "right": pygame.K_KP6,
        "jump": pygame.K_KP8
    }
)

door_image = pygame.image.load("images/door.png")
door_image = pygame.transform.scale(door_image,(int(door_image.get_width() * 3), int(door_image.get_height() * 3)))

DOOR_POSITIONS = {
    1: (100, GROUND_Y - 645),
    2: (1800, GROUND_Y-565),
    3: (1550,GROUND_Y-525),
    4: (50,  GROUND_Y - 725),
    5: (900,  GROUND_Y - 685),
    6: (200,GROUND_Y-625),
    7: (1700, GROUND_Y - 745),
    8: (1300, GROUND_Y - 875)
    }
door_rect = door_image.get_rect(center=(WIDTH//2, GROUND_Y))

def place_door_for_level(lvl):
    global door_rect
    if lvl in DOOR_POSITIONS:
        x, y = DOOR_POSITIONS[lvl]
        door_rect = door_image.get_rect(midbottom=(x, y))
    else:
        door_rect = door_image.get_rect(center=(WIDTH // 2, GROUND_Y - door_image.get_height() // 2))
    door_rect.clamp_ip(pygame.Rect(0, 0, WIDTH, HEIGHT))

button_play = pygame.image.load("images/play_button.png").convert_alpha()
button_play.set_colorkey((0,0,0))
button_play = pygame.transform.scale(
    button_play,
    (int(button_play.get_width() * 2.5), int(button_play.get_height() * 2.5))
)
button_rect = button_play.get_rect(center=(WIDTH // 2, HEIGHT // 2))

buttonlvl1 = pygame.image.load("images/button_lvl/F1.png")
buttonlvl2 = pygame.image.load("images/button_lvl/F2.png")
buttonlvl3 = pygame.image.load("images/button_lvl/F3.png")
buttonlvl4 = pygame.image.load("images/button_lvl/F4.png")
buttonlvl5 = pygame.image.load("images/button_lvl/F5.png")
buttonlvl6 = pygame.image.load("images/button_lvl/F6.png")
buttonlvl7 = pygame.image.load("images/button_lvl/F7.png")
buttonlvl8 = pygame.image.load("images/button_lvl/F8.png")

BUTTON_BIG_SIZE = (220, 140)
buttonlvl1_big = pygame.transform.scale(buttonlvl1, BUTTON_BIG_SIZE)
buttonlvl2_big = pygame.transform.scale(buttonlvl2, BUTTON_BIG_SIZE)
buttonlvl3_big = pygame.transform.scale(buttonlvl3, BUTTON_BIG_SIZE)
buttonlvl4_big = pygame.transform.scale(buttonlvl4, BUTTON_BIG_SIZE)
buttonlvl5_big = pygame.transform.scale(buttonlvl5, BUTTON_BIG_SIZE)
buttonlvl6_big = pygame.transform.scale(buttonlvl6, BUTTON_BIG_SIZE)
buttonlvl7_big = pygame.transform.scale(buttonlvl7, BUTTON_BIG_SIZE)
buttonlvl8_big = pygame.transform.scale(buttonlvl8, BUTTON_BIG_SIZE)

buttonlvl1_rect = buttonlvl1_big.get_rect(center=(300, 300))
buttonlvl2_rect = buttonlvl2_big.get_rect(center=(600, 300))
buttonlvl3_rect = buttonlvl3_big.get_rect(center=(900, 300))
buttonlvl4_rect = buttonlvl4_big.get_rect(center=(300, 600))
buttonlvl5_rect = buttonlvl5_big.get_rect(center=(600, 600))
buttonlvl6_rect = buttonlvl6_big.get_rect(center=(900, 600))
buttonlvl7_rect = buttonlvl7_big.get_rect(center=(300, 900))
buttonlvl8_rect = buttonlvl8_big.get_rect(center=(600, 900))

level_buttons = [
    None,
    (buttonlvl1_big, buttonlvl1_rect),
    (buttonlvl2_big, buttonlvl2_rect),
    (buttonlvl3_big, buttonlvl3_rect),
    (buttonlvl4_big, buttonlvl4_rect),
    (buttonlvl5_big, buttonlvl5_rect),
    (buttonlvl6_big, buttonlvl6_rect),
    (buttonlvl7_big, buttonlvl7_rect),
    (buttonlvl8_big, buttonlvl8_rect),
]

level1 = pygame.image.load("images/Levels/floor1.png")
level2 = pygame.image.load("images/Levels/floor2.png")
level3 = pygame.image.load("images/Levels/floor3.png")
level4 = pygame.image.load("images/Levels/floor4.png")
level5 = pygame.image.load("images/Levels/floor5.png")
level6 = pygame.image.load("images/Levels/floor6.png")
level7 = pygame.image.load("images/Levels/floor7.png")
level8 = pygame.image.load("images/Levels/floor8.png")

level_bgs = [
    None,
    pygame.transform.scale(level1, (WIDTH, HEIGHT)),
    pygame.transform.scale(level2, (WIDTH, HEIGHT)),
    pygame.transform.scale(level3, (WIDTH, HEIGHT)),
    pygame.transform.scale(level4, (WIDTH, HEIGHT)),
    pygame.transform.scale(level5, (WIDTH, HEIGHT)),
    pygame.transform.scale(level6, (WIDTH, HEIGHT)),
    pygame.transform.scale(level7, (WIDTH, HEIGHT)),
    pygame.transform.scale(level8, (WIDTH, HEIGHT)),
]

KEY_TO_LEVEL = {
    pygame.K_F1: 1,
    pygame.K_F2: 2,
    pygame.K_F3: 3,
    pygame.K_F4: 4,
    pygame.K_F5: 5,
    pygame.K_F6: 6,
    pygame.K_F7: 7,
    pygame.K_F8: 8,
}

dirt_smol = pygame.image.load("images/platforms-named/dirt_smol.png")
dirt_smol = pygame.transform.scale(dirt_smol, (int(dirt_smol.get_width() * 5), int(dirt_smol.get_height() * 3)))
dirt_big = pygame.image.load("images/platforms-named/dirt_big.png")
dirt_big = pygame.transform.scale(dirt_big, (int(dirt_big.get_width() * 5), int(dirt_big.get_height() * 3)))
grass_smol = pygame.image.load("images/platforms-named/grass_smol.png")
grass_smol = pygame.transform.scale(grass_smol, (int(grass_smol.get_width() * 5), int(grass_smol.get_height() * 3)))
grass_big = pygame.image.load("images/platforms-named/grass_big.png")
grass_big = pygame.transform.scale(grass_big, (int(grass_big.get_width() * 5), int(grass_big.get_height() * 3)))
sand_smol = pygame.image.load("images/platforms-named/sand_smol.png")
sand_smol = pygame.transform.scale(sand_smol, (int(sand_smol.get_width() * 5), int(sand_smol.get_height() * 3)))
sand_big = pygame.image.load("images/platforms-named/sand_big.png")
sand_big = pygame.transform.scale(sand_big, (int(sand_big.get_width() * 5), int(sand_big.get_height() * 3)))
ice_smol = pygame.image.load("images/platforms-named/ice_smol.png")
ice_smol = pygame.transform.scale(ice_smol, (int(ice_smol.get_width() * 5), int(ice_smol.get_height() * 3)))    
ice_big = pygame.image.load("images/platforms-named/ice_big.png")
ice_big = pygame.transform.scale(ice_big, (int(ice_big.get_width() * 5), int(ice_big.get_height() * 3)))    

PLATFORM_IMAGES = {
    "dirt_smol": dirt_smol,
    "dirt_big": dirt_big,
    "grass_smol": grass_smol,
    "grass_big": grass_big,
    "sand_smol": sand_smol,
    "sand_big": sand_big,
    "ice_smol": ice_smol,
    "ice_big": ice_big,
}

LEVEL_BLOCKS = {
    1: [
        ("dirt_big",  (100,  GROUND_Y-120)),
        ("grass_smol",(400, GROUND_Y-180)),
        ("grass_big", (700, GROUND_Y - 240)),
        ("sand_smol", (1000, GROUND_Y - 300)),
        ("ice_smol",  (1300, GROUND_Y - 360)),
        ("grass_big", (1600, GROUND_Y - 220)),
        ("sand_big",  (1800, GROUND_Y - 340)),
        ("dirt_smol", (1600, GROUND_Y - 460)),
        ("grass_smol",(1800, GROUND_Y - 580)),
        ("ice_big",   (1600, GROUND_Y- 700)),
        ("dirt_big",  (1200, GROUND_Y - 700)),
        ("sand_smol", (900, GROUND_Y - 700)),
        ("grass_smol",(600, GROUND_Y - 700)),
        ("ice_smol",  (250, GROUND_Y - 520)),
        ("dirt_smol", (100, GROUND_Y - 620)),
    ],
    2: [
        ("dirt_big",(100,GROUND_Y-100)),
        ("grass_smol",(400,GROUND_Y-240)),
        ("grass_smol",(600,GROUND_Y-380)),
        ("sand_smol",(400,GROUND_Y-520)),
        ("grass_big",(100,GROUND_Y-660)),
        ("sand_smol",(400,GROUND_Y-720)),
        ("sand_big",(600,GROUND_Y-720)),
        ("sand_smol",(480,GROUND_Y-720)),
        ("sand_big",(1000,GROUND_Y-420)),
        ("dirt_smol",(1300,GROUND_Y-220)),
        ("grass_smol",(1500,GROUND_Y-360)),
        ("sand_smol",(1800,GROUND_Y-420)),
        ("ice_smol",(1800,GROUND_Y-540)),
    ],
    3: [
        ("ice_big",(400,GROUND_Y-120)),
        ("ice_smol",(100,GROUND_Y-240)),
        ("ice_smol",(400,GROUND_Y-360)),
        ("ice_smol",(100,GROUND_Y-480)),
        ("grass_big",(400,GROUND_Y-600)),
        ("sand_big",(100,GROUND_Y-720)),
        ("ice_big",(400,GROUND_Y-800)),
        ("grass_smol",(700,GROUND_Y-800)),
        ("ice_smol",(900,GROUND_Y-800)),
        ("grass_smol",(1100,GROUND_Y-800)),
        ("sand_big",(1400,GROUND_Y-800)),
        ("dirt_smol",(1600,GROUND_Y-800)),
        ("grass_smol",(1520,GROUND_Y-800)),
        ("sand_smol",(1550,GROUND_Y-500)),
        ],

    4: [
        ("dirt_big",   (400,  GROUND_Y - 120)), 
        ("grass_smol", (700,  GROUND_Y - 240)),
        ("grass_smol", (1000, GROUND_Y - 360)),
        ("sand_big",   (1300, GROUND_Y - 480)),
        ("sand_big",   (1600, GROUND_Y - 600)), 
        ("ice_smol",   (1300, GROUND_Y - 700)),
        ("ice_smol",   (1000, GROUND_Y - 780)),
        ("dirt_big",   (700,  GROUND_Y - 840)),
        ("dirt_big",   (400,  GROUND_Y - 840)), 
        ("grass_smol", (100,  GROUND_Y - 900)),
        ("grass_smol", (50,  GROUND_Y - 700)),
    ],

    5: [
        ("grass_big",  (150,  GROUND_Y - 120)),
        ("sand_smol",  (450,  GROUND_Y - 240)),
        ("sand_smol",  (750,  GROUND_Y - 360)), 
        ("ice_big",    (1050, GROUND_Y - 360)),
        ("ice_big",    (1350, GROUND_Y - 360)), 
        ("dirt_smol",  (1650, GROUND_Y - 360)),
        ("dirt_smol",  (1650, GROUND_Y - 500)),
        ("dirt_smol",  (1650, GROUND_Y - 640)),
        ("grass_big",  (1400,  GROUND_Y - 720)), 
        ("sand_smol",  (1100,  GROUND_Y - 720)),
        ("sand_smol",  (900,  GROUND_Y - 660)),
        
    ],

    
    6: [  
        ("grass_big",(200,GROUND_Y-120)),
        ("sand_big",(500,GROUND_Y-240)),
        ("ice_big",(800,GROUND_Y-360)),
        ("dirt_big",(1100,GROUND_Y-480)),
        ("grass_big",(1400,GROUND_Y-600)),
        ("sand_big",(1700,GROUND_Y-720)),
        ("ice_smol",(1400,GROUND_Y-840)),
        ("grass_smol",(1100,GROUND_Y-900)),
        ("sand_smol",(800,GROUND_Y-840)),
        ("ice_smol",(500,GROUND_Y-720)),
        ("grass_big",(200,GROUND_Y-600)),
    ],

    7: [
        ("ice_big",    (150, GROUND_Y - 120)),
        ("ice_big",    (150, GROUND_Y - 260)), 
        ("dirt_smol",  (150, GROUND_Y - 400)),
        ("dirt_smol",  (150, GROUND_Y - 540)),
        ("ice_smol",   (150, GROUND_Y - 680)),
        ("grass_big",  (600, GROUND_Y - 200)), 
        ("sand_smol",  (700, GROUND_Y - 340)),
        ("sand_smol",  (700, GROUND_Y - 480)),
        ("ice_smol",    (700, GROUND_Y - 620)),
        ("ice_big",    (950, GROUND_Y - 620)),
        ("dirt_smol",  (1150, GROUND_Y - 720)),
        ("grass_smol", (1450, GROUND_Y - 720)),
        ("sand_big",   (1750, GROUND_Y - 720)),
        ("sand_big",   (1700, GROUND_Y - 600)), 
    ],

    
    8: [
        ("dirt_big",   (700,  GROUND_Y - 120)),
        ("sand_big",   (1000, GROUND_Y - 240)),
        ("sand_big",   (1300, GROUND_Y - 240)),
        ("ice_smol",   (1600, GROUND_Y - 370)),
        ("ice_big",    (1300, GROUND_Y - 500)),
        ("ice_big",    (1000, GROUND_Y - 500)),
        ("dirt_smol",  (700,  GROUND_Y - 620)),
        ("grass_big",  (400,  GROUND_Y - 740)),
        ("sand_smol",  (700,  GROUND_Y - 850)),
        ("ice_big",    (1000, GROUND_Y - 850)),
        ("ice_big",    (1300, GROUND_Y - 850)), 
    ],
}


current_level_bg = None

def restart_level():
    goblin.reset()
    knight.reset()

def build_platform_rects(lvl):
    rects = []
    for name, pos in LEVEL_BLOCKS.get(lvl, []):
        img = PLATFORM_IMAGES.get(name)
        if img:
            rects.append(img.get_rect(midbottom=pos))
    return rects

def resolve_platform_collision(player, platform_rects):
    
    cur_rect = player.surface.get_rect(midbottom=(int(player.x), int(player.y)))
    prev_rect = player.surface.get_rect(midbottom=(int(player.x), int(player.prev_y)))

    for plat in platform_rects:
        if cur_rect.colliderect(plat):
            
            if prev_rect.bottom <= plat.top:
                player.y = plat.top
                player.y_velocity = 0
                player.jumping = False
                cur_rect = player.surface.get_rect(midbottom=(int(player.x), int(player.y)))
            
            elif prev_rect.top >= plat.bottom:
                
                top_offset = player.surface.get_rect().top  
                player.y = plat.bottom + (player.surface.get_height() - player.surface.get_rect().bottom)
                player.y_velocity = 0.1
                cur_rect = player.surface.get_rect(midbottom=(int(player.x), int(player.y)))
            else:
                
                if prev_rect.centerx < plat.centerx:
                    
                    player.x = plat.left - cur_rect.width / 2
                else:
                    
                    player.x = plat.right + cur_rect.width / 2
                cur_rect = player.surface.get_rect(midbottom=(int(player.x), int(player.y)))

    player.rect = player.surface.get_rect(midbottom=(int(player.x), int(player.y)))

level = 0
level_start_time = None

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_p:
                pygame.quit()
                sys.exit()
            if event.key == pygame.K_ESCAPE and level > 0:
                paused = not paused
            if event.key == pygame.K_r:
                restart_level()
                level = 0
            if level == -1 and event.key in KEY_TO_LEVEL:
                target = KEY_TO_LEVEL[event.key]
                if target <= floor_score:
                    restart_level()
                    level = target
                    level_start_time = pygame.time.get_ticks()
                    current_level_bg = level_bgs[level]
                    place_door_for_level(level)
                    if BG_MUSIC:
                        try: pygame.mixer.music.play(-1)
                        except Exception: pass

    keys = pygame.key.get_pressed()
    mouse_pos = pygame.mouse.get_pos()

    SCREEN.fill((0, 0, 0))

    if level == 0:
        SCREEN.blit(BACKGROUND, (0, 0))
        SCREEN.blit(button_play, button_rect)

        title_surf = FONT.render('Goblin & Knight', True, (255,255,255))
        SCREEN.blit(title_surf, (WIDTH//2 - title_surf.get_width()//2, 120))

        if button_rect.collidepoint(mouse_pos) and pygame.mouse.get_pressed()[0]:
            level = -1

    elif level == -1:
        SCREEN.blit(BACK_MAIN, (0, 0))

        title_surf = FONT.render('Select Level (F1..F8) — unlocked in order', True, (255,255,255))
        SCREEN.blit(title_surf, (WIDTH//2 - title_surf.get_width()//2, 80))

        for i in range(1, 9):
            btn_surf, btn_rect = level_buttons[i]
            if i <= floor_score:
                SCREEN.blit(btn_surf, btn_rect)
            else:
                locked = btn_surf.copy()
                locked.set_alpha(90)
                SCREEN.blit(locked, btn_rect)
                lock_txt = FONT.render('LOCKED', True, (200, 40, 40))
                SCREEN.blit(lock_txt, (btn_rect.centerx - lock_txt.get_width()//2, btn_rect.centery - 10))

        if pygame.mouse.get_pressed()[0]:
            for i in range(1, 9):
                btn_surf, btn_rect = level_buttons[i]
                if btn_rect.collidepoint(mouse_pos) and i <= floor_score:
                    restart_level()
                    level = i
                    level_start_time = pygame.time.get_ticks()
                    current_level_bg = level_bgs[level]
                    place_door_for_level(level)
                    if BG_MUSIC:
                        try: pygame.mixer.music.play(-1)
                        except Exception: pass
                    break

    elif level > 0:
        if current_level_bg:
            SCREEN.blit(current_level_bg, (0, 0))
        else:
            SCREEN.blit(BACKGROUND, (0, 0))

        for name, pos in LEVEL_BLOCKS.get(level, []):
            img = PLATFORM_IMAGES.get(name)
            if img:
                rect = img.get_rect(midbottom=pos)
                SCREEN.blit(img, rect)

        SCREEN.blit(door_image, door_rect)

        if not paused:
            goblin.handle_input(keys)
            goblin.apply_gravity()
            goblin.update_animation()

            knight.handle_input(keys)
            knight.apply_gravity()
            knight.update_animation()

            platform_rects = build_platform_rects(level)
            resolve_platform_collision(goblin, platform_rects)
            resolve_platform_collision(knight, platform_rects)

        goblin.draw(SCREEN)
        knight.draw(SCREEN)

        if not paused:
            if goblin.rect.colliderect(door_rect) and knight.rect.colliderect(door_rect):
                score_goblin += 1
                score_knight += 1

                if level == floor_score and floor_score < MAX_FLOOR_SCORE:
                    floor_score += 1

                restart_level()
                level = -1
                level_start_time = None
                current_level_bg = None
                pygame.time.delay(150)

    pygame.display.update()
    CLOCK.tick(FPS)