Избегание вложенных циклов в движке 2D игры - PullRequest
0 голосов
/ 18 мая 2018

Я создаю 2D-игру.

Существует множество objects, каждый из которых имеет ширину, высоту и координаты X и Y.

Каждый объект хранится в array его класса:

  • игрок
  • союзники
  • враги
  • препятствия
  • бонусы
  • пуль, выпущенных врагами
  • пуль, выпущенных игроком и их союзниками

Чтобы игра заработала, мне нужно явно определить, занимают ли два элемента одно и то же пространство (назовемэто «столкновение»), так что

  • игрок может собирать бонусы
  • никто не может пройти через препятствия
  • союзники могут стрелять врагов
  • враги могут стрелять в союзников
  • дружественный огонь можно включить или отключить

это нужно проверять каждый кадр, 60 раз в секунду.

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

FoПример:

foreach (ally_bullets)
{
    foreach (enemies)
    {
        if ( collision detected between enemy and bullet )
        {
            remove the bullet and the enemy
        }
    }
}

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

Что может быть лучше, чем вложенные циклы?

1 Ответ

0 голосов
/ 19 мая 2018

Распространенным решением является использование Полиморфизм , в котором у вас есть базовый класс (в данном случае Object), который наследуется другими классами (такими как Player, Bullet, Enemy и т. Д.).Вместо того, чтобы каждый из них имел отдельный массив, у вас будет один массив (или, как правило, более подходящий, vector ).Теперь вы просто циклически проходите по одному массиву, в котором каждый объект выполняет свои обновления, и их обновления проверяются для каждого объекта в массиве.

Это «векторное» обновление обычно настраивается как Система обмена сообщениями..Теперь всякий раз, когда унаследованный объект получает сообщение (например, «удар по пуле»), этот объект проверяет, заботится ли он об этом сообщении.Если это так, примите сообщение, в противном случае проигнорируйте его.

Это (по моему мнению) лучший способ справиться с тем, что вы пытаетесь достичь, и я считаю, что это то, о чем вы спрашивали.

Если вы все еще используете массивы для этого, я предполагаю, что вы все еще довольно плохо знакомы с программированием, и я собираюсь предложить придерживаться того, что у вас есть сейчас.Он будет абсолютно работать (если вы знаете, как завершить свой проект), и когда вы закончите это и начнете изучать что-то более продвинутое, вы увидите как недостатки того, как вы это делаете, так и преимущества этого).

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

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

Редактировать: Еще одна вещь, которая поможет вам в том, чтобы вы продолжали следовать темам, о которых я говорил, это Шаблон наблюдателя также известный как Pattern Слушателя .

...