Example #1
0
    def test_disable(self, _init_pygame: None, default_ui_manager: UIManager,
                     _display_surface_return_none: None):
        container = UIScrollingContainer(pygame.Rect(100, 100, 200, 200),
                                         manager=default_ui_manager)
        button_1 = UIButton(relative_rect=pygame.Rect(10, 10, 150, 30),
                            text="Test Button",
                            tool_tip_text="This is a test of the button's tool tip functionality.",
                            manager=default_ui_manager,
                            container=container)

        button_2 = UIButton(relative_rect=pygame.Rect(10, 50, 150, 30),
                            text="Test Button 2",
                            manager=default_ui_manager,
                            container=container)

        container.disable()

        assert container.is_enabled is False
        assert button_1.is_enabled is False
        assert button_2.is_enabled is False

        # process a mouse button down event
        button_1.process_event(
            pygame.event.Event(pygame.MOUSEBUTTONDOWN, {'button': 1, 'pos': button_1.rect.center}))

        # process a mouse button up event
        button_1.process_event(
            pygame.event.Event(pygame.MOUSEBUTTONUP, {'button': 1, 'pos': button_1.rect.center}))

        button_1.update(0.01)

        assert button_1.check_pressed() is False
    def test_set_dimensions(self, _init_pygame, default_ui_manager,
                            _display_surface_return_none):
        container = UIScrollingContainer(pygame.Rect(100, 100, 200, 200),
                                         manager=default_ui_manager)

        container.set_dimensions((50, 50))

        assert container.rect.size == (50, 50)
Example #3
0
    def test_add_element(self, _init_pygame, default_ui_manager: IUIManagerInterface,
                         _display_surface_return_none):
        container = UIScrollingContainer(pygame.Rect(100, 100, 200, 200),
                                         manager=default_ui_manager)

        button = UIButton(relative_rect=pygame.Rect(0, 0, 50, 50), text="",
                          manager=default_ui_manager)
        default_ui_manager.get_root_container().remove_element(button)
        container.get_container().add_element(button)
        assert len(container.get_container().elements) == 1
    def test_set_relative_position(self, _init_pygame, default_ui_manager,
                                   _display_surface_return_none):
        container = UIScrollingContainer(pygame.Rect(100, 100, 200, 200),
                                         manager=default_ui_manager)
        container_2 = UIScrollingContainer(pygame.Rect(50, 50, 50, 50),
                                           manager=default_ui_manager,
                                           container=container)

        container_2.set_relative_position((25, 25))

        assert container_2.rect.topleft == (125, 125)
Example #5
0
    def test_set_scrollable_area_dimensions(self, _init_pygame, default_ui_manager,
                                            _display_surface_return_none):
        container = UIScrollingContainer(pygame.Rect(100, 100, 200, 200),
                                         manager=default_ui_manager)

        container.set_scrollable_area_dimensions((500, 600))

        assert container.vert_scroll_bar is not None
        assert container.horiz_scroll_bar is not None
        assert container.scrollable_container.rect.size == (500, 600)
        assert container._view_container.rect.size == (200-container.vert_scroll_bar.rect.width,
                                                       200-container.horiz_scroll_bar.rect.height)
    def test_show_hide_rendering(self, _init_pygame, default_ui_manager,
                                 _display_surface_return_none):
        resolution = (400, 400)
        empty_surface = pygame.Surface(resolution)
        empty_surface.fill(pygame.Color(0, 0, 0))

        surface = empty_surface.copy()
        manager = UIManager(resolution)

        container = UIScrollingContainer(relative_rect=pygame.Rect(
            100, 100, 200, 100),
                                         manager=manager,
                                         visible=0)
        container.set_scrollable_area_dimensions((600, 600))
        manager.update(0.01)
        manager.draw_ui(surface)
        assert compare_surfaces(empty_surface, surface)

        surface.fill(pygame.Color(0, 0, 0))
        container.show()
        manager.update(0.01)
        manager.draw_ui(surface)
        assert not compare_surfaces(empty_surface, surface)

        surface.fill(pygame.Color(0, 0, 0))
        container.hide()
        manager.update(0.01)
        manager.draw_ui(surface)
        assert compare_surfaces(empty_surface, surface)
    def test_show(self, _init_pygame, default_ui_manager,
                  _display_surface_return_none):
        container = UIScrollingContainer(relative_rect=pygame.Rect(
            100, 100, 400, 400),
                                         manager=default_ui_manager,
                                         visible=0)
        container.set_scrollable_area_dimensions((500, 600))

        assert container.visible == 0

        assert container._root_container.visible == 0
        assert container._view_container.visible == 0
        assert container.horiz_scroll_bar.visible == 0
        assert container.vert_scroll_bar.visible == 0
        assert container.scrollable_container.visible == 0

        container.show()

        assert container.visible == 1

        assert container._root_container.visible == 1
        assert container._view_container.visible == 1
        assert container.horiz_scroll_bar.visible == 1
        assert container.vert_scroll_bar.visible == 1
        assert container.scrollable_container.visible == 1
Example #8
0
    def test_kill(self, _init_pygame, default_ui_manager,
                  _display_surface_return_none):
        container = UIScrollingContainer(pygame.Rect(100, 100, 200, 200),
                                         manager=default_ui_manager)
        container_2 = UIScrollingContainer(pygame.Rect(50, 50, 50, 50),
                                           manager=default_ui_manager,
                                           container=container)

        button = UIButton(relative_rect=pygame.Rect(20, 20, 30, 20), text="X",
                          manager=default_ui_manager, container=container_2)

        container.kill()

        assert not button.alive()
        assert not container_2.alive()
        assert not container.alive()
    def test_update(self, _init_pygame, default_ui_manager,
                    _display_surface_return_none):
        container = UIScrollingContainer(pygame.Rect(100, 100, 200, 200),
                                         manager=default_ui_manager)

        container.set_scrollable_area_dimensions((500, 600))

        container.horiz_scroll_bar.scroll_wheel_right = True
        container.horiz_scroll_bar.update(0.02)

        container.update(0.02)

        assert container.get_container().relative_rect.x == -18
 def test_get_container(self, _init_pygame,
                        default_ui_manager: IUIManagerInterface,
                        _display_surface_return_none):
     container = UIScrollingContainer(pygame.Rect(100, 100, 200, 200),
                                      manager=default_ui_manager)
     assert container.get_container() == container.scrollable_container
 def test_creation(self, _init_pygame, default_ui_manager,
                   _display_surface_return_none):
     UIScrollingContainer(relative_rect=pygame.Rect(100, 100, 400, 400),
                          manager=default_ui_manager)
Example #12
0
class GameMode(Mode):

    def on_calcel_build(self):
        tower.towers.remove(self.dragging_tower)
        self.dragging_tower.game_object.mark_to_destroy = True
        self.on_finish_build()


    def on_place_tower(self):
        session_data.player_gold -= self.dragging_tower.definition.cost
        self.on_finish_build()
        self.game_gui_updater.update_stats_gui()


    def on_finish_build(self):
        self.building_panel.hide()
        self.dragging_tower = None
        for t in tower.towers:
            t.change_range_indicators_activity(False)


    def spawn_tower(self, index):
        self.building_panel.show()
        definition = tower.tower_definitions[index]

        tower_object = GameObject(
            get_tile_coords(3, 0),
            (1, 1),
            0
        )

        tower_object.add_component(StaticSprite).init_component(
            pos=(0, 0),
            size=(map.TILE_SIZE, map.TILE_SIZE),
            angle=0,
            image_path=TOWERS_PATH + definition.image + '.png',
            alpha=True
        )

        if definition.range_type == tower.CIRCULAR_RANGE_TYPE:
            tower_object.add_component(Circle).init_component(
                pos=(0, 0),
                radius=map.TILE_SIZE * 2,
                color=(25, 25, 225, 200),
                thickness=1
            )
        else:
            tower_object.add_component(Rectangle).init_component(
                pos=(0, 0),
                w=map.TILE_SIZE,
                h=map.TILE_SIZE,
                color=(25, 25, 225, 200),
                thickness=1
            )
            tower_object.add_component(Rectangle).init_component(
                pos=(0, 0),
                w=map.TILE_SIZE,
                h=map.TILE_SIZE,
                color=(25, 25, 225, 200),
                thickness=1
            )

        tower_object.add_component(Tower).init_component(
            enemies_path_coords=map_settings.settings.enemies_path_coords,
            definition=definition,
            on_build_callback=lambda: self.on_place_tower()
        )

        self.dragging_tower = tower_object.get_components(Tower)[0]


    def start_fall(self):
        self.build_mode_active = False
        self.enemies_spawner.start_spawn()
        self.start_fall_btn.disable()
        for btn in self.tower_build_buttons:
            btn.disable()
        self.game_gui_updater.update_stats_gui()

        self.switch_right_panel(False)
        self.towers_btn.disable()
        self.spells_btn.disable()


    def on_fall_end(self):
        self.build_mode_active = True
        self.start_fall_btn.enable()
        curr_fall = map_settings.settings.falls[self.enemies_spawner.current_fall]
        session_data.player_gold += curr_fall.gold_reward
        self.game_gui_updater.update_stats_gui()

        self.switch_right_panel(True)
        self.towers_btn.enable()
        self.spells_btn.enable()


    def on_map_end(self):
        self.game_gui_updater.update_stats_gui()
        level_end_window = LevelEndWindow(True, self)


    def on_add_damages_to_player(self):
        if session_data.player_hp <= 0 and not self.game_over:
            level_end_window = LevelEndWindow(False, self)
            self.game_over = True


    def on_enemy_destruction(self):
        self.game_gui_updater.update_stats_gui()


    def replay_map(self):
        switch_mode(MODE_GAME, file_name=self.current_map)


    def play_next_map(self):
        """
        Works only for campaign levels named as numbers where number means order of levels.
        """

        only_name = self.current_map.split('.')[0] # remove extension

        if only_name.isnumeric():
            as_num = int(only_name)

            maps = file_utils.get_all_files_in_path(MAPS_PATH)
            for m in maps:
                map_name = m.split('/')[1].split('.')[0]
                if map_name.isnumeric() and int(map_name) == as_num+1:
                    switch_mode(MODE_GAME, file_name=map_name + ".tdmap")
                    return

        # if we're not in campaign, select next level from list
        SaveLoadWindow(
            "maps",
            "Select Map",
            lambda f: switch_mode(MODE_GAME, file_name=f),
            False
        )


    def switch_right_panel(self, switch_to_towers):

        if switch_to_towers:
            self.towers_view_panel.show()
            self.spells_view_panel.hide()
        else:
            self.spells_view_panel.show()
            self.towers_view_panel.hide()

        self.game_gui_updater.update_stats_gui()


    def research_spell(self, index):

        definition = spell.spells_definitions[index]

        session_data.player_gold -= definition.research_cost
        session_data.spells_researched[index] = True

        self.game_gui_updater.update_stats_gui()


    def on_cancel_spell(self):
        self.casting_panel.hide()
        self.casting_spell.game_object.mark_to_destroy = True
        self.casting_spell = None


    def on_cast_spell_end(self):
        session_data.player_mana -= self.casting_spell.definition.use_cost
        self.casting_panel.hide()
        self.game_gui_updater.update_stats_gui()


    def on_cast_spell_start(self, index):
        self.casting_panel.show()

        definition = spell.spells_definitions[index]

        spell_go = GameObject(get_tile_coords(3, 0), (1, 1), 0)

        spell_go.add_component(Circle).init_component(
            pos=(0, 0),
            radius=map.TILE_SIZE * 2,
            color=(225, 25, 25, 200),
            thickness=1
        )

        spell_go.add_component(Spell).init_component(
            enemies_path_coords=map_settings.settings.enemies_path_coords,
            definition=definition,
            game_mode=self
        )

        self.casting_spell = spell_go.get_components(Spell)[0]


    def init_gui(self):
        # top panel
        top_panel = UIPanel(
            pygame.Rect(0, 0, SCREEN_WIDTH, 30),
            starting_layer_height=4,
            manager=ui_manager
        )

        # player's health bar
        self.player_hp_bar = UIPanel(
            relative_rect=pygame.Rect(SCREEN_WIDTH / 2, 5, SCREEN_WIDTH / 2 - 15, 15),
            manager=ui_manager,
            starting_layer_height=5,
            container=top_panel,
            object_id="#player_health_bar"
        )

        self.enemy_fall_bar = UIPanel(
            relative_rect=pygame.Rect(15, 5, SCREEN_WIDTH / 2 - 15, 15),
            manager=ui_manager,
            starting_layer_height=5,
            container=top_panel,
            object_id="#enemies_fall_bar"
        )

        # right panel
        right_panel_w = SCREEN_WIDTH - TILE_SIZE * MAP_W
        right_panel_h = SCREEN_HEIGHT - 30
        right_panel = UIPanel(
            pygame.Rect(TILE_SIZE * MAP_W, 30, right_panel_w, right_panel_h),
            starting_layer_height=4,
            manager=ui_manager
        )

        fall_info_panel = UIPanel(
            relative_rect=pygame.Rect(0, 0, right_panel_w - 5, 120),
            starting_layer_height=4,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=right_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "top"
            }
        )

        self.fall_label = UITextBox(
            "<b>Fall:</b> 0 / 10",
            pygame.Rect(5, 5, 300, 35),
            ui_manager,
            container=fall_info_panel,
            object_id="#no_border_textbox",
        )

        self.fall_reward_label = UITextBox(
            "<b>Reward:</b> 1000 gold coins",
            pygame.Rect(5, 40, 400, 35),
            ui_manager,
            container=fall_info_panel,
            object_id="#no_border_textbox",
        )

        # build panel
        build_panel = UIPanel(
            relative_rect=pygame.Rect(0, 120, right_panel_w - 5, 600),
            starting_layer_height=4,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=right_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            }
        )

        self.gold_label = UITextBox(
            f"<b><font color=#DEAF21>Gold: </font>{session_data.player_gold}</b>, " +
            f"<b><font color=#4488FF>Mana: </font>{session_data.player_mana}</b>",
            pygame.Rect(5, 5, 500, 35),
            ui_manager,
            container=build_panel,
            object_id="#no_border_textbox",
        )

        """
        UITextBox(
            "<b>Towers</b>",
            pygame.Rect(5, 45, 300, 40),
            ui_manager,
            container=build_panel,
            object_id="#no_border_textbox",
        )
        """

        self.towers_btn = UIButton(
                pygame.Rect(5, 45, 145, 30),
                "Towers",
                ui_manager,
                container=build_panel,
        )
        register_ui_callback(self.towers_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.switch_right_panel(True))

        self.spells_btn = UIButton(
                pygame.Rect(155, 45, 145, 30),
                "Spells",
                ui_manager,
                container=build_panel,
        )
        register_ui_callback(self.spells_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.switch_right_panel(False))

        self.towers_view_panel = UIPanel(
            relative_rect=pygame.Rect(5, 80, right_panel_w - 20, 500),
            starting_layer_height=3,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=build_panel
        )

        self.towers_container = UIScrollingContainer(
            pygame.Rect(0, 0, right_panel_w - 30, 500 * Y_RATIO),
            ui_manager,
            container=self.towers_view_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            },
            object_id="#enemy_scrolling_container",
            starting_height=3
        )

        item_height = 200 * Y_RATIO
        self.towers_container.set_scrollable_area_dimensions((right_panel_w - 50, 2 + len(tower.tower_definitions) * item_height + 10 + 10))
        self.tower_build_buttons = []

        for n in range(0, len(tower.tower_definitions)):
            if n+1 > map_settings.settings.max_tower:
                break;

            definition = tower.tower_definitions[n]

            tower_panel = UIPanel(
                relative_rect=pygame.Rect(2, 5 + item_height * n, right_panel_w - 55, item_height),
                starting_layer_height=5,
                manager=ui_manager,
                container=self.towers_container,
                object_id="#tower_panel"
            )

            UITextBox(
                "<b>" + definition.name + "</b>",
                pygame.Rect(5, 5, 340 * X_RATIO, 30 * Y_RATIO),
                ui_manager,
                container=tower_panel,
                object_id="#no_border_textbox",
            )

            tower_stats_panel = UIPanel(
                relative_rect=pygame.Rect(7, 35, right_panel_w - 80, 120 * Y_RATIO),
                starting_layer_height=5,
                manager=ui_manager,
                container=tower_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "top",
                    "bottom": "bottom"
                }
            )

            image_path = TOWERS_PATH + definition.image + ".png"
            image_size = (76 * X_RATIO, 76 * Y_RATIO)
            image_panel = UIPanel(
                relative_rect=pygame.Rect(5, 5, image_size[0], image_size[1]),
                starting_layer_height=5,
                manager=ui_manager,
                container=tower_stats_panel,
            )

            UIImage(
                relative_rect=pygame.Rect(0, -8, image_size[0], image_size[1]),
                image_surface=resource_cache.get_resource(image_path,
                                                          resource_cache.SurfaceType, alpha=True),
                manager=ui_manager,
                container=image_panel
            )

            UITextBox(
                "<font color=#BB0000><b>Damages: </b></font>" + str(definition.damages) +
                "<br><br>"
                "<font color=#9141D1><b>Speed: </b></font>" + str(definition.projectile_speed) +
                "<br><br>" +
                "<font color=#4488FF><b>Reload Time: </b></font>" + str(definition.reload_time) +
                "<br><br>" +
                "<font color=#00FF00><b>Range: </b></font>" + str(definition.range) +
                "<br><br>" +
                "<font color=#DEAF21><b>Cost: </b></font>" + str(definition.cost)
                ,
                pygame.Rect(5 + image_size[0], 0, 160, 140),
                ui_manager,
                container=tower_stats_panel,
                object_id="#no_border_textbox"
            )

            tower_build_btn = UIButton(
                pygame.Rect(8, -34 * Y_RATIO, (right_panel_w - 80) * X_RATIO, 30 * Y_RATIO),
                "Build",
                ui_manager,
                container=tower_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "bottom",
                    "bottom": "bottom"
                }
            )
            self.tower_build_buttons.append(tower_build_btn)
            register_ui_callback(tower_build_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e, i=n: self.spawn_tower(i))


        # spells

        self.spells_view_panel = UIPanel(
            relative_rect=pygame.Rect(5, 80, right_panel_w - 20, 500),
            starting_layer_height=3,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=build_panel
        )

        spells_container = UIScrollingContainer(
            pygame.Rect(0, 0, right_panel_w - 30, 500 * Y_RATIO),
            ui_manager,
            container=self.spells_view_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            },
            object_id="#enemy_scrolling_container",
            starting_height=3
        )

        item_height = 320 * Y_RATIO
        spells_container.set_scrollable_area_dimensions(
            (right_panel_w - 50, 2 + len(spell.spells_definitions) * item_height + 10 + 10)
        )
        self.spell_research_buttons = []
        self.spell_use_buttons = []

        for n in range(0, len(spell.spells_definitions)):
            if n+1 > map_settings.settings.max_spell:
                break;

            definition = spell.spells_definitions[n]

            spell_panel = UIPanel(
                relative_rect=pygame.Rect(2, 5 + item_height * n, right_panel_w - 55, item_height),
                starting_layer_height=5,
                manager=ui_manager,
                container=spells_container,
                object_id="#tower_panel"
            )

            UITextBox(
                "<b>" + definition.name + "</b>",
                pygame.Rect(5, 5, 340 * X_RATIO, 30 * Y_RATIO),
                ui_manager,
                container=spell_panel,
                object_id="#no_border_textbox",
            )

            spell_stats_panel = UIPanel(
                relative_rect=pygame.Rect(7, 35, right_panel_w - 80, 240 * Y_RATIO),
                starting_layer_height=5,
                manager=ui_manager,
                container=spell_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "top",
                    "bottom": "bottom"
                }
            )

            image_path = EFFECTS_PATH + definition.icon_image + ".png"
            image_size = (76 * X_RATIO, 76 * Y_RATIO)
            image_panel = UIPanel(
                relative_rect=pygame.Rect((right_panel_w - 80) * 0.5 - image_size[0] * 0.5, 5, image_size[0], image_size[1]),
                starting_layer_height=5,
                manager=ui_manager,
                container=spell_stats_panel,
            )

            UIImage(
                relative_rect=pygame.Rect(0, -8, image_size[0], image_size[1]),
                image_surface=resource_cache.get_resource(image_path,
                                                          resource_cache.SurfaceType, alpha=True),
                manager=ui_manager,
                container=image_panel
            )

            UITextBox(
                spell.make_description(definition),
                pygame.Rect(5, 5 + image_size[1], right_panel_w - 80, item_height - image_size[1]),
                ui_manager,
                container=spell_stats_panel,
                object_id="#no_border_textbox"
            )

            spell_research_btn = UIButton(
                pygame.Rect(8, -34 * Y_RATIO, (right_panel_w - 200) * X_RATIO, 30 * Y_RATIO),
                "Research",
                ui_manager,
                container=spell_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "bottom",
                    "bottom": "bottom"
                }
            )
            self.spell_research_buttons.append(spell_research_btn)
            register_ui_callback(spell_research_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e, i=n: self.research_spell(i))

            spell_use_btn = UIButton(
                pygame.Rect(8 + (right_panel_w - 200) * X_RATIO, -34 * Y_RATIO, (right_panel_w - 200) * X_RATIO, 30 * Y_RATIO),
                "Use",
                ui_manager,
                container=spell_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "bottom",
                    "bottom": "bottom"
                }
            )
            self.spell_use_buttons.append(spell_use_btn)
            register_ui_callback(spell_use_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e, i=n: self.on_cast_spell_start(i))

        # bottom buttons section

        buttons_panel = UIPanel(
            relative_rect=pygame.Rect(0, -140 * Y_RATIO, right_panel_w - 5, 140 * Y_RATIO),
            starting_layer_height=100,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=right_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "bottom",
                "bottom": "bottom"
            }
        )

        # start fall button
        self.start_fall_btn = UIButton(
            pygame.Rect(20, -120 * Y_RATIO, right_panel_w * 0.8, 40 * Y_RATIO),
            "Start Fall",
            ui_manager,
            container=buttons_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "bottom",
                "bottom": "bottom"
            }
        )
        register_ui_callback(self.start_fall_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.start_fall())

        # back button
        self.back_btn = UIButton(
            pygame.Rect(20, -60 * Y_RATIO, right_panel_w * 0.8, 40 * Y_RATIO),
            "Back To Menu",
            ui_manager,
            container=buttons_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "bottom",
                "bottom": "bottom"
            }
        )
        register_ui_callback(self.back_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: switch_mode(MODE_MENU))


        # building
        self.building_panel = UIPanel(
            pygame.Rect(TILE_SIZE * MAP_W, 30, right_panel_w, right_panel_h),
            starting_layer_height=200,
            manager=ui_manager
        )

        UITextBox(
            "<font size=5><b>Place Tower On Map</b></font>",
            pygame.Rect(right_panel_w/6, right_panel_h/4, right_panel_w, 40),
            ui_manager,
            container=self.building_panel,
            object_id="#no_border_textbox"
        )

        cancel_btn = UIButton(
            pygame.Rect(80, (right_panel_h/4)+50, right_panel_w * 0.5, 40),
            "Cancel",
            ui_manager,
            container=self.building_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            }
        )
        register_ui_callback(cancel_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.on_calcel_build())

        self.building_panel.hide()

        # casting spell
        self.casting_panel = UIPanel(
            pygame.Rect(TILE_SIZE * MAP_W, 30, right_panel_w, right_panel_h),
            starting_layer_height=200,
            manager=ui_manager
        )

        UITextBox(
            "<font size=5><b>Click On Path To Cast Spell</b></font>",
            pygame.Rect(5, right_panel_h / 4, right_panel_w, 40),
            ui_manager,
            container=self.casting_panel,
            object_id="#no_border_textbox"
        )

        cancel_btn = UIButton(
            pygame.Rect(80, (right_panel_h / 4) + 50, right_panel_w * 0.5, 40),
            "Cancel",
            ui_manager,
            container=self.casting_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            }
        )
        register_ui_callback(cancel_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.on_cancel_spell())

        self.casting_panel.hide()


    def init_mode(self, **kwargs):

        session_data.player_hp = 100.0
        # session_data.player_mana = 1000
        session_data.enemies_in_level = 0

        tower.towers = []
        enemy.enemies = []
        session_data.spells_researched = [False] * len(spell.spells_definitions)

        self.build_mode_active = True

        map.create_map()
        self.current_map = kwargs.get("file_name")
        map.load_map(self.current_map)

        self.init_gui()

        enemies_spawner_gameobject = GameObject((0, 0), (0, 0), 0)
        enemies_spawner_gameobject.add_component(EnemiesSpawner).init_component(
            game_mode=self
        )
        self.enemies_spawner = enemies_spawner_gameobject.get_components(EnemiesSpawner)[0]

        game_gui_updater_go = GameObject((0, 0), (1, 1), 0)
        game_gui_updater_go.add_component(GameGUIUpdater).init_component(
            fall_label=self.fall_label,
            fall_reward_label=self.fall_reward_label,
            gold_label=self.gold_label,
            tower_build_buttons=self.tower_build_buttons,
            spell_research_buttons=self.spell_research_buttons,
            spell_use_buttons=self.spell_use_buttons,
            enemies_spawner=self.enemies_spawner,
            player_hp_bar=self.player_hp_bar,
            enemies_fall_bar=self.enemy_fall_bar,
            game_mode=self
        )
        self.game_gui_updater = game_gui_updater_go.get_components(GameGUIUpdater)[0]
        self.game_gui_updater.update_stats_gui()

        self.dragging_tower = None
        self.casting_spell = None

        # test effect
        """
        effect_go = GameObject((100, 100), (1, 1), 0)
        effect_go.add_component(DynamicSprite).init_component(
            pos=(0, 0),
            size=(256, 256),
            angle=0,
            images_paths=file_utils.get_all_files_in_path("sources\images\effects\explosion"),
            alpha=True,
            speed=0.3
        )
        """

        self.switch_right_panel(True)

        self.game_over = False


    def deinit_mode(self):
        pass
Example #13
0
    def init_gui(self):
        # top panel
        top_panel = UIPanel(
            pygame.Rect(0, 0, SCREEN_WIDTH, 30),
            starting_layer_height=4,
            manager=ui_manager
        )

        # player's health bar
        self.player_hp_bar = UIPanel(
            relative_rect=pygame.Rect(SCREEN_WIDTH / 2, 5, SCREEN_WIDTH / 2 - 15, 15),
            manager=ui_manager,
            starting_layer_height=5,
            container=top_panel,
            object_id="#player_health_bar"
        )

        self.enemy_fall_bar = UIPanel(
            relative_rect=pygame.Rect(15, 5, SCREEN_WIDTH / 2 - 15, 15),
            manager=ui_manager,
            starting_layer_height=5,
            container=top_panel,
            object_id="#enemies_fall_bar"
        )

        # right panel
        right_panel_w = SCREEN_WIDTH - TILE_SIZE * MAP_W
        right_panel_h = SCREEN_HEIGHT - 30
        right_panel = UIPanel(
            pygame.Rect(TILE_SIZE * MAP_W, 30, right_panel_w, right_panel_h),
            starting_layer_height=4,
            manager=ui_manager
        )

        fall_info_panel = UIPanel(
            relative_rect=pygame.Rect(0, 0, right_panel_w - 5, 120),
            starting_layer_height=4,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=right_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "top"
            }
        )

        self.fall_label = UITextBox(
            "<b>Fall:</b> 0 / 10",
            pygame.Rect(5, 5, 300, 35),
            ui_manager,
            container=fall_info_panel,
            object_id="#no_border_textbox",
        )

        self.fall_reward_label = UITextBox(
            "<b>Reward:</b> 1000 gold coins",
            pygame.Rect(5, 40, 400, 35),
            ui_manager,
            container=fall_info_panel,
            object_id="#no_border_textbox",
        )

        # build panel
        build_panel = UIPanel(
            relative_rect=pygame.Rect(0, 120, right_panel_w - 5, 600),
            starting_layer_height=4,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=right_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            }
        )

        self.gold_label = UITextBox(
            f"<b><font color=#DEAF21>Gold: </font>{session_data.player_gold}</b>, " +
            f"<b><font color=#4488FF>Mana: </font>{session_data.player_mana}</b>",
            pygame.Rect(5, 5, 500, 35),
            ui_manager,
            container=build_panel,
            object_id="#no_border_textbox",
        )

        """
        UITextBox(
            "<b>Towers</b>",
            pygame.Rect(5, 45, 300, 40),
            ui_manager,
            container=build_panel,
            object_id="#no_border_textbox",
        )
        """

        self.towers_btn = UIButton(
                pygame.Rect(5, 45, 145, 30),
                "Towers",
                ui_manager,
                container=build_panel,
        )
        register_ui_callback(self.towers_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.switch_right_panel(True))

        self.spells_btn = UIButton(
                pygame.Rect(155, 45, 145, 30),
                "Spells",
                ui_manager,
                container=build_panel,
        )
        register_ui_callback(self.spells_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.switch_right_panel(False))

        self.towers_view_panel = UIPanel(
            relative_rect=pygame.Rect(5, 80, right_panel_w - 20, 500),
            starting_layer_height=3,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=build_panel
        )

        self.towers_container = UIScrollingContainer(
            pygame.Rect(0, 0, right_panel_w - 30, 500 * Y_RATIO),
            ui_manager,
            container=self.towers_view_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            },
            object_id="#enemy_scrolling_container",
            starting_height=3
        )

        item_height = 200 * Y_RATIO
        self.towers_container.set_scrollable_area_dimensions((right_panel_w - 50, 2 + len(tower.tower_definitions) * item_height + 10 + 10))
        self.tower_build_buttons = []

        for n in range(0, len(tower.tower_definitions)):
            if n+1 > map_settings.settings.max_tower:
                break;

            definition = tower.tower_definitions[n]

            tower_panel = UIPanel(
                relative_rect=pygame.Rect(2, 5 + item_height * n, right_panel_w - 55, item_height),
                starting_layer_height=5,
                manager=ui_manager,
                container=self.towers_container,
                object_id="#tower_panel"
            )

            UITextBox(
                "<b>" + definition.name + "</b>",
                pygame.Rect(5, 5, 340 * X_RATIO, 30 * Y_RATIO),
                ui_manager,
                container=tower_panel,
                object_id="#no_border_textbox",
            )

            tower_stats_panel = UIPanel(
                relative_rect=pygame.Rect(7, 35, right_panel_w - 80, 120 * Y_RATIO),
                starting_layer_height=5,
                manager=ui_manager,
                container=tower_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "top",
                    "bottom": "bottom"
                }
            )

            image_path = TOWERS_PATH + definition.image + ".png"
            image_size = (76 * X_RATIO, 76 * Y_RATIO)
            image_panel = UIPanel(
                relative_rect=pygame.Rect(5, 5, image_size[0], image_size[1]),
                starting_layer_height=5,
                manager=ui_manager,
                container=tower_stats_panel,
            )

            UIImage(
                relative_rect=pygame.Rect(0, -8, image_size[0], image_size[1]),
                image_surface=resource_cache.get_resource(image_path,
                                                          resource_cache.SurfaceType, alpha=True),
                manager=ui_manager,
                container=image_panel
            )

            UITextBox(
                "<font color=#BB0000><b>Damages: </b></font>" + str(definition.damages) +
                "<br><br>"
                "<font color=#9141D1><b>Speed: </b></font>" + str(definition.projectile_speed) +
                "<br><br>" +
                "<font color=#4488FF><b>Reload Time: </b></font>" + str(definition.reload_time) +
                "<br><br>" +
                "<font color=#00FF00><b>Range: </b></font>" + str(definition.range) +
                "<br><br>" +
                "<font color=#DEAF21><b>Cost: </b></font>" + str(definition.cost)
                ,
                pygame.Rect(5 + image_size[0], 0, 160, 140),
                ui_manager,
                container=tower_stats_panel,
                object_id="#no_border_textbox"
            )

            tower_build_btn = UIButton(
                pygame.Rect(8, -34 * Y_RATIO, (right_panel_w - 80) * X_RATIO, 30 * Y_RATIO),
                "Build",
                ui_manager,
                container=tower_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "bottom",
                    "bottom": "bottom"
                }
            )
            self.tower_build_buttons.append(tower_build_btn)
            register_ui_callback(tower_build_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e, i=n: self.spawn_tower(i))


        # spells

        self.spells_view_panel = UIPanel(
            relative_rect=pygame.Rect(5, 80, right_panel_w - 20, 500),
            starting_layer_height=3,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=build_panel
        )

        spells_container = UIScrollingContainer(
            pygame.Rect(0, 0, right_panel_w - 30, 500 * Y_RATIO),
            ui_manager,
            container=self.spells_view_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            },
            object_id="#enemy_scrolling_container",
            starting_height=3
        )

        item_height = 320 * Y_RATIO
        spells_container.set_scrollable_area_dimensions(
            (right_panel_w - 50, 2 + len(spell.spells_definitions) * item_height + 10 + 10)
        )
        self.spell_research_buttons = []
        self.spell_use_buttons = []

        for n in range(0, len(spell.spells_definitions)):
            if n+1 > map_settings.settings.max_spell:
                break;

            definition = spell.spells_definitions[n]

            spell_panel = UIPanel(
                relative_rect=pygame.Rect(2, 5 + item_height * n, right_panel_w - 55, item_height),
                starting_layer_height=5,
                manager=ui_manager,
                container=spells_container,
                object_id="#tower_panel"
            )

            UITextBox(
                "<b>" + definition.name + "</b>",
                pygame.Rect(5, 5, 340 * X_RATIO, 30 * Y_RATIO),
                ui_manager,
                container=spell_panel,
                object_id="#no_border_textbox",
            )

            spell_stats_panel = UIPanel(
                relative_rect=pygame.Rect(7, 35, right_panel_w - 80, 240 * Y_RATIO),
                starting_layer_height=5,
                manager=ui_manager,
                container=spell_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "top",
                    "bottom": "bottom"
                }
            )

            image_path = EFFECTS_PATH + definition.icon_image + ".png"
            image_size = (76 * X_RATIO, 76 * Y_RATIO)
            image_panel = UIPanel(
                relative_rect=pygame.Rect((right_panel_w - 80) * 0.5 - image_size[0] * 0.5, 5, image_size[0], image_size[1]),
                starting_layer_height=5,
                manager=ui_manager,
                container=spell_stats_panel,
            )

            UIImage(
                relative_rect=pygame.Rect(0, -8, image_size[0], image_size[1]),
                image_surface=resource_cache.get_resource(image_path,
                                                          resource_cache.SurfaceType, alpha=True),
                manager=ui_manager,
                container=image_panel
            )

            UITextBox(
                spell.make_description(definition),
                pygame.Rect(5, 5 + image_size[1], right_panel_w - 80, item_height - image_size[1]),
                ui_manager,
                container=spell_stats_panel,
                object_id="#no_border_textbox"
            )

            spell_research_btn = UIButton(
                pygame.Rect(8, -34 * Y_RATIO, (right_panel_w - 200) * X_RATIO, 30 * Y_RATIO),
                "Research",
                ui_manager,
                container=spell_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "bottom",
                    "bottom": "bottom"
                }
            )
            self.spell_research_buttons.append(spell_research_btn)
            register_ui_callback(spell_research_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e, i=n: self.research_spell(i))

            spell_use_btn = UIButton(
                pygame.Rect(8 + (right_panel_w - 200) * X_RATIO, -34 * Y_RATIO, (right_panel_w - 200) * X_RATIO, 30 * Y_RATIO),
                "Use",
                ui_manager,
                container=spell_panel,
                anchors={
                    "left": "left",
                    "right": "right",
                    "top": "bottom",
                    "bottom": "bottom"
                }
            )
            self.spell_use_buttons.append(spell_use_btn)
            register_ui_callback(spell_use_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e, i=n: self.on_cast_spell_start(i))

        # bottom buttons section

        buttons_panel = UIPanel(
            relative_rect=pygame.Rect(0, -140 * Y_RATIO, right_panel_w - 5, 140 * Y_RATIO),
            starting_layer_height=100,
            object_id="#thicker_panel",
            manager=ui_manager,
            container=right_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "bottom",
                "bottom": "bottom"
            }
        )

        # start fall button
        self.start_fall_btn = UIButton(
            pygame.Rect(20, -120 * Y_RATIO, right_panel_w * 0.8, 40 * Y_RATIO),
            "Start Fall",
            ui_manager,
            container=buttons_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "bottom",
                "bottom": "bottom"
            }
        )
        register_ui_callback(self.start_fall_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.start_fall())

        # back button
        self.back_btn = UIButton(
            pygame.Rect(20, -60 * Y_RATIO, right_panel_w * 0.8, 40 * Y_RATIO),
            "Back To Menu",
            ui_manager,
            container=buttons_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "bottom",
                "bottom": "bottom"
            }
        )
        register_ui_callback(self.back_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: switch_mode(MODE_MENU))


        # building
        self.building_panel = UIPanel(
            pygame.Rect(TILE_SIZE * MAP_W, 30, right_panel_w, right_panel_h),
            starting_layer_height=200,
            manager=ui_manager
        )

        UITextBox(
            "<font size=5><b>Place Tower On Map</b></font>",
            pygame.Rect(right_panel_w/6, right_panel_h/4, right_panel_w, 40),
            ui_manager,
            container=self.building_panel,
            object_id="#no_border_textbox"
        )

        cancel_btn = UIButton(
            pygame.Rect(80, (right_panel_h/4)+50, right_panel_w * 0.5, 40),
            "Cancel",
            ui_manager,
            container=self.building_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            }
        )
        register_ui_callback(cancel_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.on_calcel_build())

        self.building_panel.hide()

        # casting spell
        self.casting_panel = UIPanel(
            pygame.Rect(TILE_SIZE * MAP_W, 30, right_panel_w, right_panel_h),
            starting_layer_height=200,
            manager=ui_manager
        )

        UITextBox(
            "<font size=5><b>Click On Path To Cast Spell</b></font>",
            pygame.Rect(5, right_panel_h / 4, right_panel_w, 40),
            ui_manager,
            container=self.casting_panel,
            object_id="#no_border_textbox"
        )

        cancel_btn = UIButton(
            pygame.Rect(80, (right_panel_h / 4) + 50, right_panel_w * 0.5, 40),
            "Cancel",
            ui_manager,
            container=self.casting_panel,
            anchors={
                "left": "left",
                "right": "right",
                "top": "top",
                "bottom": "bottom"
            }
        )
        register_ui_callback(cancel_btn, pygame_gui.UI_BUTTON_PRESSED, lambda e: self.on_cancel_spell())

        self.casting_panel.hide()
class MapSettingsWindow(UIWindow):
    def on_fall_add_btn_click(self):
        map_settings.settings.falls.append(
            EnemiesFall([
                EnemiesGroup([0] * len(enemy.enemies_definitions), 1.0,
                             [0.5, 1.0])
            ], 100))
        self.current_selected_group = 0
        self.update_settings()

    def on_fall_remove_btn_click(self):
        if len(map_settings.settings.falls) > 1:
            map_settings.settings.falls.remove(
                map_settings.settings.falls[self.current_selected_fall])
            self.current_selected_fall = 0
            self.current_selected_group = 0
            self.update_settings()

    def on_fall_list_item_select(self):
        for i in range(0, len(self.falls_ui_list.item_list)):
            if self.falls_ui_list.item_list[i]['selected']:
                self.current_selected_fall = i
                self.current_selected_group = 0
                self.update_groups_list()
                self.update_fall_panel()
                return

    def on_group_add_btn_click(self):
        map_settings.settings.falls[self.current_selected_fall].groups.append(
            EnemiesGroup([0] * len(enemy.enemies_definitions), 1.0,
                         [0.5, 1.0]))
        self.update_groups_list()
        self.update_group_panel()
        self.update_enemies_panel()

    def on_group_remove_btn_click(self):
        curr_fall = map_settings.settings.falls[self.current_selected_fall]
        if len(curr_fall.groups) > 1:
            curr_fall.groups.remove(
                curr_fall.groups[self.current_selected_group])
        self.current_selected_group = 0
        self.update_groups_list()

    def on_fall_gold_text_changed(self, e):
        if len(map_settings.settings.falls) > 0:
            if len(e.text) > 0 and e.text.isnumeric():
                map_settings.settings.falls[
                    self.current_selected_fall].gold_reward = int(e.text)
            else:
                map_settings.settings.falls[
                    self.current_selected_fall].gold_reward = 0
                self.update_fall_panel()

    def on_start_gold_text_changed(self, e):
        if len(e.text) > 0 and e.text.isnumeric():
            map_settings.settings.start_gold = int(e.text)
        else:
            map_settings.settings.start_gold = 0
            self.update_general_panel()

    def on_start_mana_text_changed(self, e):
        if len(e.text) > 0 and e.text.isnumeric():
            map_settings.settings.start_mana = int(e.text)
        else:
            map_settings.settings.start_mana = 0
            self.update_general_panel()

    def on_group_list_item_select(self, e):
        for i in range(0, len(self.groups_ui_list.item_list)):
            if self.groups_ui_list.item_list[i]['selected']:
                self.current_selected_group = i
                self.update_group_panel()
                self.update_enemies_panel()
                return

    def on_group_spawn_delay_changed(self, e):
        if len(map_settings.settings.falls) > 0:
            if len(map_settings.settings.falls[
                    self.current_selected_fall].groups) > 0:
                curr_group = map_settings.settings.falls[
                    self.current_selected_fall].groups[
                        self.current_selected_group]
                if len(e.text) > 0 and utils.is_float(e.text):
                    curr_group.spawn_delay = float(e.text)
                else:
                    curr_group.spawn_delay = 0.0
                    self.update_group_panel()

    def on_group_spawn_interval_left_changed(self, e):
        if len(map_settings.settings.falls) > 0:
            if len(map_settings.settings.falls[
                    self.current_selected_fall].groups) > 0:
                curr_group = map_settings.settings.falls[
                    self.current_selected_fall].groups[
                        self.current_selected_group]
                if len(e.text) > 0 and utils.is_float(e.text):
                    curr_group.interval[0] = float(e.text)
                else:
                    curr_group.interval[0] = 0.0
                    self.update_group_panel()

    def on_group_spawn_interval_right_changed(self, e):
        if len(map_settings.settings.falls) > 0:
            if len(map_settings.settings.falls[
                    self.current_selected_fall].groups) > 0:
                curr_group = map_settings.settings.falls[
                    self.current_selected_fall].groups[
                        self.current_selected_group]
                if len(e.text) > 0 and utils.is_float(e.text):
                    curr_group.interval[1] = float(e.text)
                else:
                    curr_group.interval[1] = 0.0
                    self.update_group_panel()

    def on_change_enemy_count(self, e, i):
        if len(map_settings.settings.falls) > 0:
            if len(map_settings.settings.falls[
                    self.current_selected_fall].groups) > 0:
                curr_group = map_settings.settings.falls[
                    self.current_selected_fall].groups[
                        self.current_selected_group]
                if len(e.text) > 0 and e.text.isnumeric():
                    curr_group.enemies_counts[i] = int(e.text)
                else:
                    curr_group.enemies_counts[i] = 0
                    self.update_enemies_panel()

    def on_max_tower_text_changed(self, e):
        if len(e.text) > 0 and e.text.isnumeric():
            map_settings.settings.max_tower = math_utils.clamp(
                int(e.text), 0, len(tower.tower_definitions))
        else:
            map_settings.settings.max_tower = len(tower.tower_definitions)
            self.update_general_panel()

    def on_max_spell_text_changed(self, e):
        if len(e.text) > 0 and e.text.isnumeric():
            map_settings.settings.max_spell = math_utils.clamp(
                int(e.text), 0, len(spell.spells_definitions))
        else:
            map_settings.settings.max_spell = len(spell.spells_definitions)
            self.update_general_panel()

    def __init__(self):
        windowWidth = 1340
        windowHeight = 600
        super().__init__(pygame.Rect(
            SCREEN_WIDTH * 0.5 - windowWidth * 0.5,
            SCREEN_HEIGHT * 0.5 - windowHeight * 0.5,
            windowWidth,
            windowHeight,
        ),
                         ui_manager,
                         window_display_title="Settings",
                         resizable=False)

        UILabel(pygame.Rect(0, 0, 80, 30),
                "General",
                ui_manager,
                container=self)

        general_panel = UIPanel(pygame.Rect(10, 30, 250, 600 - 100),
                                starting_layer_height=4,
                                manager=ui_manager,
                                container=self,
                                object_id="#thicker_panel")
        UILabel(pygame.Rect(10, 10, 80, 30),
                "Start Gold",
                ui_manager,
                container=general_panel)

        self.start_gold_text_line = UITextEntryLine(
            pygame.Rect(100, 10, 60, 20),
            manager=ui_manager,
            container=general_panel,
            #object_id='#file_path_text_line',
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'bottom'
            })

        register_ui_callback(self.start_gold_text_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_start_gold_text_changed(e))

        UILabel(pygame.Rect(10, 40, 80, 30),
                "Start Mana",
                ui_manager,
                container=general_panel)
        self.start_mana_text_line = UITextEntryLine(
            pygame.Rect(100, 40, 60, 20),
            manager=ui_manager,
            container=general_panel,
            #object_id='#file_path_text_line',
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'bottom'
            })

        register_ui_callback(self.start_mana_text_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_start_mana_text_changed(e))

        UILabel(pygame.Rect(10, 70, 80, 30),
                "Max Tower",
                ui_manager,
                container=general_panel)

        self.max_tower_text_line = UITextEntryLine(
            pygame.Rect(100, 70, 60, 20),
            manager=ui_manager,
            container=general_panel,
            #object_id='#file_path_text_line',
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'bottom'
            })

        register_ui_callback(self.max_tower_text_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_max_tower_text_changed(e))

        UILabel(pygame.Rect(10, 100, 80, 30),
                "Max Spell",
                ui_manager,
                container=general_panel)

        self.max_spell_text_line = UITextEntryLine(
            pygame.Rect(100, 100, 60, 20),
            manager=ui_manager,
            container=general_panel,
            #object_id='#file_path_text_line',
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'bottom'
            })

        register_ui_callback(self.max_spell_text_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_max_spell_text_changed(e))

        # ---------------------------- falls

        UILabel(pygame.Rect(250, 0, 80, 30),
                "Falls",
                ui_manager,
                container=self)

        self.falls_list = ["Dummy", "Dummy"]
        self.current_selected_fall = 0
        self.falls_ui_list = UISelectionList(
            pygame.Rect(270, 30, 250, 220),
            item_list=self.falls_list,
            manager=ui_manager,
            container=self,
            object_id="#thicker_panel",
        )

        register_ui_callback(self.falls_ui_list,
                             pygame_gui.UI_SELECTION_LIST_NEW_SELECTION,
                             lambda e: self.on_fall_list_item_select())

        self.fall_add_btn = UIButton(pygame.Rect(270, 250, 125, 30),
                                     "Add Fall",
                                     ui_manager,
                                     container=self)
        self.fall_remove_btn = UIButton(pygame.Rect(395, 250, 125, 30),
                                        "Remove Fall",
                                        ui_manager,
                                        container=self)

        register_ui_callback(self.fall_add_btn, pygame_gui.UI_BUTTON_PRESSED,
                             lambda e: self.on_fall_add_btn_click())
        register_ui_callback(self.fall_remove_btn,
                             pygame_gui.UI_BUTTON_PRESSED,
                             lambda e: self.on_fall_remove_btn_click())

        UILabel(pygame.Rect(262, 290, 120, 30),
                "Fall Settings",
                ui_manager,
                container=self)

        self.fall_settings_panel = UIPanel(pygame.Rect(270, 320, 250, 210),
                                           starting_layer_height=4,
                                           object_id="#thicker_panel",
                                           manager=ui_manager,
                                           container=self)

        # gold reward

        UILabel(pygame.Rect(5, 10, 100, 30),
                "Gold Reward",
                ui_manager,
                container=self.fall_settings_panel)

        self.fall_gold_reward = UITextEntryLine(
            pygame.Rect(105, 10, 60, 20),
            manager=ui_manager,
            container=self.fall_settings_panel,
        )

        register_ui_callback(self.fall_gold_reward,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_fall_gold_text_changed(e))

        # ---------------------------- groups

        UILabel(pygame.Rect(515, 0, 80, 30),
                "Groups",
                ui_manager,
                container=self)

        self.groups_list = []
        self.current_selected_group = 0
        self.groups_ui_list = UISelectionList(
            pygame.Rect(530, 30, 380, 220),
            item_list=self.groups_list,
            manager=ui_manager,
            container=self,
            object_id="#thicker_panel",
        )

        register_ui_callback(self.groups_ui_list,
                             pygame_gui.UI_SELECTION_LIST_NEW_SELECTION,
                             lambda e: self.on_group_list_item_select(e))

        self.group_add_btn = UIButton(pygame.Rect(530, 250, 380 * 0.5, 30),
                                      "Add Group",
                                      ui_manager,
                                      container=self)
        self.group_remove_btn = UIButton(pygame.Rect(530 + 380 * 0.5, 250,
                                                     380 * 0.5, 30),
                                         "Remove Group",
                                         ui_manager,
                                         container=self)

        register_ui_callback(self.group_add_btn, pygame_gui.UI_BUTTON_PRESSED,
                             lambda e: self.on_group_add_btn_click())
        register_ui_callback(self.group_remove_btn,
                             pygame_gui.UI_BUTTON_PRESSED,
                             lambda e: self.on_group_remove_btn_click())

        UILabel(pygame.Rect(530, 290, 120, 30),
                "Group Settings",
                ui_manager,
                container=self)

        group_settings_panel = UIPanel(pygame.Rect(530, 320, 380, 210),
                                       starting_layer_height=4,
                                       object_id="#thicker_panel",
                                       manager=ui_manager,
                                       container=self)

        UILabel(pygame.Rect(5, 10, 100, 30),
                "Spawn After",
                ui_manager,
                container=group_settings_panel)

        self.group_spawn_mode_dropdown = UIDropDownMenu(
            ["End Of Previous Group Spawn", "Previous Group Destruction"],
            "End Of Previous Group Spawn",
            pygame.Rect(105, 15, 250, 20),
            ui_manager,
            container=group_settings_panel)

        # spawn delay

        UILabel(pygame.Rect(5, 45, 100, 30),
                "Spawn Delay",
                ui_manager,
                container=group_settings_panel)
        self.spawn_delay_entry_line = UITextEntryLine(
            pygame.Rect(105, 45, 40, 20),
            manager=ui_manager,
            container=group_settings_panel)
        UILabel(pygame.Rect(150, 45, 60, 30),
                "seconds",
                ui_manager,
                container=group_settings_panel)

        register_ui_callback(self.spawn_delay_entry_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_group_spawn_delay_changed(e))

        # interval

        UILabel(pygame.Rect(-2, 80, 100, 30),
                "Interval:",
                ui_manager,
                container=group_settings_panel)
        UILabel(pygame.Rect(2, 115, 50, 30),
                "From",
                ui_manager,
                container=group_settings_panel)
        self.interval_from_entry_line = UITextEntryLine(
            pygame.Rect(50, 115, 40, 20),
            manager=ui_manager,
            container=group_settings_panel)
        UILabel(pygame.Rect(95, 115, 20, 30),
                "To",
                ui_manager,
                container=group_settings_panel)
        self.interval_to_entry_line = UITextEntryLine(
            pygame.Rect(120, 115, 40, 20),
            manager=ui_manager,
            container=group_settings_panel)
        UILabel(pygame.Rect(165, 115, 60, 30),
                "seconds",
                ui_manager,
                container=group_settings_panel)

        register_ui_callback(
            self.interval_from_entry_line, pygame_gui.UI_TEXT_ENTRY_CHANGED,
            lambda e: self.on_group_spawn_interval_left_changed(e))

        register_ui_callback(
            self.interval_to_entry_line, pygame_gui.UI_TEXT_ENTRY_CHANGED,
            lambda e: self.on_group_spawn_interval_right_changed(e))

        # ---------------------------- enemies

        self.enemies_label = UILabel(pygame.Rect(910, 0, 80, 30),
                                     "Enemies",
                                     ui_manager,
                                     container=self)

        self.enemies_view_panel = UIPanel(relative_rect=pygame.Rect(
            920, 30, 385, 505),
                                          starting_layer_height=4,
                                          object_id="#thicker_panel",
                                          manager=ui_manager,
                                          container=self)
        #self.enemies_view_panel.hide()
        #self.enemies_label.hide()

        #250, 600 - 100
        self.enemy_container = UIScrollingContainer(
            pygame.Rect(0, 0, 380, 500),
            ui_manager,
            container=self.enemies_view_panel,
            object_id="#enemy_scrolling_container",
            starting_height=4)

        item_height = 165
        self.enemy_container.set_scrollable_area_dimensions(
            (360, 5 + len(enemy.enemies_definitions) * item_height + 10))
        """
        for n in range(0, 24):
            UIButton(
                pygame.Rect(5, 5 + 50 * n, 370, 45),
                "hi",
                ui_manager,
                self.enemy_container
            )
        """

        self.enemies_counts_entry_lines = []
        for n in range(0, len(enemy.enemies_definitions)):
            enemy_panel = UIPanel(relative_rect=pygame.Rect(
                5, 5 + item_height * n, 350, item_height),
                                  starting_layer_height=4,
                                  manager=ui_manager,
                                  container=self.enemy_container,
                                  object_id="#thicker_panel")
            enemy_stats_panel = UIPanel(relative_rect=pygame.Rect(
                10, 35, 325, 80),
                                        starting_layer_height=4,
                                        manager=ui_manager,
                                        container=enemy_panel)

            UITextBox(
                "<b>" + enemy.enemies_definitions[n].name + "</b>",
                pygame.Rect(5, 5, 340, 30),
                ui_manager,
                container=enemy_panel,
                object_id="#no_border_textbox",
            )
            definition = enemy.enemies_definitions[n]
            preview_sprite_path = ENEMIES_PATH + definition.sprites_directory + "/" + definition.preview_sprite + ".png"
            image_size = (720 * 0.15, 480 * 0.15)
            UIImage(relative_rect=pygame.Rect(5, 5, image_size[0],
                                              image_size[1]),
                    image_surface=resource_cache.get_resource(
                        preview_sprite_path,
                        resource_cache.SurfaceType,
                        alpha=True),
                    manager=ui_manager,
                    container=enemy_stats_panel)
            UITextBox("<font color=#00FF00><b>Health: </b></font>" +
                      str(definition.health) + "<br><br>"
                      "<font color=#BB0000><b>Damage: </b></font>" +
                      str(definition.damages) + "</br></br>" +
                      "<font color=#4488FF><b>Speed: </b></font>" +
                      str(definition.speed),
                      pygame.Rect(5 + image_size[0] + 5, 5, 120, 140),
                      ui_manager,
                      container=enemy_stats_panel,
                      object_id="#no_border_textbox")
            UITextBox("Count: ",
                      pygame.Rect(5, item_height - 45, 80, 30),
                      ui_manager,
                      container=enemy_panel,
                      object_id="#no_border_textbox")
            self.enemies_counts_entry_lines.append(
                UITextEntryLine(
                    pygame.Rect(65, item_height - 45, 50, 25),
                    manager=ui_manager,
                    container=enemy_panel,
                ))

            register_ui_callback(
                self.enemies_counts_entry_lines[n],
                pygame_gui.UI_TEXT_ENTRY_CHANGED,
                lambda e, i=n: self.on_change_enemy_count(e, i))

        self.set_blocking(True)
        self.update_settings()

    def update_falls_list(self):
        self.falls_list = []
        for i in range(0, len(map_settings.settings.falls)):
            self.falls_list.append("Fall " + str(i + 1))
        self.falls_ui_list.set_item_list(self.falls_list)

        if len(self.falls_list) > 0:
            # self.falls_ui_list.item_list[self.current_selected_fall]['selected'] = True
            curr_fall = map_settings.settings.falls[self.current_selected_fall]
            self.fall_gold_reward.set_text(str(curr_fall.gold_reward))

    def update_groups_list(self):
        if len(self.falls_list) > 0:
            curr_fall = map_settings.settings.falls[self.current_selected_fall]

            # there is always at least 1 group per fall
            self.groups_list = []
            for i in range(0, len(curr_fall.groups)):
                self.groups_list.append("Group " + str(i + 1))
            self.groups_ui_list.set_item_list(self.groups_list)

    def update_group_panel(self):
        curr_fall = map_settings.settings.falls[self.current_selected_fall]
        if len(self.falls_list) > 0 and len(curr_fall.groups) > 0:
            curr_group = curr_fall.groups[self.current_selected_group]
            self.group_spawn_mode_dropdown.selected_option = curr_group.spawn_mode
            self.spawn_delay_entry_line.set_text(str(curr_group.spawn_delay))
            self.interval_from_entry_line.set_text(str(curr_group.interval[0]))
            self.interval_to_entry_line.set_text(str(curr_group.interval[1]))

    def update_fall_panel(self):
        self.fall_gold_reward.set_text(
            str(map_settings.settings.falls[
                self.current_selected_fall].gold_reward))

    def update_general_panel(self):
        self.start_gold_text_line.set_text(
            str(map_settings.settings.start_gold))
        self.start_mana_text_line.set_text(
            str(map_settings.settings.start_mana))
        self.max_tower_text_line.set_text(str(map_settings.settings.max_tower))
        self.max_spell_text_line.set_text(str(map_settings.settings.max_spell))

    def update_enemies_panel(self):
        curr_group = map_settings.settings.falls[
            self.current_selected_fall].groups[self.current_selected_group]
        for n in range(0, len(self.enemies_counts_entry_lines)):
            self.enemies_counts_entry_lines[n].set_text(
                str(curr_group.enemies_counts[n]))

    def update_settings(self):
        self.update_general_panel()
        self.update_falls_list()
        self.update_groups_list()