#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, потому что связанные списки, хотя и являются итеративными, не индексируются.