Цикл двойного итератора C для обнаружения столкновений

#c #iterator #collision-detection

#c #итератор #обнаружение столкновений

Вопрос:

Перво-наперво, я совсем новичок в C ! Итак, у меня есть стандартный список объектов, представляющих элементы в 2d-пространстве, и я хочу выполнить базовое обнаружение столкновений. Моя первая идея (исходящая в основном из опыта Java …) состоит в том, чтобы сравнить каждый объект друг с другом, вызывая функцию для проверки пересечения каждой пары или объектов. В Java это было бы просто: взять первый элемент ArrayList, сравнить его со вторым, третьим и т.д. Затем взять второй элемент, сравнить его с третьим, четвертым и т.д. Это подход, который я использовал для решения проблемы в C , но я использую итератор (а не прямой доступ к элементам, как я бы делал в Java), но итераторы предназначены для линейного использования, верно? Таким образом, прямой доступ не подходит.

Итак, мой вопрос в том, как мне выполнить этот алгоритм? Я также обоснованно уверен, что это не лучший способ сделать (очень простой) обнаружение столкновений, поэтому любые советы по этому поводу тоже приветствовались бы. Вот мой (нерабочий) код.

 for (list<Box>::iterator p = mBoxes.begin(); p != mBoxes.end(); p  ) {
    for (list<Box>::iterator q = mBoxes.begin()   p); q != mBoxes.end(); q  ) {
        if (p->isIntersecting(q)) {
            p->changeDirection();
            q->changeDirection();
        }
    }
}
  

Это должно проиллюстрировать метод, который я пытаюсь использовать, но, конечно, моя попытка mBoxes.begin() p не работает!

Комментарии:

1. Просто совет, при работе с итераторами отдавайте предпочтение prefix , а не postfix (с точки зрения производительности), поэтому в вашем цикле это должно быть: q и p

2. Еще одно предложение: если вы хотите использовать индекс вместо interator, рассмотрите std::vector вместо std::list.

Ответ №1:

РЕДАКТИРОВАТЬ: Ответ на несколько комментариев.

 for (list<Box>::iterator p = mBoxes.begin(); p != mBoxes.end();   p) {
    for (list<Box>::iterator q = p); q != mBoxes.end();   q) {
        if (p==q) continue;
        if (p->isIntersecting(*q)) {
            p->changeDirection();
            q->changeDirection();
        }
    }
}
  

Комментарии:

1. Поскольку p и q являются указателями, вы можете сравнить их (например, «if (p == q) continue;», чтобы пропустить сравнение с самим собой)

2. Отлично, имеет смысл. Моя функция isIntersecting () принимает тип Box в качестве аргумента, как мне получить фактический элемент из списка, передавая его q, согласно моему примеру, передает ему итератор

Ответ №2:

Класс list является связанным списком, вы не можете напрямую индексировать в нем. Кроме того, итераторы не являются индексами, просто не имеет никакого смысла.

Однако, теоретически, вы должны иметь возможность скопировать итератор, если вы измените q = mboxes.begin () p на q = p, он должен установить q как итератор, указывающий на то же местоположение p, и это может просто решить вашу проблему.

 for (list<Box>::iterator p = mBoxes.begin(); p != mBoxes.end(); p  ) {
  for (list<Box>::iterator q = p, q  ; q != mBoxes.end(); q  ) {
    if (p->isIntersecting(q)) {
        p->changeDirection();
        q->changeDirection();
    }
  }
}
  

q должен просто пропустить текущий элемент, чтобы вы не сравнивали элемент с самим собой.

Ответ №3:

Что-то вроде этого должно сработать:

 for (int p = 0; p < mBoxes.size();   p)
{
    for (int q = 0; q < mBoxes.size();   q)
    {
        if (p == q)
        {
            // don't compare for collision against itself
            continue;
        }
        if (mBoxes[p]->isIntersecting(mBoxes[q]))
        {
            mBoxes[p]->changeDirection();
            mBoxes[q]->changeDirection();
        }
    }
}
  

Однако одна из проблем заключается в том, что при выполнении итерации вы будете сравнивать p с пересечением q, а также q с пересечением p, что означает, что если они пересекутся, они дважды изменят направление, каждый раз возвращая их в одно и то же направление. Поэтому потребуется некоторая дополнительная логика, чтобы избежать этого.

Комментарии:

1. -1 : int p p->isIntersecting ? Как вы думаете, какого типа p это?

2. Это не сработает, mBoxes — это связанный список элементов Box, вы создали p и q целых чисел, у них нет методов, которые вы вызываете для них, и вы не можете индексировать в mBoxes, потому что связанные списки, хотя и являются итеративными, не индексируются.