Slomix / ParkourBeat

4 stars 5 forks source link

Оптимизировать алгоритм поиска ближайших частиц так, чтобы время его работы не зависело от длины уровня #17

Open Dymeth opened 8 months ago

DrupalDoesNotExists commented 8 months ago

Самым очевидным решением кажется разделить весь уровень на секции и загружать путь по секциям. Тут в принципе можно даже пренебречь радиальным расстоянием и просто отображать все партиклы в секции разом.

Из плюсов:

  1. Просто и со вкусом
  2. Разбиение на секции можно выполнять при сохранении
  3. Нет никаких дорогих формул вроде квадратных корней к вычислению

Из минусов:

  1. Нужно куда-то сохранять сами секции, возможно придётся незначительно поменять формат хранения путей
Dymeth commented 8 months ago

Самым очевидным решением кажется разделить весь уровень на секции и загружать путь по секциям. Тут в принципе можно даже пренебречь радиальным расстоянием и просто отображать все партиклы в секции разом.

Из плюсов:

  1. Просто и со вкусом
  2. Разбиение на секции можно выполнять при сохранении
  3. Нет никаких дорогих формул вроде квадратных корней к вычислению

Из минусов:

  1. Нужно куда-то сохранять сами секции, возможно придётся незначительно поменять формат хранения путей

Сам тоже думал над реализацией через секции. Но нужно будет отображать не только ту секцию, в которой находится игрок, но и одну из двух соседних - просто по координатам находить ближайшую. Таким образом, даже на краю секции всё будет отображаться корректно.

При этом я бы оставил вычисление ближайших частиц по радиусу, поскольку в двух секциях может быть достаточно большое количество частиц. Текущий алгоритм поиска по радиусу НЕ использует вычисление квадратного корня, поэтому работает относительно производительно: https://github.com/Slomix/ParkourBeat/blob/58bc13a1e9960bc2c2c873deaec189b44794910e/src/main/java/ru/sortix/parkourbeat/levels/ParticleController.java#L138

Что касается загрузки с диска - я не вижу в этом необходимости, поскольку частицы можно довольно легко разделить на секции уже при загрузке уровня с диска, это не должно занять много времени.

Длина секции - это радиус видимости частиц, умноженный на 2 (диаметр).

При этом для игроков длина секции должна составлять 10 блоков, а вот для редакторов карт, скорее всего, в несколько раз больше - допустим, 30 блоков. Из этого вытекает, что у каждого уровня должно быть две разные схемы разделения на секции. Опять же, предлагаю их обе формировать при загрузке уровней в оперативную память