diff --git a/__pycache__/common.cpython-314.pyc b/__pycache__/common.cpython-314.pyc index e8dab0f..6b7fa64 100644 Binary files a/__pycache__/common.cpython-314.pyc and b/__pycache__/common.cpython-314.pyc differ diff --git a/__pycache__/eb_engine.cpython-314.pyc b/__pycache__/eb_engine.cpython-314.pyc index f5cf719..ebeb9b8 100644 Binary files a/__pycache__/eb_engine.cpython-314.pyc and b/__pycache__/eb_engine.cpython-314.pyc differ diff --git a/__pycache__/eb_objects.cpython-314.pyc b/__pycache__/eb_objects.cpython-314.pyc index 474e34f..7537c2e 100644 Binary files a/__pycache__/eb_objects.cpython-314.pyc and b/__pycache__/eb_objects.cpython-314.pyc differ diff --git a/common.py b/common.py index ccf4703..5947690 100644 --- a/common.py +++ b/common.py @@ -4,6 +4,7 @@ import uuid from dataclasses import dataclass, field from copy import deepcopy import pygame +import pygame_gui def path_exists(data, path): current = data diff --git a/def_map.json b/def_map.json index 0425386..9b9c343 100644 --- a/def_map.json +++ b/def_map.json @@ -6,7 +6,11 @@ "name": "2", "sprite_name": "grass_small" }, - "item_obj": {}, + "item_obj": { + "id": "1", + "name": "2", + "sprite_name": "sword_default" + }, "creature_obj": {} }, { @@ -16,7 +20,11 @@ "sprite_name": "grass_small" }, "item_obj": {}, - "creature_obj": {} + "creature_obj": { + "id": "1", + "name": "2", + "sprite_name": "elf_watching" + } }, { "terrain_obj": { diff --git a/eb_engine.py b/eb_engine.py index 1989a98..0ab99df 100644 --- a/eb_engine.py +++ b/eb_engine.py @@ -1,4 +1,5 @@ -from common import pygame, os, json, uuid, deepcopy, dataclass, field +from common import os, json, uuid, deepcopy, dataclass, field +from common import pygame, pygame_gui import eb_objects import eb_terrain_objects import eb_creature_objects @@ -7,7 +8,7 @@ import eb_creature_objects import gc, psutil, os cell_classes = {"grass_small": eb_terrain_objects.Ground, - "sword_default": eb_objects.Item} + "sword_default": eb_objects.Item, "elf_watching": eb_creature_objects.Unit} main_dir = os.path.dirname(os.path.abspath(__file__)) sprites_dir = os.path.join(main_dir, "res", "sprites") @@ -18,10 +19,10 @@ sprites_dir = os.path.join(main_dir, "res", "sprites") @dataclass class Cell: - terrain_obj: any + terrain_obj: None = None item_obj: None = None creature_obj: None = None - is_target: bool = False + is_target: bool = False @dataclass class Map: @@ -45,12 +46,15 @@ class Map: for line in range(len(buff)): self.cells[line] = [] for cell in buff[str(line)]: - final_cell = deepcopy(Cell(cell_classes[cell["terrain_obj"]["sprite_name"]](**cell["terrain_obj"]))) + final_cell = Cell(cell_classes[cell["terrain_obj"]["sprite_name"]](**cell["terrain_obj"])) if cell["item_obj"]: - final_cell.item_obj = deepcopy(cell_classes[cell["item_obj"]["sprite_name"]](**cell["item_obj"])) + final_cell.item_obj = cell_classes[cell["item_obj"]["sprite_name"]](**cell["item_obj"]) - self.cells[line].append(deepcopy(final_cell)) + if cell["creature_obj"]: + final_cell.creature_obj = cell_classes[cell["creature_obj"]["sprite_name"]](**cell["creature_obj"]) + + self.cells[line].append(final_cell) def draw_map(self, screen, current_frame, grid = True): for j in range(len(self.cells)): @@ -126,12 +130,57 @@ class Engine: scaled = self.scale_image(sprite) self.cached_sprites[sp_name][i] = scaled + def create_console(self, manager): + console_window = pygame_gui.elements.UIWindow( + pygame.Rect(100, 100, 400, 300), + manager=manager, + window_display_title='Console', + resizable=True + ) + + input_entry = pygame_gui.elements.UITextEntryLine( + relative_rect=pygame.Rect(10, 250, 380, 30), + container=console_window, + manager=manager + ) + + # ★ UIScrollingContainer ★ + scroll_container = pygame_gui.elements.UIScrollingContainer( + relative_rect=pygame.Rect(10, 10, 380, 230), + container=console_window, + manager=manager, + allow_scroll_x=False + ) + + # ★ UITextBox ВНУТРИ контейнера ★ + output_box = pygame_gui.elements.UITextBox( + html_text=">>> Готово!\n", + relative_rect=pygame.Rect(0, 0, 380, 1000), # ← Увеличьте высоту! + container=scroll_container, + manager=manager + ) + + scroll_container.set_scrollable_area_dimensions((380, 2000)) + return console_window, input_entry, scroll_container, output_box def main_loop(self): easy_map = Map("def_map.json", self.cached_sprites) #sp = eb_objects.Sprite(self.sprites, "elf_watching") #gr = pygame.image.load(file_path).convert_alpha() + background = pygame.Surface((1600, 800)) + background.fill("chartreuse4") + + manager = pygame_gui.UIManager((1600, 800)) + + #hello_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((350, 275), (100, 50)), + # text='Say Hello', + # manager=manager) + + console_window, input_entry, scroll_container, output_box = self.create_console(manager) + output_log = ">>> hlwrld1\n" + console_active = False + clock = pygame.time.Clock() running = True unlock = True @@ -142,16 +191,17 @@ class Engine: # profiling - #process = psutil.Process(os.getpid()) - #gc.collect() - #mem_before = process.memory_info().rss / 1024 + process = psutil.Process(os.getpid()) + gc.collect() + mem_before = process.memory_info().rss / 1024 while running: + time_delta = clock.tick(60)/1000.0 #pygame.event.clear() - #if global_counter % 1000 == 0: - # gc.collect() - # mem_after = process.memory_info().rss / 1024 - # print(f"Leak: {mem_after - mem_before:.1f} KB per 1000 frames") + if global_counter % 1000 == 0: + gc.collect() + mem_after = process.memory_info().rss / 1024 + print(f"Leak: {mem_after - mem_before:.1f} KB per 1000 frames") # poll for events # pygame.QUIT event means the user clicked X to close your window @@ -159,13 +209,42 @@ class Engine: if event.type == pygame.QUIT: running = False + if event.type == pygame_gui.UI_TEXT_ENTRY_FINISHED and event.ui_element == input_entry: + user_text = input_entry.get_text() + if user_text.strip(): + output_log += f">>> {user_text}\n" + output_box.set_text(output_log) + input_entry.set_text("") + console_active = False + + console_active = bool(input_entry.get_text().strip()) + + if event.type == pygame.VIDEORESIZE: + new_size = event.size + self.screen = pygame.display.set_mode(new_size, pygame.RESIZABLE) + manager.clear_and_set_new_size((new_size[0], new_size[1])) + + # ★ ПЕРЕСОЗДАНИЕ ★ + console_window.kill() + input_entry.kill() + scroll_container.kill() + output_box.kill() + + console_window, input_entry, scroll_container, output_box = self.create_console(manager) + + + manager.process_events(event) + + manager.update(time_delta) # fill the screen with a color to wipe away anything from last frame - self.screen.fill("chartreuse4") + #self.screen.fill("chartreuse4") + self.screen.blit(background, (0, 0)) easy_map.draw_map(self.screen, current_frame + 1) + manager.draw_ui(self.screen) #print(easy_map.cells[0][0].item_obj.sprite_cache) - if unlock: + if not console_active: keys = pygame.key.get_pressed() if keys[pygame.K_w]: easy_map.cam_y += self.camera_step @@ -193,12 +272,10 @@ class Engine: global_counter = 0 # flip() the display to put your work on screen - pygame.display.flip() - # limits FPS to 60 - clock.tick(max_fps) + pygame.display.update() if global_counter % 100 == 0: current_fps = clock.get_fps() - print(f"Current FPS: {current_fps:.2f}") + #print(f"Current FPS: {current_fps:.2f}") pygame.quit() \ No newline at end of file diff --git a/eb_objects.py b/eb_objects.py index b75c1f4..c072815 100644 --- a/eb_objects.py +++ b/eb_objects.py @@ -5,7 +5,7 @@ class Object: id: str name: str sprite_name: str - sprite_state: int = 0 + sprite_state: int = 0 def draw(self, draw_data): if draw_data["spr_up"] == 0: diff --git a/main.py b/main.py index 1655dac..7025ed0 100644 --- a/main.py +++ b/main.py @@ -27,16 +27,18 @@ if __name__ == "__main__": #техдолг: #проверить дефолтдикт field и None = None - #не взлетело кэширование - потом доделать - + # техдолг - draw_data to dd + # изучить pypmler + # настроить логирование всего + #SLOP: + # проверить у ллм на ошибки - РЕГУЛЯРНАЯ АКТИВНОСТЬ: # - deepcopy + # - общие + - main() - # техдолг - draw_data to dd - #pygame.init() - #size = width, height = 640, 480 - ## Use HWSURFACE and DOUBLEBUF flags - #screen = pygame.display.set_mode(size, pygame.HWSURFACE | pygame.DOUBLEBUF) - # изучить pypmler - # настроить логирование всего \ No newline at end of file + main() + + # добавил гуй, динамическая консоль, всё работает, но: + # - слоп, почистить + # - мини-баг - если первые вводимые буквы совпадают с клавишами управления, один раз успевает проскочить до лока. некритично. + # - при вводе текста нет прокрутки к концу + # - плавающий баг - если повводить текст, а потом закрыть консоль, игра не закроется по эскейпу. \ No newline at end of file