from typing import Optional import pygame.time from level.Level import Level from level.LevelManager import LevelManager from level.selection.ScreenManager import ScreenManager from physics import ConstantsParser from physics.SpriteManager import SpriteManager, DrawLayers from physics.TickData import TickData from sprite.PositionScale import PositionScale from sprite.SpritesheetManager import SpritesheetManager from sprite.StaticSprite import StaticSprite from ui_elements.ClickEvent import ClickEvent from ui_elements.KeyManager import KeyManager from ui_elements.TextLabel import TextLabel LABEL_COUNT = 10 OFFSET = (50, 20) class LevelSelectionScreenManager(ScreenManager): def __init__(self, sprite_manager: SpriteManager, spritesheet_manager: SpritesheetManager, main_loop, level_manager: LevelManager): super().__init__(sprite_manager, spritesheet_manager, main_loop) self.level_manager = level_manager self.levels_by_theme = self.level_manager.get_levels_by_theme() self.themes = ConstantsParser.CONFIG.themes self.level_labels: list[TextLabel] = [] self.theme_label: Optional[TextLabel] = None self.selected_theme = self.themes[0] self.key_input_delay = -1 def select_next_theme(self, click=None): if click is None or click.is_click_down(ClickEvent.CLICK_LEFT): index = (self.themes.index(self.selected_theme) + 1) % len(self.themes) self.select_theme(self.themes[index]) def select_prev_theme(self, click=None): if click is None or click.is_click_down(ClickEvent.CLICK_LEFT): index = self.themes.index(self.selected_theme) - 1 if index < 0: index = len(self.themes) - 1 self.select_theme(self.themes[index]) def select_level(self, click: ClickEvent, level: Level): if click.is_click_down(ClickEvent.CLICK_LEFT): self.main_loop.select_level(level) def go_to_menu(self, click): if click.is_click_down(ClickEvent.CLICK_LEFT): self.main_loop.select_main_menu() def initialize(self): arrow_left = StaticSprite(self.spritesheet_manager.get_sheet('ui_arrow')) arrow_left.set_animation_state('right') arrow_left.position_scale = PositionScale((OFFSET[0], OFFSET[1]), (1.8, 1.8)) arrow_left.add_click_listener(self.select_prev_theme) self.add_element(DrawLayers.UI, arrow_left) arrow_right = StaticSprite(self.spritesheet_manager.get_sheet('ui_arrow')) arrow_right.set_animation_state('left') arrow_right.position_scale = PositionScale((OFFSET[0] + 50, OFFSET[1]), (1.8, 1.8)) arrow_right.add_click_listener(self.select_next_theme) self.add_element(DrawLayers.UI, arrow_right) self.theme_label = TextLabel('', OFFSET[0] + 120, OFFSET[1] - 2, font_size=65) self.theme_label.position_scale.scale = (0.5, 0.5) self.add_element(DrawLayers.UI, self.theme_label) self.back_button = TextLabel('BACK [ESC]', 610, 430, font_size=30) self.back_button.position_scale.scale = (0.5, 0.5) self.add_element(DrawLayers.UI, self.back_button) self.back_button.add_click_listener(lambda click: self.go_to_menu(click)) for i in range(0, LABEL_COUNT): label = TextLabel(str(i), OFFSET[0] + 30, OFFSET[1] + 60 + i * 50, font_size=65) label.position_scale.scale = (0.5, 0.5) self.level_labels.append(label) self.add_element(DrawLayers.UI, label) self.select_theme(self.selected_theme) def select_theme(self, theme: str): self.selected_theme = theme self.theme_label.set_text(theme) for label in self.level_labels: label.set_text('') label.click_listeners = [] levels = self.levels_by_theme[self.selected_theme] if len(levels) > 0: self.level_labels[0].set_text(levels[0].name) self.level_labels[0].add_click_listener( lambda click: self.select_level(click, levels[0]) ) if len(levels) > 1: self.level_labels[1].set_text(levels[1].name) self.level_labels[1].add_click_listener( lambda click: self.select_level(click, levels[1]) ) if len(levels) > 2: self.level_labels[2].set_text(levels[2].name) self.level_labels[2].add_click_listener( lambda click: self.select_level(click, levels[2]) ) if len(levels) > 3: self.level_labels[3].set_text(levels[3].name) self.level_labels[3].add_click_listener( lambda click: self.select_level(click, levels[3]) ) if len(levels) > 4: self.level_labels[4].set_text(levels[4].name) self.level_labels[4].add_click_listener( lambda click: self.select_level(click, levels[4]) ) if len(levels) > 5: self.level_labels[5].set_text(levels[5].name) self.level_labels[5].add_click_listener( lambda click: self.select_level(click, levels[5]) ) if len(levels) > 6: self.level_labels[6].set_text(levels[6].name) self.level_labels[6].add_click_listener( lambda click: self.select_level(click, levels[6]) ) if len(levels) > 7: self.level_labels[7].set_text(levels[7].name) self.level_labels[7].add_click_listener( lambda click: self.select_level(click, levels[7]) ) if len(levels) > 8: self.level_labels[8].set_text(levels[8].name) self.level_labels[8].add_click_listener( lambda click: self.select_level(click, levels[8]) ) if len(levels) > 9: self.level_labels[9].set_text(levels[9].name) self.level_labels[9].add_click_listener( lambda click: self.select_level(click, levels[9]) ) def destroy(self): super().destroy() def tick(self, tick_data: TickData): if self.key_input_delay >= 0: self.key_input_delay -= tick_data.dt if self.key_input_delay <= 0: if tick_data.key_manager.is_keymap_down(KeyManager.KEY_ESCAPE): self.main_loop.select_main_menu() elif tick_data.key_manager.is_keymap_down(KeyManager.KEY_LEFT): self.select_prev_theme() self.key_input_delay = 5 elif tick_data.key_manager.is_keymap_down(KeyManager.KEY_RIGHT): self.select_next_theme() self.key_input_delay = 5