From 5ba8c8b3ab7d37c5ca6753a37dc3351207d8c3f9 Mon Sep 17 00:00:00 2001 From: shiva404 Date: Sat, 7 Mar 2026 00:22:24 +0300 Subject: [PATCH] Fixed leaky abstraction Map - draw - Object. --- eb_engine.py | 111 +++++++++++++++++++++++++++----------------------- eb_objects.py | 27 +----------- main.py | 22 +--------- plan.txt | 1 + 4 files changed, 64 insertions(+), 97 deletions(-) diff --git a/eb_engine.py b/eb_engine.py index d67a861..5e4bb6d 100644 --- a/eb_engine.py +++ b/eb_engine.py @@ -77,7 +77,16 @@ class Map: cell.creature_obj.walkable_matrix = self.walkable_matrix cell.creature_obj.rocks_matrix = self.rocks_matrix + def draw_obj(self, obj, draw_data): + if draw_data["spr_up"] == 0: + if obj.sprite_state == len(draw_data["sprites"][obj.sprite_name]) - 1: + obj.sprite_state = 0 + else: + obj.sprite_state += 1 + sp = draw_data["sprites"][obj.sprite_name][obj.sprite_state] + rect = sp.get_rect(center = (draw_data["x"] + draw_data["w"] /2, draw_data["y"] + draw_data["h"]/ 2)) + draw_data["screen"].blit(sp, rect) def move_obj(self, type, start, goal): """Перемещает объект типа 'terrain_obj', 'item_obj' или 'creature_obj' @@ -156,54 +165,54 @@ class Map: if cell.terrain_obj and cell.terrain_obj.sprite_name == "rock_small": self.rocks_matrix[r][c] = True -# def draw_map(self, screen, current_frame, grid=True): -# terrain_list = [] -# creature_list = [] -# -# # ★ 1 ПАСС: собираем terrain и creatures ★ -# for j in range(len(self.cells)): -# for i, cell in enumerate(self.cells[j]): -# base_x = i * self.cell_size + self.cam_x -# base_y = j * self.cell_size + self.cam_y -# -# # Terrain данные -# terrain_dd = { -# "x": int(base_x * self.scale), "y": int(base_y * self.scale), -# "w": int(self.cell_size * self.scale - self.cell_dist), -# "h": int(self.cell_size * self.scale - self.cell_dist), -# "spr_up": current_frame % self.sprites_refresh, -# "sprites": self.sprites, "scale": self.scale, "screen": screen -# } -# terrain_list.append((cell.terrain_obj, terrain_dd)) -# -# # Creature данные (если есть) -# if cell.creature_obj: -# offset_x, offset_y = cell.creature_obj.render_offset -# creature_dd = terrain_dd.copy() -# creature_dd["x"] = int((base_x + offset_x) * self.scale) -# creature_dd["y"] = int((base_y + offset_y) * self.scale) -# creature_list.append((cell.creature_obj, creature_dd)) -# -# # ★ 2 ПАСС: рисуем terrain ★ -# for obj, dd in terrain_list: -# obj.draw(dd) -# -# # ★ 3 ПАСС: рисуем ВСЕХ creatures ПОСЛЕ terrain ★ -# for obj, dd in creature_list: -# obj.draw(dd) -# -# # ★ 4 ПАСС: grid поверх всего ★ -# for j in range(len(self.cells)): -# for i, cell in enumerate(self.cells[j]): -# base_x = i * self.cell_size + self.cam_x -# base_y = j * self.cell_size + self.cam_y -# grid_rect = pygame.Rect( -# int(base_x * self.scale), int(base_y * self.scale), -# int(self.cell_size * self.scale - self.cell_dist), -# int(self.cell_size * self.scale - self.cell_dist) -# ) -# color = self.target_color if cell.is_target else self.color -# pygame.draw.rect(screen, color, grid_rect, self.bord) + def OLDSTABLE_draw_map(self, screen, current_frame, grid=True): + terrain_list = [] + creature_list = [] + + # ★ 1 ПАСС: собираем terrain и creatures ★ + for j in range(len(self.cells)): + for i, cell in enumerate(self.cells[j]): + base_x = i * self.cell_size + self.cam_x + base_y = j * self.cell_size + self.cam_y + + # Terrain данные + terrain_dd = { + "x": int(base_x * self.scale), "y": int(base_y * self.scale), + "w": int(self.cell_size * self.scale - self.cell_dist), + "h": int(self.cell_size * self.scale - self.cell_dist), + "spr_up": current_frame % self.sprites_refresh, + "sprites": self.sprites, "scale": self.scale, "screen": screen + } + terrain_list.append((cell.terrain_obj, terrain_dd)) + + # Creature данные (если есть) + if cell.creature_obj: + offset_x, offset_y = cell.creature_obj.render_offset + creature_dd = terrain_dd.copy() + creature_dd["x"] = int((base_x + offset_x) * self.scale) + creature_dd["y"] = int((base_y + offset_y) * self.scale) + creature_list.append((cell.creature_obj, creature_dd)) + + # ★ 2 ПАСС: рисуем terrain ★ + for obj, dd in terrain_list: + obj.draw(dd) + + # ★ 3 ПАСС: рисуем ВСЕХ creatures ПОСЛЕ terrain ★ + for obj, dd in creature_list: + obj.draw(dd) + + # ★ 4 ПАСС: grid поверх всего ★ + for j in range(len(self.cells)): + for i, cell in enumerate(self.cells[j]): + base_x = i * self.cell_size + self.cam_x + base_y = j * self.cell_size + self.cam_y + grid_rect = pygame.Rect( + int(base_x * self.scale), int(base_y * self.scale), + int(self.cell_size * self.scale - self.cell_dist), + int(self.cell_size * self.scale - self.cell_dist) + ) + color = self.target_color if cell.is_target else self.color + pygame.draw.rect(screen, color, grid_rect, self.bord) def draw_map(self, screen, current_frame, grid=True): screen_rect = screen.get_rect() @@ -251,11 +260,11 @@ class Map: # ★ 2 ПАСС: рисуем terrain ★ for obj, dd in terrain_list: - obj.draw(dd) + self.draw_obj(obj, dd) # ★ 3 ПАСС: рисуем ВСЕХ creatures ПОСЛЕ terrain ★ for obj, dd in creature_list: - obj.draw(dd) + self.draw_obj(obj, dd) # ★ 4 ПАСС: grid только для видимых ячеек ★ for j in range(min_row, max_row): @@ -268,7 +277,7 @@ class Map: grid_rect = pygame.Rect( int(base_x * self.scale), int(base_y * self.scale), int(self.cell_size * self.scale - self.cell_dist), - int(self.cell_size * self.scale - self.cell_dist) # ИСПРАВЛЕНО + int(self.cell_size * self.scale - self.cell_dist) ) color = self.target_color if cell.is_target else self.color pygame.draw.rect(screen, color, grid_rect, self.bord) diff --git a/eb_objects.py b/eb_objects.py index d11d52a..46bb09a 100644 --- a/eb_objects.py +++ b/eb_objects.py @@ -25,21 +25,8 @@ class Object: sprite_state: int = 0 grid_pos: tuple = None # current_map - # pos # weight # effects = {} - - def draw(self, draw_data): - if draw_data["spr_up"] == 0: - if self.sprite_state == len(draw_data["sprites"][self.sprite_name]) - 1: - self.sprite_state = 0 - else: - self.sprite_state += 1 - - sp = draw_data["sprites"][self.sprite_name][self.sprite_state] - rect = sp.get_rect(center = (draw_data["x"] + draw_data["w"] /2, draw_data["y"] + draw_data["h"]/ 2)) - draw_data["screen"].blit(sp, rect) - def update(self): pass @@ -49,15 +36,13 @@ class Terrain(Object): @dataclass class Creature(Object): - direction: int = 0 # tuple? + #direction: int = 0 # tuple? move_progress: float = 0.0 # 0.0 = старт клетки, 1.0 = конец клетки current_target: tuple = None # (row, col) следующая клетка final_goal: tuple = None move_speed: float = 0.02 # пикселей/кадр render_offset: tuple = (0.0, 0.0) start_pos: tuple = None # (row, col) начальная позиция сегмента пути - replan_counter: int = 0 - REPLAN_INTERVAL: int = 30000 waypoints: list = field(default_factory = list) walkable_matrix: list = field(default_factory = list) rocks_matrix: list = field(default_factory = list) @@ -92,12 +77,6 @@ class Creature(Object): self.render_offset = (0.0, 0.0) return - #self.replan_counter += 1 - #if self.replan_counter >= self.REPLAN_INTERVAL: - # self.replan_counter = 0 - # self.replan(map_obj.cells, self.start_pos) - - if self.current_target is None: return #target_row, target_col = self.current_target @@ -258,16 +237,12 @@ class Creature(Object): self.grid_pos[1] + area)) self.move(cells, goal) - def move_rand(self, cells, area_start, area_end): goal = (random.randint(area_start, area_end), random.randint(area_start, area_end)) while goal == self.grid_pos: goal = (random.randint(area_start, area_end), random.randint(area_start, area_end)) self.move(cells, goal) - - - @dataclass class Item(Object): # passive_abilities = {} diff --git a/main.py b/main.py index 02c7c4f..78d3d29 100644 --- a/main.py +++ b/main.py @@ -10,36 +10,18 @@ if __name__ == "__main__": main() # todo: # прокрутка баг консоль и карта - # ОПТИМИЗАЦИИ - # перепроверять путь пореже, или только после столкновения, или локальный поиск - # очередь задач и задача рандомного патруля # устроить краш тест поиску пути, запустив много объектов на маленьком поле, успел заметить баги # добавить функцию движения за каким-то объектом # сделать, чтобы в случае отменненого движения не телепортировался назад, а плавно # приступаем к логике # сделать по аналогии с текущей клеткой текущий объект - - - # посмотреть как в clock = pygame.time.Clock() работает фпс # перемещать оъект в другую клетку при половине офсета # техдолг Егору # убрать cells и mapobject creature - перенести нужную логику в методы Map # система имен спрайтов и Action - реализовать - # рисовать группой спрайтов как в перпл + # рисовать группой спрайтов # нужен ли теперь start_pos? grid_pos? - # class Task с проверками выполнения экшонов - - #вернуть назад апдейт. вернул - работает, сравнить с новым и решить - #final_goal = None - check all! - #рефактор goal = (random.randint(self.grid_pos[0] - area, - # self.grid_pos[0] + area), - # random.randint(self.grid_pos[1] - area, - # self.grid_pos[1] + area)) - - # отловить баг - иногда всё равно встают - похоже из-за реплана и коллизий с эльфами - # вроде починил, добавив final_goal = None в реплан, проверить - - # совет ксюши - не считать коллизии с объектами, только при перемещении в клетку проверять \ No newline at end of file + # class Task с проверками выполнения экшонов \ No newline at end of file diff --git a/plan.txt b/plan.txt index 2f28281..e5918ec 100644 --- a/plan.txt +++ b/plan.txt @@ -1,4 +1,5 @@ 1. Доработка системы задач: класс Task, новые задачи, проработка старых; + 2. Доработка движка и приведение его структуры в порядок: - вынос всех функций карты в карту, объекты знают свою позицию и им этого хватит. взаимодействия с картой и другими объектами должно происходить только в методе движения, остальные методы должны абстрагироваться от карты;