From b34aaa1664b9ef3e86004a6ad349cea7e6055478 Mon Sep 17 00:00:00 2001 From: shiva404 Date: Mon, 16 Feb 2026 17:20:37 +0300 Subject: [PATCH] shameslop, but gui still works. --- __pycache__/common.cpython-314.pyc | Bin 607 -> 630 bytes __pycache__/eb_engine.cpython-314.pyc | Bin 12955 -> 16864 bytes __pycache__/eb_objects.cpython-314.pyc | Bin 2516 -> 2516 bytes common.py | 1 + def_map.json | 12 ++- eb_engine.py | 117 ++++++++++++++++++++----- eb_objects.py | 2 +- main.py | 22 ++--- 8 files changed, 121 insertions(+), 33 deletions(-) diff --git a/__pycache__/common.cpython-314.pyc b/__pycache__/common.cpython-314.pyc index e8dab0fa2b9077e0b5d83d136b19067859eee4f3..6b7fa640df0a8960efae9db39125f02c490d9d92 100644 GIT binary patch delta 126 zcmcc5@{NU8n~#@^0SKJZCuQbNTZlX-=wLkpz&-2*kzm UldYMgcyBWZeqmu}6acFQ0FEpj7ytkO delta 79 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 delta 3960 zcma)9du*H46~EuhcKk@3*sKxNNhCw*8T;O;dfVL=gK2X>5TaWgFYrIoENM zBG|Z+fA@U%o_p@O_nw#MpAueF8=DIqRs!wU4?ds#PbDEA;zzzIOT?`+XB+Fny=L89 zMTSUN+-=bZS-;D}*I4Nm+Dr zSk^5Oq8G5Y#Cl;T`&V(}hOpQL*R%=*aY{z&fbft2qYBcXoarMxgkjTFN@K}%G;`#U z0k%e}H;IN6OP^#1r4w!!aA+F<{{A$1l6+87IwO~|_oZ5w(>){mKeZ7-xCOK1brQ5P zx4hnl3#c2RlpT_H?DPSt;U#xdd@x#+2QE1PUm$ssESN}n(sWAAFvoAmu*cO@DjH9LnW!3dvCl0#;OyH98q7i9(f&f%Xu;q_!z+n5HeZ%6 z56*V>{kDI$^U(F?hi01T^w5#%cy@N^7|>T&X;%aKly%ATixS#YqS zB9E;D54R4XjZGBQ2)o$JMUCAK9N-rwCur#S;a&`vjDLQS~WCU&bB)J!iGzSoKFivfOT*2vCoU&nLrDn?FfAD zeMq$-gaHh@9-||w9_2gIJ{&)YunS=?LO;R)Kv1UZp)=$}GOp7-NGikduzFCWWyr*B zAAPKLGH3jLpk0QuKbCEcMq}x8MvsAoL_ty4YZGYcL4m6>5EKpuOKBAfsYa+ls72uF z79cf*a9eRYh@bycU%Cxh4k6Sb)FWV2q!VO3|p3 z-6nub7fR2FCjK%KTT`}A=w%aSz9#exqc9$eA5|04oM&lpS!e@X?^U@A-o~z!`Gg0U zQTCD$xOBpIQOb#uSs<{bjX#l9Q}v}-OEJzG3V7+5X2@EG>XaLuk{pYTsB|qm6YvWg z*{gxNd(mDXh*Nbq`KTeK$H(YnxHUdR&f2)a!52*}^R&?{cy75bn%4fu4u0#PG zA*#h=DV0j>)#^$UH|B4#-&NOwn}1wgFC1qjHHX1!Gc_Mp@Y}%s=x&5(5i$Tl6Wz$t zwdHW&)3sHw@b%gz;W75d+6VbUpO`SSmZkw#>2b697E5bZ3=3Hae)15>DnpyICg{y! zF>8rPjUW$OkCXsEfbb}@!xaG*s(0a1yOZn$Bgqy-3POc!KMamGTiNR#S7qk|gp9zg zRggZgr?8Zj`oL~5HbzLOguPSmYA(%5UWs9OIhIC*kT*Za9=2DD5ryqtejI3qzzH(<3xnsi)*l^9huh}fWc)9QV1tE$1@!lf> zZ2dLs*u}NqR7v3c|4Odsw^G$%*)K(uAz|gN5mO5UhmS*-whrdATgCGIi+t_r6|8Cpi?fE5P zC1MLhbZHlt*Yrqz5MEbodJii$x!E6r)`_qg0-oiR9YRlZ4C4PIS|)ukdGXr<*=g9~ zM`I9s)NxJiIOW(ePN|yKt9OPDY^pvbwYCor1Z#OP=1!jrQL>&KQw?QDDia?y6!kbP zFeJ!ZhOD2=s)oG(zTF3DFX(E>!^u>N1~BX!(x`e8icd&y5XqpjNElLI^aSl^H5>dB zdpSp6ln)-`3D2lWJJ{qCE$8Y!CI&VH}f(Q^_pso&zs%!R|d3*75drt3}I&sZjHD46CD9sktT|72d)C9X<7&|}qVrI&A z(^-1XadGtRy6J}X)1D1;&dxtu3ZJu`u|4acSg^dM@?wR@e+>BiMQIYLM-YC5@EQU> zPEg6!1U!eC4~)~{SX||G360|P*H$HL-_|mrpB>%$Xs!s6a)yTH!)v60p!gA%@bs4` z#`~3ZNdeCDlH?m|%d3%mm8?Y*NeZd68-(!mhIU3TBh(?>S*on8RF2>@LO=YpA@<6) zgTBH&g5p^m6;_lf$Pp}OW!=rJw|iZUA&$f$oonNIGG&-{(ad-{VaU6o5TN*HhaP7? z>|Wjf1d_i(z_gHaLB3xleqz1Gs}94mc`TC{PpMn!?_msYN_!7rK@tSvebO^WdS*xu z^KDu?@g|^=_P_aN{q2iWAMB9Q0)PfzTMX^m77ZwQO(i9&^2z>GhLGUaPL_Ybc Ih$PqJzsy5%`Tzg` diff --git a/__pycache__/eb_objects.cpython-314.pyc b/__pycache__/eb_objects.cpython-314.pyc index 474e34f07425f4d06e97894cd1f3b4c70493d470..7537c2e010d0284216ecef72f353440f6de078df 100644 GIT binary patch delta 36 rcmca2d_|a7n~#@^0SJ!7Ps&`skynn5QEsvh+g>I)`OUA{UNQjyu$Br+ delta 36 rcmca2d_|a7n~#@^0SKmqP0HM|kynn5QF*cs+g>JRmCdi&UNQjytYHcz 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