Сделал ещё одну очевидную оптимизацию - кэширование матриц препятствий, результат превзошёл всё ожидания. 300 объектов - плавные 60 фпс, 500 объектов - 60 фпс с микрофризами. Для масштабов игры этого уже более чем достаточно. Теперь следует добиться такого же для более слабых машин, надо выбрать минимальные системные требования.

This commit is contained in:
shiva404
2026-03-06 04:00:43 +03:00
parent fa189a4c3b
commit b1548ea182
6 changed files with 529 additions and 50 deletions

226
common.py
View File

@@ -26,6 +26,12 @@ def path_exists(data, path):
return False return False
return True return True
def find_way(cells, start, goal, walkable, rocks_only):
result = bfs_quick(cells, start, goal, walkable, rocks_only)
return result
'''
#def find_way(cells, start, goal): #def find_way(cells, start, goal):
# """Находит путь от start=(row, col) к goal=(row, col). row=y (строка), col=x (столбец)""" # """Находит путь от start=(row, col) к goal=(row, col). row=y (строка), col=x (столбец)"""
# rows = len(cells) # rows = len(cells)
@@ -289,8 +295,9 @@ def path_exists(data, path):
# #
# return path # return path
'''
def find_way(cells, start, goal): def bfs_quick(cells, start, goal, walkable, rocks_only):
"""★СУПЕРБЫСТРЫЙ BFS: массивы вместо set/deque★""" """★СУПЕРБЫСТРЫЙ BFS: массивы вместо set/deque★"""
rows = len(cells) rows = len(cells)
if rows == 0: if rows == 0:
@@ -303,22 +310,22 @@ def find_way(cells, start, goal):
if (s_row >= rows or s_col >= cols or if (s_row >= rows or s_col >= cols or
g_row >= rows or g_col >= cols): g_row >= rows or g_col >= cols):
print(f"Путь не найден: выход за границы {start} -> {goal}") #print(f"Путь не найден: выход за границы {start} -> {goal}")
return None return None
# ★ МАТРИЦЫ вместо set (10x быстрее хэширования) ★ ## ★ МАТРИЦЫ вместо set (10x быстрее хэширования) ★
walkable = [[True] * cols for _ in range(rows)] #walkable = [[True] * cols for _ in range(rows)]
rocks_only = [[False] * cols for _ in range(rows)] #rocks_only = [[False] * cols for _ in range(rows)]
start_creature = cells[s_row][s_col].creature_obj #start_creature = cells[s_row][s_col].creature_obj
#
for r in range(rows): #for r in range(rows):
for c in range(cols): # for c in range(cols):
cell = cells[r][c] # cell = cells[r][c]
if (cell.creature_obj and cell.creature_obj != start_creature) or \ # if (cell.creature_obj and cell.creature_obj != start_creature) or \
(cell.terrain_obj and cell.terrain_obj.sprite_name == "rock_small"): # (cell.terrain_obj and cell.terrain_obj.sprite_name == "rock_small"):
walkable[r][c] = False # walkable[r][c] = False
if cell.terrain_obj and cell.terrain_obj.sprite_name == "rock_small": # if cell.terrain_obj and cell.terrain_obj.sprite_name == "rock_small":
rocks_only[r][c] = True # rocks_only[r][c] = True
# ★ ВЫЧИСЛЯЕМЫЕ МАССИВЫ ★ # ★ ВЫЧИСЛЯЕМЫЕ МАССИВЫ ★
visited = [[False] * cols for _ in range(rows)] visited = [[False] * cols for _ in range(rows)]
@@ -380,4 +387,191 @@ def can_move_diagonal(r, c, nr, nc, rocks_only, rows, cols):
check1_ok = (0 <= r1 < rows and 0 <= c1 < cols and not rocks_only[r1][c1]) 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]) check2_ok = (0 <= r2 < rows and 0 <= c2 < cols and not rocks_only[r2][c2])
return check1_ok and check2_ok return check1_ok and check2_ok
'''
#def bfs_quick_d(obstacle_matrix, start, goal):
# rows = len(obstacle_matrix)
# if rows == 0:
# print("❌ DEBUG: ПУСТАЯ МАТРИЦА")
# return None
#
# cols = len(obstacle_matrix[0])
# s_row, s_col = start
# g_row, g_col = goal
#
# print(f"🔍 DEBUG: start={start}, goal={goal}, размер={rows}x{cols}")
#
# if (s_row >= rows or s_col >= cols or
# g_row >= rows or g_col >= cols):
# print(f"❌ DEBUG: ВЫХОД ЗА ГРАНИЦЫ: start({s_row},{s_col}) goal({g_row},{g_col})")
# return None
#
# print(f"✅ DEBUG: Границы OK. obstacle[start]={obstacle_matrix[s_row][s_col]}, obstacle[goal]={obstacle_matrix[g_row][g_col]}")
#
# visited = [[False] * cols for _ in range(rows)]
# parent = [[None] * cols for _ in range(rows)]
#
# 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
# print(f"✅ DEBUG: Старт добавлен в очередь. queue_size={queue_size}")
#
# directions = [(-1,0), (1,0), (0,-1), (0,1), (-1,-1), (-1,1), (1,-1), (1,1)]
#
# DEBUG_COUNTER = 0
#
# while front < queue_size:
# r, c = queue[front]
# front += 1
# DEBUG_COUNTER += 1
#
# print(f"🔄 DEBUG[{DEBUG_COUNTER}]: обрабатываем ({r},{c}), очередь={front}/{queue_size}")
#
# if r == g_row and c == g_col:
# print(f"✅ DEBUG: НАЙДЕН ЦЕЛЬ! Путь: ({r},{c})")
# path = []
# 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 = r + dr, c + dc
#
# print(f" 📍 Проверяем соседа ({nr},{nc}): граница={0<=nr<rows and 0<=nc<cols}, "
# f"visited={visited[nr][nc]}, obstacle={obstacle_matrix[nr][nc]}")
#
# if (0 <= nr < rows and 0 <= nc < cols and
# not visited[nr][nc] and
# not obstacle_matrix[nr][nc]):
#
# diagonal_ok = True
# if dr * dc != 0:
# diagonal_ok = can_move_diagonal(r, c, nr, nc, obstacle_matrix)
# print(f" ↘️ Диагональ: {diagonal_ok}")
#
# if diagonal_ok:
# visited[nr][nc] = True
# parent[nr][nc] = (r, c)
# queue[queue_size] = [nr, nc]
# queue_size += 1
# print(f" ✅ Добавили ({nr},{nc}) в очередь. queue_size={queue_size}")
# else:
# print(f" ❌ Диагональ заблокирована!")
# else:
# print(f" ❌ Сосед отклонен!")
#
# print(f"❌ DEBUG: ОЧЕРЕДЬ ОПУСТЕЛА! Обработано {DEBUG_COUNTER} узлов")
# print(f" Последняя клетка в очереди: {queue[front-1] if front > 0 else 'ПУСТО'}")
# print(f" Цель ({g_row},{g_col}) помечена как visited? {visited[g_row][g_col]}")
# return None
#
#
#def bfs_quick(obstacle_matrix, start, goal):
# """★СУПЕРБЫСТРЫЙ BFS 8-направлений★
# obstacle_matrix - ТОЛЬКО камни
# """
# rows = len(obstacle_matrix)
# if rows == 0:
# return None
#
# cols = len(obstacle_matrix[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):
# return None
#
# # ★ МАТРИЦЫ состояния ★
# visited = [[False] * cols for _ in range(rows)]
# parent = [[None] * cols for _ in range(rows)]
#
# # ★ БЫСТРАЯ ОЧЕРЕДЬ ★
# 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
#
# # ★ 8 НАПРАВЛЕНИЙ ★
# 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
#
# if r == g_row and c == g_col:
# # ★ Реконструкция пути ★
# path = []
# 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 = r + dr, c + dc
#
# if not (0 <= nr < rows and 0 <= nc < cols):
# continue
# if visited[nr][nc] or obstacle_matrix[nr][nc]:
# continue
#
# diagonal_ok = True
# if dr * dc != 0:
# diagonal_ok = can_move_diagonal(r, c, nr, nc, obstacle_matrix)
# if diagonal_ok:
# visited[nr][nc] = True
# parent[nr][nc] = (r, c)
# queue[queue_size] = [nr, nc]
# queue_size += 1
#
# return None
'''
#def can_move_diagonal(r, c, nr, nc, obstacle_matrix):
# """Диагональ БЛОКИРУЕТСЯ только камнями по углам"""
# rows, cols = len(obstacle_matrix), len(obstacle_matrix[0])
# 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 obstacle_matrix[r1][c1])
# check2_ok = (0 <= r2 < rows and 0 <= c2 < cols and not obstacle_matrix[r2][c2])
#
# return check1_ok and check2_ok
#def can_move_diagonal(r, c, nr, nc, obstacle_matrix):
# """Проверка диагонали с границами"""
# rows, cols = len(obstacle_matrix), len(obstacle_matrix[0])
# dr = nr - r
# dc = nc - c
#
# # ★ ПРОВЕРКА ГРАНИЦ ПОПЕРЕДУ ★
# r1, c1 = r + dr, c # вертикальная
# r2, c2 = r, c + dc # горизонтальная
#
# # Если УЖЕ за границей - False
# if not (0 <= r1 < rows and 0 <= c1 < cols):
# return False
# if not (0 <= r2 < rows and 0 <= c2 < cols):
# return False
#
# return not obstacle_matrix[r1][c1] and not obstacle_matrix[r2][c2]

View File

@@ -11,7 +11,9 @@
"name": "2", "name": "2",
"sprite_name": "sword_default" "sprite_name": "sword_default"
}, },
"creature_obj": {} "creature_obj": {"id": "1",
"name": "2",
"sprite_name": "elf_watching"}
}, },
{ {
"terrain_obj": { "terrain_obj": {
@@ -20,7 +22,9 @@
"sprite_name": "grass_small" "sprite_name": "grass_small"
}, },
"item_obj": {}, "item_obj": {},
"creature_obj": {} "creature_obj": {"id": "1",
"name": "2",
"sprite_name": "elf_watching"}
}, },
{ {
"terrain_obj": { "terrain_obj": {

View File

@@ -38,6 +38,8 @@ class Map:
sprites: dict sprites: dict
sprites_refresh: int = 60 sprites_refresh: int = 60
cells: dict = field(default_factory = dict) cells: dict = field(default_factory = dict)
walkable_matrix: list = field(default_factory = list)
rocks_matrix: list = field(default_factory = list)
color: str = "gray57" color: str = "gray57"
target_color: str = "gold" target_color: str = "gold"
cell_size: int = 150 cell_size: int = 150
@@ -66,7 +68,16 @@ class Map:
final_cell.creature_obj = cell_classes[cell["creature_obj"]["sprite_name"]](**cell["creature_obj"]) final_cell.creature_obj = cell_classes[cell["creature_obj"]["sprite_name"]](**cell["creature_obj"])
final_cell.creature_obj.grid_pos = (line, col) final_cell.creature_obj.grid_pos = (line, col)
self.cells[line].append(final_cell) self.cells[line].append(final_cell)
self.compute_walkable_rocks()
for j in range(len(self.cells)):
for cell in self.cells[j]:
if cell.creature_obj:
cell.creature_obj.walkable_matrix = self.walkable_matrix
cell.creature_obj.rocks_matrix = self.rocks_matrix
def move_obj(self, type, start, goal): def move_obj(self, type, start, goal):
"""Перемещает объект типа 'terrain_obj', 'item_obj' или 'creature_obj' """Перемещает объект типа 'terrain_obj', 'item_obj' или 'creature_obj'
@@ -114,10 +125,36 @@ class Map:
return (row, col) return (row, col)
def update_map(self, time_delta): def update_map(self, time_delta):
self.compute_walkable_rocks()
for j in range(len(self.cells)): for j in range(len(self.cells)):
for cell in self.cells[j]: for cell in self.cells[j]:
if cell.creature_obj: if cell.creature_obj:
cell.creature_obj.update(time_delta, self.cell_size, self) # self! cell.creature_obj.update(time_delta, self.cell_size, self)
def compute_walkable_rocks(self):
"""Вычисляет матрицы walkable и rocks_only БЕЗ учета стартовой позиции"""
rows = len(self.cells)
if rows == 0:
return None, None
cols = len(self.cells[0])
# ★ ИНИЦИАЛИЗАЦИЯ ★
self.walkable_matrix = [[True] * cols for _ in range(rows)]
self.rocks_matrix = [[False] * cols for _ in range(rows)]
# ★ ПОЛНЫЙ ПРОХОД ПО КАРТЕ
for r in range(rows):
for c in range(cols):
cell = self.cells[r][c]
# Запрещаем ВСЕ существа (включая стартовое!)
if cell.creature_obj or \
(cell.terrain_obj and cell.terrain_obj.sprite_name == "rock_small"):
self.walkable_matrix[r][c] = False
# Отмечаем маленькие камни
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): # def draw_map(self, screen, current_frame, grid=True):
# terrain_list = [] # terrain_list = []
@@ -168,7 +205,6 @@ class Map:
# color = self.target_color if cell.is_target else self.color # color = self.target_color if cell.is_target else self.color
# pygame.draw.rect(screen, color, grid_rect, self.bord) # pygame.draw.rect(screen, color, grid_rect, self.bord)
def draw_map(self, screen, current_frame, grid=True): def draw_map(self, screen, current_frame, grid=True):
screen_rect = screen.get_rect() screen_rect = screen.get_rect()
terrain_list = [] terrain_list = []
@@ -238,9 +274,6 @@ class Map:
pygame.draw.rect(screen, color, grid_rect, self.bord) pygame.draw.rect(screen, color, grid_rect, self.bord)
@dataclass @dataclass
class Engine: class Engine:
sprites: dict = field(default_factory = dict) sprites: dict = field(default_factory = dict)
@@ -328,14 +361,6 @@ class Engine:
def main_loop(self): def main_loop(self):
easy_map = Map("def_map.json", self.cached_sprites) easy_map = Map("def_map.json", self.cached_sprites)
#print(easy_map.find_way((1, 1), (5, 5)))
#print(easy_map.find_way((0, 0), (1, 1)))
#print(easy_map.find_way((0, 0), (0, 1)))
#print(easy_map.find_way((0, 0), (0, 0)))
#sp = eb_objects.Sprite(self.sprites, "elf_watching")
#gr = pygame.image.load(file_path).convert_alpha()
background = pygame.Surface((1600, 800)) background = pygame.Surface((1600, 800))
background.fill("chartreuse4") background.fill("chartreuse4")
@@ -380,7 +405,12 @@ class Engine:
col < len(easy_map.cells[row]) and col < len(easy_map.cells[row]) and
easy_map.cells[row][col].creature_obj is None): easy_map.cells[row][col].creature_obj is None):
elf = eb_objects.Creature(id=f"elf_{random.randint(1000,9999)}", name="Elf", sprite_name="elf_watching", grid_pos = pos) elf = eb_objects.Creature(id=f"elf_{random.randint(1000,9999)}",
name="Elf", sprite_name="elf_watching",
grid_pos = pos,
walkable_matrix = easy_map.walkable_matrix,
rocks_matrix = easy_map.rocks_matrix)
r_move_short = eb_objects.Action(sprite_name="elf_watching", func=partial(elf.patrol, easy_map.cells, 3), duration=0.01) r_move_short = eb_objects.Action(sprite_name="elf_watching", func=partial(elf.patrol, easy_map.cells, 3), duration=0.01)
r_move_long = eb_objects.Action(sprite_name="elf_watching", func=partial(elf.move_rand, easy_map.cells, 0, 99), duration=0.01) r_move_long = eb_objects.Action(sprite_name="elf_watching", func=partial(elf.move_rand, easy_map.cells, 0, 99), duration=0.01)
elf.tasks.append([r_move_short]*5 + [r_move_long]) elf.tasks.append([r_move_short]*5 + [r_move_long])
@@ -514,8 +544,7 @@ class Engine:
cell_coords = easy_map.get_cell_at_mouse(mouse_pos) cell_coords = easy_map.get_cell_at_mouse(mouse_pos)
if cell_coords: if cell_coords:
#print(f"Движение: {active_cell} -> {cell_coords}") #print(f"Движение: {active_cell} -> {cell_coords}")
easy_map.cells[active_cell[0]][active_cell[1]].creature_obj.move( easy_map.cells[active_cell[0]][active_cell[1]].creature_obj.move(easy_map.cells, cell_coords)
easy_map.cells, cell_coords)
if keys[pygame.K_ESCAPE]: if keys[pygame.K_ESCAPE]:
running = False running = False

View File

@@ -59,6 +59,8 @@ class Creature(Object):
replan_counter: int = 0 replan_counter: int = 0
REPLAN_INTERVAL: int = 30000 REPLAN_INTERVAL: int = 30000
waypoints: list = field(default_factory = list) waypoints: list = field(default_factory = list)
walkable_matrix: list = field(default_factory = list)
rocks_matrix: list = field(default_factory = list)
inventory: dict = field(default_factory = dict) inventory: dict = field(default_factory = dict)
quick_actions: list = field(default_factory = list) quick_actions: list = field(default_factory = list)
@@ -76,7 +78,7 @@ class Creature(Object):
def replan(self, cells, pos): def replan(self, cells, pos):
from common import find_way from common import find_way
path = find_way(cells, pos, self.final_goal) path = find_way(cells, pos, self.final_goal, self.walkable_matrix, self.rocks_matrix)
if path and len(path) > 1: if path and len(path) > 1:
self.waypoints = path[1:] self.waypoints = path[1:]
self.current_target = self.waypoints[0] self.current_target = self.waypoints[0]
@@ -97,25 +99,37 @@ class Creature(Object):
if self.current_target is None: return if self.current_target is None: return
target_row, target_col = self.current_target
if (target_row in map_obj.cells and #target_row, target_col = self.current_target
target_col < len(map_obj.cells[target_row])): #if (target_row in map_obj.cells and
target_cell = map_obj.cells[target_row][target_col] # target_col < len(map_obj.cells[target_row])):
if target_cell.creature_obj is not None: # target_cell = map_obj.cells[target_row][target_col]
self.current_target = None #if target_cell.creature_obj is not None:
self.waypoints.clear() # self.current_target = None
self.render_offset = (0.0, 0.0) # self.waypoints.clear()
self.replan(map_obj.cells, self.start_pos) # self.render_offset = (0.0, 0.0)
return # self.replan(map_obj.cells, self.start_pos)
# return
self.move_progress += self.move_speed * time_delta * 60 self.move_progress += self.move_speed * time_delta * 60
self.move_progress = min(self.move_progress, 1.0) self.move_progress = min(self.move_progress, 1.0)
if self.move_progress >= 1.0: if self.move_progress >= 1.0:
map_obj.move_obj('creature_obj', self.start_pos, self.current_target) if (map_obj.move_obj('creature_obj', self.start_pos, self.current_target)):
self.grid_pos = self.current_target self.grid_pos = self.current_target
else:
self.current_target = None
self.waypoints.clear()
self.render_offset = (0.0, 0.0)
#если в матрице не считаем объекты, то:
#добавляем клетку в матрицу, матрицу периодически чистим
#посчитать как дорого обходится просчёт матрицы
self.replan(map_obj.cells, self.start_pos)
#тут сделать красивый переход в одну из соседних клеток
return
if self.waypoints: self.waypoints.pop(0) if self.waypoints: self.waypoints.pop(0)
if self.waypoints: if self.waypoints:
self.start_pos = self.current_target self.start_pos = self.current_target
self.current_target = self.waypoints[0] self.current_target = self.waypoints[0]
@@ -141,7 +155,7 @@ class Creature(Object):
def move(self, cells, goal): def move(self, cells, goal):
from common import find_way from common import find_way
self.final_goal = goal self.final_goal = goal
path = find_way(cells, self.grid_pos, goal) path = find_way(cells, self.grid_pos, self.final_goal, self.walkable_matrix, self.rocks_matrix)
if path and len(path) > 1: if path and len(path) > 1:
self.waypoints = path[1:] self.waypoints = path[1:]
self.current_target = self.waypoints[0] self.current_target = self.waypoints[0]
@@ -171,6 +185,9 @@ class Creature(Object):
#clear goal/wp #clear goal/wp
def update(self, time_delta, cell_size, map_obj): def update(self, time_delta, cell_size, map_obj):
self.walkable_matrix = map_obj.walkable_matrix
self.rocks_matrix = map_obj.rocks_matrix
#quick_actions? here? #quick_actions? here?
#print(self.waypoints, self.final_goal, self.action_counter, self.task_counter) #print(self.waypoints, self.final_goal, self.action_counter, self.task_counter)
if self.final_goal is not None: if self.final_goal is not None:

231
f.txt Normal file
View File

@@ -0,0 +1,231 @@
Elves count: 500 - Current FPS: 58.82
Elves count: 500 - Current FPS: 54.35
Elves count: 500 - Current FPS: 57.14
Elves count: 500 - Current FPS: 55.56
Elves count: 500 - Current FPS: 58.14
Elves count: 500 - Current FPS: 54.95
Elves count: 500 - Current FPS: 61.35
Elves count: 500 - Current FPS: 58.14
Elves count: 500 - Current FPS: 61.73
Elves count: 500 - Current FPS: 45.87
Elves count: 500 - Current FPS: 54.35
Elves count: 500 - Current FPS: 58.48
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 58.48
Elves count: 500 - Current FPS: 50.51
Elves count: 500 - Current FPS: 55.25
Elves count: 500 - Current FPS: 52.36
Elves count: 500 - Current FPS: 53.76
Elves count: 500 - Current FPS: 52.36
Elves count: 500 - Current FPS: 49.02
Elves count: 500 - Current FPS: 61.73
Elves count: 500 - Current FPS: 57.80
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 54.64
Elves count: 500 - Current FPS: 54.95
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 60.24
Elves count: 500 - Current FPS: 61.73
Elves count: 500 - Current FPS: 44.05
Elves count: 500 - Current FPS: 58.82
Elves count: 500 - Current FPS: 54.05
Elves count: 500 - Current FPS: 55.56
Elves count: 500 - Current FPS: 58.82
Elves count: 500 - Current FPS: 49.50
Elves count: 500 - Current FPS: 56.18
Elves count: 500 - Current FPS: 58.82
Elves count: 500 - Current FPS: 57.47
Elves count: 500 - Current FPS: 34.13
Elves count: 500 - Current FPS: 48.54
Elves count: 500 - Current FPS: 54.64
Elves count: 500 - Current FPS: 60.24
Elves count: 500 - Current FPS: 57.14
Elves count: 500 - Current FPS: 56.50
Elves count: 500 - Current FPS: 50.00
Elves count: 500 - Current FPS: 60.98
Elves count: 500 - Current FPS: 59.88
Elves count: 500 - Current FPS: 58.82
Elves count: 500 - Current FPS: 43.10
Leak: 2232.0 KB per 1000 frames
Elves count: 500 - Current FPS: 50.25
Elves count: 500 - Current FPS: 41.67
Elves count: 500 - Current FPS: 57.80
Elves count: 500 - Current FPS: 45.25
Elves count: 500 - Current FPS: 49.50
Elves count: 500 - Current FPS: 58.48
Elves count: 500 - Current FPS: 56.18
Elves count: 500 - Current FPS: 52.63
Elves count: 500 - Current FPS: 49.02
Elves count: 500 - Current FPS: 57.47
Elves count: 500 - Current FPS: 55.56
Elves count: 500 - Current FPS: 56.18
Elves count: 500 - Current FPS: 55.56
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 60.24
Elves count: 500 - Current FPS: 57.47
Elves count: 500 - Current FPS: 60.61
Elves count: 500 - Current FPS: 60.61
Elves count: 500 - Current FPS: 46.30
Elves count: 500 - Current FPS: 58.82
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 54.35
Elves count: 500 - Current FPS: 59.17
Elves count: 500 - Current FPS: 54.95
Elves count: 500 - Current FPS: 54.64
Elves count: 500 - Current FPS: 48.08
Elves count: 500 - Current FPS: 41.49
Elves count: 500 - Current FPS: 54.35
Elves count: 500 - Current FPS: 56.50
Elves count: 500 - Current FPS: 60.24
Elves count: 500 - Current FPS: 61.35
Elves count: 500 - Current FPS: 59.17
Elves count: 500 - Current FPS: 50.25
Elves count: 500 - Current FPS: 60.98
Elves count: 500 - Current FPS: 52.63
Elves count: 500 - Current FPS: 57.80
Elves count: 500 - Current FPS: 54.05
Elves count: 500 - Current FPS: 51.28
Elves count: 500 - Current FPS: 52.08
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 61.73
Elves count: 500 - Current FPS: 54.05
Elves count: 500 - Current FPS: 59.17
Elves count: 500 - Current FPS: 54.64
Elves count: 500 - Current FPS: 50.51
Elves count: 500 - Current FPS: 51.28
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 60.61
Elves count: 500 - Current FPS: 51.28
Elves count: 500 - Current FPS: 60.98
Elves count: 500 - Current FPS: 57.47
Elves count: 500 - Current FPS: 52.63
Elves count: 500 - Current FPS: 50.00
Elves count: 500 - Current FPS: 59.88
Elves count: 500 - Current FPS: 54.95
Elves count: 500 - Current FPS: 58.14
Elves count: 500 - Current FPS: 45.45
Elves count: 500 - Current FPS: 52.91
Elves count: 500 - Current FPS: 32.57
Elves count: 500 - Current FPS: 29.07
Elves count: 500 - Current FPS: 45.25
Elves count: 500 - Current FPS: 30.03
Elves count: 500 - Current FPS: 45.66
Elves count: 500 - Current FPS: 43.86
Elves count: 500 - Current FPS: 38.91
Elves count: 500 - Current FPS: 35.97
Elves count: 500 - Current FPS: 34.01
Elves count: 500 - Current FPS: 44.84
Elves count: 500 - Current FPS: 36.63
Elves count: 500 - Current FPS: 39.84
Elves count: 500 - Current FPS: 42.55
Elves count: 500 - Current FPS: 31.65
Elves count: 500 - Current FPS: 30.96
Elves count: 500 - Current FPS: 37.59
Elves count: 500 - Current FPS: 39.53
Elves count: 500 - Current FPS: 45.87
Elves count: 500 - Current FPS: 37.31
Elves count: 500 - Current FPS: 35.34
Elves count: 500 - Current FPS: 39.22
Elves count: 500 - Current FPS: 47.17
Elves count: 500 - Current FPS: 39.37
Elves count: 500 - Current FPS: 25.25
Elves count: 500 - Current FPS: 35.97
Elves count: 500 - Current FPS: 48.54
Elves count: 500 - Current FPS: 44.64
Elves count: 500 - Current FPS: 43.67
Elves count: 500 - Current FPS: 28.17
Elves count: 500 - Current FPS: 35.97
Elves count: 500 - Current FPS: 31.06
Elves count: 500 - Current FPS: 47.62
Elves count: 500 - Current FPS: 37.59
Elves count: 500 - Current FPS: 42.19
Elves count: 500 - Current FPS: 50.25
Elves count: 500 - Current FPS: 35.59
Elves count: 500 - Current FPS: 45.45
Elves count: 500 - Current FPS: 45.45
Elves count: 500 - Current FPS: 28.65
Elves count: 500 - Current FPS: 24.15
Elves count: 500 - Current FPS: 42.55
Leak: 3284.0 KB per 1000 frames
Elves count: 500 - Current FPS: 42.19
Elves count: 500 - Current FPS: 35.09
Elves count: 500 - Current FPS: 42.19
Elves count: 500 - Current FPS: 51.55
Elves count: 500 - Current FPS: 32.36
Elves count: 500 - Current FPS: 39.22
Elves count: 500 - Current FPS: 35.59
Elves count: 500 - Current FPS: 28.57
Elves count: 500 - Current FPS: 22.73
Elves count: 500 - Current FPS: 31.85
Elves count: 500 - Current FPS: 26.74
Elves count: 500 - Current FPS: 24.94
Elves count: 500 - Current FPS: 22.08
Elves count: 500 - Current FPS: 24.51
Elves count: 500 - Current FPS: 34.97
Elves count: 500 - Current FPS: 30.40
Elves count: 500 - Current FPS: 47.62
Elves count: 500 - Current FPS: 40.16
Elves count: 500 - Current FPS: 55.87
Elves count: 500 - Current FPS: 33.78
Elves count: 500 - Current FPS: 50.00
Elves count: 500 - Current FPS: 50.51
Elves count: 500 - Current FPS: 33.00
Elves count: 500 - Current FPS: 54.64
Elves count: 500 - Current FPS: 61.35
Elves count: 500 - Current FPS: 51.02
Elves count: 500 - Current FPS: 54.35
Elves count: 500 - Current FPS: 50.51
Elves count: 500 - Current FPS: 53.19
Elves count: 500 - Current FPS: 53.76
Elves count: 500 - Current FPS: 39.37
Elves count: 500 - Current FPS: 49.50
Elves count: 500 - Current FPS: 60.24
Elves count: 500 - Current FPS: 47.17
Elves count: 500 - Current FPS: 54.64
Elves count: 500 - Current FPS: 60.61
Elves count: 500 - Current FPS: 56.50
Elves count: 500 - Current FPS: 58.48
Elves count: 500 - Current FPS: 58.82
Elves count: 500 - Current FPS: 52.36
Elves count: 500 - Current FPS: 57.47
Elves count: 500 - Current FPS: 61.73
Elves count: 500 - Current FPS: 60.61
Elves count: 500 - Current FPS: 39.06
Elves count: 500 - Current FPS: 51.55
Elves count: 500 - Current FPS: 56.82
Elves count: 500 - Current FPS: 59.52
Elves count: 500 - Current FPS: 54.64
Elves count: 500 - Current FPS: 54.95
Elves count: 500 - Current FPS: 56.50
Elves count: 500 - Current FPS: 52.63
Elves count: 500 - Current FPS: 59.17
Elves count: 500 - Current FPS: 55.56
Elves count: 500 - Current FPS: 58.82
Elves count: 500 - Current FPS: 55.87
Elves count: 500 - Current FPS: 48.08
Elves count: 500 - Current FPS: 60.24
Elves count: 500 - Current FPS: 51.55
Elves count: 500 - Current FPS: 58.14
Elves count: 500 - Current FPS: 57.14
Elves count: 500 - Current FPS: 47.85
Elves count: 500 - Current FPS: 50.00
Elves count: 500 - Current FPS: 47.62
Elves count: 500 - Current FPS: 56.18
Elves count: 500 - Current FPS: 55.56
Elves count: 500 - Current FPS: 53.48
Elves count: 500 - Current FPS: 52.91
Elves count: 500 - Current FPS: 60.98
Elves count: 500 - Current FPS: 57.14
Elves count: 500 - Current FPS: 34.60
Elves count: 500 - Current FPS: 41.84
Elves count: 500 - Current FPS: 59.88
Elves count: 500 - Current FPS: 49.75
Elves count: 500 - Current FPS: 47.62
Elves count: 500 - Current FPS: 50.51
Elves count: 500 - Current FPS: 35.97
Elves count: 500 - Current FPS: 57.47
Elves count: 500 - Current FPS: 55.56
Elves count: 500 - Current FPS: 45.25
Elves count: 500 - Current FPS: 35.59

View File

@@ -19,4 +19,8 @@
- сделать фундамент для MapManager, пока не развивать, но надо исходить из того - сделать фундамент для MapManager, пока не развивать, но надо исходить из того
что одновременно может рендериться несколько карт; что одновременно может рендериться несколько карт;
3. Оптимизация. 3. Оптимизация.
- проверяем, есть ли объект в клетке только перед непосредственным перемещением в ячейку
Cells, а не каждый calc_step; + (исправить визуальный баг, см комменты calc_step)
- перестаём учитывать объекты в алгоритме поиска пути; - (попробовать ещё раз, подумать)
- заранее передаем в алгоритм карту препятствий; +