From 6b6ca341dc99c2ab3b9fdc074ad32a5c7881ba3f Mon Sep 17 00:00:00 2001 From: shiva404 Date: Tue, 24 Feb 2026 02:03:22 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D1=83=D1=81=D0=BA=D0=BE=D1=80=D0=B5=D0=BD=D0=BD=D1=8B=D0=B9=20?= =?UTF-8?q?A*=20=D0=B8=D0=B7=20=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE=D1=82?= =?UTF-8?q?=D0=B5=D0=BA=D0=B8=20pathfinding=20-=20=D0=BF=D1=80=D0=BE=D0=B8?= =?UTF-8?q?=D0=B7=D0=B2=D0=BE=D0=BB=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=B2=D1=8B=D1=80=D0=BE=D1=81=D0=BB?= =?UTF-8?q?=D0=B0,=20=D0=BD=D0=BE=20=D0=BD=D0=B5=D1=81=D0=B8=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=BE.=20=D0=9F=D0=BE=D0=BA=D0=B0=20=D1=8D=D1=82=D0=BE?= =?UTF-8?q?=D1=82=20=D0=B2=D0=B0=D1=80=D0=B8=D0=B0=D0=BD=D1=82=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B8=D0=BB,?= =?UTF-8?q?=20=D1=81=D0=B5=D0=B9=D1=87=D0=B0=D1=81=20=D1=80=D0=B5=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20BFS=20+=20walkable?= =?UTF-8?q?=20=D0=BC=D0=B0=D1=82=D1=80=D0=B8=D1=86=D0=B0,=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82=20=D0=B3=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=B4=D0=BE=20=D0=BB=D1=83=D1=87=D1=88=D0=B5,=20=D1=81?= =?UTF-8?q?=20=D0=BD=D0=B5=D0=BE=D0=BF=D1=82=D0=B8=D0=BC=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=BC=20=D1=80=D0=B5=D0=BD=D0=B4=D0=B5=D1=80=D0=BE?= =?UTF-8?q?=D0=BC=20100=20=D0=BE=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=B4=D0=B5=D1=80=D0=B6=D0=B8=D1=82,=20=D0=B1=D0=B5=D0=B7?= =?UTF-8?q?=20=D1=80=D0=B5=D0=BD=D0=B4=D0=B5=D1=80=D0=B0=20300.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/common.cpython-314.pyc | Bin 4867 -> 5202 bytes __pycache__/eb_engine.cpython-314.pyc | Bin 22703 -> 24552 bytes __pycache__/eb_objects.cpython-314.pyc | Bin 5568 -> 7263 bytes common.py | 285 +++++++++++++++++++------ def_map.json | 6 +- eb_engine.py | 72 ++++++- eb_objects.py | 40 +++- main.py | 12 +- problems.txt | 3 +- 9 files changed, 337 insertions(+), 81 deletions(-) diff --git a/__pycache__/common.cpython-314.pyc b/__pycache__/common.cpython-314.pyc index 17ef8f37ece86794ed51844e0ea072cfd0f4d118..17834610c7996041fbdaeedc719160f88225a5e0 100644 GIT binary patch literal 5202 zcmb6dTW}lI_3mmV>;0DB4>^7$b`l3W&Z9Opv1>baj7=h(RYP2>inK8zvb0&PNK876 zl0ru`N!c)nh?xKiO^Y)?>j5%N3xSjm%1nP *-r;NdY-{vgRm^VOcalHA24hF)9u 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 diff --git a/__pycache__/eb_engine.cpython-314.pyc b/__pycache__/eb_engine.cpython-314.pyc index 19cabcd04013127f4a80952cedb037027eb82fbc..e52359c852318cf2942dc262d756dd31689ed767 100644 GIT binary patch delta 6357 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 P-D40+vk#;JiPQfB^*pe# delta 4824 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 Q$3M`4_~5h-ryCFa4ZX$yHvj+t delta 1135 zcmZuwOKcle6n$?#_Bft#?f5f^r`Sm&hgfl;aSOB!h0>2`scKaNIH4hNEIU7NJnowb zffe4+k_BRMk?5)tOWIWt-66pmbrXar8bP~Yg~Xyw7OarCcU(uU)F=7ebLX9R=DqXA z503sc8Jmn50}O|D=j*k6>~?HO<6pt^+Uk_z8Fs{r*|N9KR!!!`?GR$3$_{foY_gW- z4ceNQtTHcU%VVrK0KaI5N)3g~9uF0(jMlqY=Ijw=R(9#?mqwYKN_vBriFOKq=)ij^e~T)mL@)y7h*<@#!{%vV;N zdaGxobn4zJe6JT`FQAV*htOqzYGd$^enm>jP&3-_pOJyX@kzLEM5Onl@W9BywYY(8 zK5k1#e_*V6gR%XrDqk|-n|Km_i(iy3CE#`<1@no|xD0Ibk7MH=<1m|=fcMgu6MFp1 z%2wr`p4--Q*RTAlkHX#bBAm`N_*J;2UVxp9Rg$J9J3NjH-{x~Na_tEoAxo*^2Xq(Uq>2_2!Rz%4TiKbyz+$Dj-~KTQp9D}_gC#`&WRi>J30YsbV!JV#=+ zXAzj~S@g0A!b*!0xgR8;D;F;kQ0`)pAV_hZ*aAVFphmE_y@Ysrf8s4TG5j*00dM$Z z+A4G}{%%^`^E;u4TG|=1)bhVC!TsSQd=`?~gComiMKFs$H;izV?P^So1iKf@&<#)U z1=z}#M^;HnKpW{xLwnNIK-vVwni~Cpqy$YOuMkie!J`VMd=jeGfpYNfz%|h4_heaQ vzV_<6)7)q+y(T`ymi~zDO}J^jX&&L_&p+B_SaxM5MITDY9=16|_rLQ$$zuD> diff --git a/common.py b/common.py index bfeb276..a892229 100644 --- a/common.py +++ b/common.py @@ -1,6 +1,7 @@ import os import json import uuid +import random from dataclasses import dataclass, field from copy import deepcopy @@ -12,6 +13,14 @@ import pygame_gui from classes import Rock +from pathfinding.core.grid import Grid +from pathfinding.finder.a_star import AStarFinder + +from collections import defaultdict +from heapq import heappush, heappop +from math import sqrt, inf + + def path_exists(data, path): current = data for key in path: @@ -146,87 +155,233 @@ def path_exists(data, path): # print("Путь не найден (нет связи)") # return None +#def find_way(cells, start, goal): +# """Находит путь с диагональным движением, но БЕЗ прохода через углы""" +# rows = len(cells) +# if rows == 0: +# return None +# cols = len(cells[0]) +# +# def is_passable(cell): +# return (cell.terrain_obj is None or not isinstance(cell.terrain_obj, Rock)) +# +# s_row, s_col = start +# g_row, g_col = goal +# if not (0 <= s_row < rows and 0 <= s_col < cols and 0 <= g_row < rows and 0 <= g_col < cols): +# return None +# +# start_cell = cells[s_row][s_col] +# goal_cell = cells[g_row][g_col] +# if not is_passable(start_cell) or not is_passable(goal_cell): +# print(f"Старт/гол непроходимы") +# return None +# +# directions = [ +# (-1, 0), (1, 0), (0, -1), (0, 1), # ортогональ (1.0) +# (-1, -1), (-1, 1), (1, -1), (1, 1) # диагональ (1.414) +# ] +# +# def can_move_diagonal(current_r, current_c, dr, dc): +# """Проверяет, можно ли двигаться по диагонали (НЕ через угол)""" +# nr, nc = current_r + dr, current_c + dc +# +# # Ортогональные соседи ДОЛЖНЫ быть проходимыми для диагонального хода +# ortho1_r, ortho1_c = current_r + dr, current_c # вертикальный сосед +# ortho2_r, ortho2_c = current_r, current_c + dc # горизонтальный сосед +# +# # Проверяем границы для ортососедей +# if not (0 <= ortho1_r < rows and 0 <= ortho1_c < cols): +# return False +# if not (0 <= ortho2_r < rows and 0 <= ortho2_c < cols): +# return False +# +# return (is_passable(cells[ortho1_r][ortho1_c]) and +# is_passable(cells[ortho2_r][ortho2_c])) +# +# open_set = [] +# h = max(abs(s_row - g_row), abs(s_col - g_col)) +# heappush(open_set, (h, 0, s_row, s_col)) +# +# came_from = {} +# g_score = defaultdict(lambda: float('inf')) +# g_score[(s_row, s_col)] = 0 +# +# while open_set: +# _, _, row, col = heappop(open_set) +# if (row, col) == (g_row, g_col): +# path = [] +# current = (row, col) +# while current in came_from: +# path.append(current) +# current = came_from[current] +# path.append(start) +# return path[::-1] +# +# for dr, dc in directions: +# nr, nc = row + dr, col + dc +# if 0 <= nr < rows and 0 <= nc < cols: +# target_cell = cells[nr][nc] +# +# if (nr, nc) != start and target_cell.creature_obj is not None: +# continue +# if not is_passable(target_cell): +# continue +# +# if abs(dr) + abs(dc) == 2: +# if not can_move_diagonal(row, col, dr, dc): +# continue +# +# move_cost = 1.414 if abs(dr) + abs(dc) == 2 else 1.0 +# tentative_g = g_score[(row, col)] + move_cost +# pos = (nr, nc) +# +# if tentative_g < g_score[pos]: +# came_from[pos] = (row, col) +# g_score[pos] = tentative_g +# h = max(abs(nr - g_row), abs(nc - g_col)) +# f = tentative_g + h +# heappush(open_set, (f, tentative_g, nr, nc)) +# +# print("Путь не найден") +# return None + + +#def find_way(cells, start, goal): +# """A* pathfinding — только новая библиотека""" +# rows = len(cells) +# if rows == 0: +# print("Путь не найден: пустая карта") +# return None +# +# cols = len(cells[0]) +# +# # ★ Проверка границ ★ +# s_row, s_col = start +# g_row, g_col = goal +# if (s_row >= rows or s_col >= cols or +# g_row >= rows or g_col >= cols): +# print(f"Путь не найден: выход за границы карты {start} -> {goal}") +# return None +# +# # ★ НАХОДИМ существо в start ★ +# start_creature = cells[s_row][s_col].creature_obj +# +# # Матрица препятствий +# matrix = [[1 for _ in cells[row]] for row in range(rows)] +# +# for r in range(rows): +# for c in range(cols): +# cell_creature = cells[r][c].creature_obj +# if cell_creature and cell_creature != start_creature: +# matrix[r][c] = 0 +# +# from pathfinding.core.grid import Grid +# from pathfinding.finder.a_star import AStarFinder +# +# grid = Grid(matrix=matrix) +# start_node = grid.node(s_row, s_col) +# end_node = grid.node(g_row, g_col) +# +# finder = AStarFinder() +# path_nodes, _ = finder.find_path(start_node, end_node, grid) +# +# if not path_nodes or len(path_nodes) <= 1: +# print(f"Путь не найден: {start} -> {goal}") +# return None +# +# path = [(node.x, node.y) for node in path_nodes] +# +# return path + + def find_way(cells, start, goal): - """Находит путь с диагональным движением, но БЕЗ прохода через углы""" + """★СУПЕРБЫСТРЫЙ BFS: массивы вместо set/deque★""" rows = len(cells) if rows == 0: + print("Путь не найден: пустая карта") return None + cols = len(cells[0]) - - def is_passable(cell): - return (cell.terrain_obj is None or not isinstance(cell.terrain_obj, Rock)) - s_row, s_col = start g_row, g_col = goal - if not (0 <= s_row < rows and 0 <= s_col < cols and 0 <= g_row < rows and 0 <= g_col < cols): + + if (s_row >= rows or s_col >= cols or + g_row >= rows or g_col >= cols): + print(f"Путь не найден: выход за границы {start} -> {goal}") return None - start_cell = cells[s_row][s_col] - goal_cell = cells[g_row][g_col] - if not is_passable(start_cell) or not is_passable(goal_cell): - print(f"Старт/гол непроходимы") - return None + # ★ МАТРИЦЫ вместо set (10x быстрее хэширования) ★ + walkable = [[True] * cols for _ in range(rows)] + rocks_only = [[False] * cols for _ in range(rows)] + start_creature = cells[s_row][s_col].creature_obj - directions = [ - (-1, 0), (1, 0), (0, -1), (0, 1), # ортогональ (1.0) - (-1, -1), (-1, 1), (1, -1), (1, 1) # диагональ (1.414) - ] + for r in range(rows): + for c in range(cols): + cell = cells[r][c] + if (cell.creature_obj and cell.creature_obj != start_creature) or \ + (cell.terrain_obj and cell.terrain_obj.sprite_name == "rock_small"): + walkable[r][c] = False + if cell.terrain_obj and cell.terrain_obj.sprite_name == "rock_small": + rocks_only[r][c] = True - def can_move_diagonal(current_r, current_c, dr, dc): - """Проверяет, можно ли двигаться по диагонали (НЕ через угол)""" - nr, nc = current_r + dr, current_c + dc + # ★ ВЫЧИСЛЯЕМЫЕ МАССИВЫ ★ + visited = [[False] * cols for _ in range(rows)] + parent = [[None] * cols for _ in range(rows)] + + # ★ БЫСТРАЯ ОЧЕРЕДЬ: индекс вместо deque ★ + queue_size = 0 + queue = [[0, 0] for _ in range(rows * cols)] # Предварительно выделяем + queue[0] = [s_row, s_col] + queue_size = 1 + front = 0 + + visited[s_row][s_col] = True + + directions = [(-1,0), (1,0), (0,-1), (0,1), + (-1,-1), (-1,1), (1,-1), (1,1)] + + while front < queue_size: + # ★ БЫСТРОЕ извлечение ★ + r, c = queue[front] + front += 1 - # Ортогональные соседи ДОЛЖНЫ быть проходимыми для диагонального хода - ortho1_r, ortho1_c = current_r + dr, current_c # вертикальный сосед - ortho2_r, ortho2_c = current_r, current_c + dc # горизонтальный сосед - - # Проверяем границы для ортососедей - if not (0 <= ortho1_r < rows and 0 <= ortho1_c < cols): - return False - if not (0 <= ortho2_r < rows and 0 <= ortho2_c < cols): - return False - - return (is_passable(cells[ortho1_r][ortho1_c]) and - is_passable(cells[ortho2_r][ortho2_c])) - - open_set = [] - h = max(abs(s_row - g_row), abs(s_col - g_col)) - heappush(open_set, (h, 0, s_row, s_col)) - - came_from = {} - g_score = defaultdict(lambda: float('inf')) - g_score[(s_row, s_col)] = 0 - - while open_set: - _, _, row, col = heappop(open_set) - if (row, col) == (g_row, g_col): + if r == g_row and c == g_col: path = [] - current = (row, col) - while current in came_from: - path.append(current) - current = came_from[current] - path.append(start) + cr, cc = g_row, g_col + while True: + path.append((cr, cc)) + if parent[cr][cc] is None: + break + pr, pc = parent[cr][cc] + cr, cc = pr, pc return path[::-1] for dr, dc in directions: - nr, nc = row + dr, col + dc - if 0 <= nr < rows and 0 <= nc < cols and is_passable(cells[nr][nc]): + nr, nc = r + dr, c + dc + + if (0 <= nr < rows and 0 <= nc < cols and + walkable[nr][nc] and not visited[nr][nc]): # ★ ПРОВЕРКА ДИАГОНАЛИ ★ - if abs(dr) + abs(dc) == 2: # диагональное движение - if not can_move_diagonal(row, col, dr, dc): - continue # пропускаем запрещённую диагональ - - move_cost = 1.414 if abs(dr) + abs(dc) == 2 else 1.0 - tentative_g = g_score[(row, col)] + move_cost - pos = (nr, nc) - - if tentative_g < g_score[pos]: - came_from[pos] = (row, col) - g_score[pos] = tentative_g - h = max(abs(nr - g_row), abs(nc - g_col)) - f = tentative_g + h - heappush(open_set, (f, tentative_g, nr, nc)) + if dr * dc == 0 or can_move_diagonal(r, c, nr, nc, rocks_only, rows, cols): + visited[nr][nc] = True + parent[nr][nc] = (r, c) + + # ★ БЫСТРОЕ добавление в очередь ★ + queue[queue_size] = [nr, nc] + queue_size += 1 - print("Путь не найден") - return None \ No newline at end of file + print(f"Путь не найден: {start} -> {goal}") + return None + +def can_move_diagonal(r, c, nr, nc, rocks_only, rows, cols): + """Запрет среза только около rock""" + dr = nr - r + dc = nc - c + r1, c1 = r + dr, c + r2, c2 = r, c + dc + + check1_ok = (0 <= r1 < rows and 0 <= c1 < cols and not rocks_only[r1][c1]) + check2_ok = (0 <= r2 < rows and 0 <= c2 < cols and not rocks_only[r2][c2]) + + return check1_ok and check2_ok \ No newline at end of file diff --git a/def_map.json b/def_map.json index 0f2b5e2..4b2f92c 100644 --- a/def_map.json +++ b/def_map.json @@ -926,7 +926,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 2d2eddb..56e8cdb 100644 --- a/eb_engine.py +++ b/eb_engine.py @@ -1,4 +1,5 @@ -from common import os, json, uuid, deepcopy, dataclass, field +from common import os, json, uuid, deepcopy, random +from common import dataclass, field from common import pygame, pygame_gui import eb_objects import eb_terrain_objects @@ -68,6 +69,9 @@ class Map: def move_obj(self, type, start, goal): """Перемещает объект типа 'terrain_obj', 'item_obj' или 'creature_obj' из клетки start=(row, col) в goal=(row, col)""" + if goal is None: + return False + s_y, s_x = start d_y, d_x = goal @@ -79,8 +83,9 @@ class Map: source_cell = self.cells[s_y][s_x] dest_cell = self.cells[d_y][d_x] obj = getattr(source_cell, type) + check = getattr(dest_cell, type) - if obj is None: + if obj is None or check is not None: return False setattr(source_cell, type, None) @@ -287,6 +292,11 @@ class Engine: gc.collect() mem_before = process.memory_info().rss / 1024 + + NUM_ELVES = 1000 + elf_count = 0 + + while running: time_delta = clock.tick(60)/1000.0 #pygame.event.clear() @@ -301,6 +311,19 @@ class Engine: if event.type == pygame.QUIT: running = False + if event.type == pygame.MOUSEWHEEL: + scroll_y = event.y + + if scroll_y > 0: + easy_map.scale += self.scale_step * 5 + self.spr_scale += self.scale_step * 5 + self.scale_sprites() + elif scroll_y < 0 and easy_map.scale >= self.scale_step: + easy_map.scale -= self.scale_step * 5 + self.spr_scale -= self.scale_step * 5 + self.scale_sprites() + + if event.type == pygame_gui.UI_TEXT_ENTRY_FINISHED and event.ui_element == input_entry: user_text = input_entry.get_text() exec(user_text) @@ -349,15 +372,44 @@ class Engine: if keys[pygame.K_d]: easy_map.cam_x -= self.camera_step - if keys[pygame.K_q]: - easy_map.scale += self.scale_step - self.spr_scale += self.scale_step - self.scale_sprites() - if keys[pygame.K_e] and easy_map.scale >= self.scale_step: - easy_map.scale -= self.scale_step - self.spr_scale -= self.scale_step - self.scale_sprites() + #if keys[pygame.K_q]: + # easy_map.scale += self.scale_step + # self.spr_scale += self.scale_step + # self.scale_sprites() + #if keys[pygame.K_e] and easy_map.scale >= self.scale_step: + # easy_map.scale -= self.scale_step + # self.spr_scale -= self.scale_step + # self.scale_sprites() + + if keys[pygame.K_SPACE] and elf_count < NUM_ELVES: + # Находим свободные клетки + # ★ МАССОВЫЙ СПАВН 50 эльфов ★ + free_cells = [] + for j in range(len(easy_map.cells)): # ★ ЛИМИТ строк ★ + for i in range(len(easy_map.cells[j])): # ★ ЛИМИТ колонок ★ + cell = easy_map.cells[j][i] + if (cell.creature_obj is None and + cell.terrain_obj and + cell.terrain_obj.sprite_name == "grass_small"): + free_cells.append((j, i)) + + spawn_count = min(50, len(free_cells)) # ★ Не больше свободных клеток ★ + for _ in range(spawn_count): + row, col = random.choice(free_cells) + elf = eb_objects.Creature(id=f"elf_{random.randint(1000,9999)}", name="Elf", sprite_name="elf_watching") + easy_map.cells[row][col].creature_obj = elf + + # ★ БЕЗОПАСНЫЙ выбор цели ★ + possible_targets = [c for c in free_cells if c != (row, col)] + if possible_targets: + target_cell = random.choice(possible_targets) + elf.move(easy_map.cells, (row, col), target_cell) + + free_cells.remove((row, col)) # Убираем занятые клетки + + + if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: mouse_pos = pygame.mouse.get_pos() console_rect = console_window.get_abs_rect() diff --git a/eb_objects.py b/eb_objects.py index db98d10..c24e56c 100644 --- a/eb_objects.py +++ b/eb_objects.py @@ -38,13 +38,28 @@ class Creature(Object): 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 = 300 + + + def replan(self, cells, pos): + from common import find_way + path = find_way(cells, pos, self.final_goal) + if path and len(path) > 1: + self.waypoints = path[1:] + self.current_target = self.waypoints[0] + else: + self.waypoints.clear() + self.current_target = None def move(self, cells, start, goal): from common import find_way + self.final_goal = goal self.start_pos = start path = find_way(cells, start, goal) if path and len(path) > 1: @@ -59,6 +74,24 @@ class Creature(Object): if self.current_target is None or not self.waypoints: 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 + if (target_row in map_obj.cells and + target_col < len(map_obj.cells[target_row])): + target_cell = map_obj.cells[target_row][target_col] + if target_cell.creature_obj is not None: + self.current_target = None + self.waypoints.clear() + self.render_offset = (0.0, 0.0) + self.replan(map_obj.cells, self.start_pos) + return self.move_progress += self.move_speed * time_delta * 60 self.move_progress = min(self.move_progress, 1.0) @@ -66,7 +99,7 @@ class Creature(Object): if self.move_progress >= 1.0: map_obj.move_obj('creature_obj', self.start_pos, self.current_target) - self.waypoints.pop(0) + if self.waypoints: self.waypoints.pop(0) if self.waypoints: self.start_pos = self.current_target # Новая клетка как старт self.current_target = self.waypoints[0] @@ -79,7 +112,10 @@ class Creature(Object): # ★ ТОЛЬКО интерполяция offset ★ start_row, start_col = self.start_pos #or (0, 0) - target_row, target_col = self.current_target + if self.current_target is None: + self.render_offset = (0.0, 0.0) + return + target_row, target_col = self.current_target offset_x = (target_col - start_col) * cell_size * self.move_progress offset_y = (target_row - start_row) * cell_size * self.move_progress self.render_offset = (offset_x, offset_y) diff --git a/main.py b/main.py index e9d4166..4b0d6d7 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,18 @@ import eb_engine +#import os +#os.environ['PYTHONJIT'] = '1' def main(): e = eb_engine.Engine() e.main_loop() if __name__ == "__main__": - main() \ No newline at end of file + main() + # todo: + # прокрутка баг консоль и карта + # ОПТИМИЗАЦИИ + # очередь задач и задача рандомного патруля + # устроить краш тест поиску пути, запустив много объектов на маленьком поле, успел заметить баги + # добавить функцию движения за каким-то объектом + # сделать, чтобы в случае отменненого движения не телепортировался назад, а плавно + # приступаем к логике \ No newline at end of file diff --git a/problems.txt b/problems.txt index 6721b95..d95cc90 100644 --- a/problems.txt +++ b/problems.txt @@ -50,8 +50,7 @@ scale_image() вызывается 150×150=22,500 раз в секунду пр # проверить у ллм на ошибки - РЕГУЛЯРНАЯ АКТИВНОСТЬ: # - deepcopy + # - общие + - # !!! ДОБАВИТЬ ПРОКРУТКУ И МАСШТАБ КАРТЫ ДЛЯ МЫШИ !!! - # + # # ДОДЕЛАТЬ move для Creature - хранить pos в объекте ??? # # ПРОВЕРИТЬ МЕНЯЕТСЯ ЛИ ПЕРЕДАННЫЙ В ОБЪЕКТ cells и если да,