Боиды сталкиваются друг с другом

Я искал какой-то псевдокод для Boids и написал это на C ++. Тем не менее, я считаю, что boids иногда сталкиваются друг с другом. Я думал, что запрограммировал его правильно, учитывая, насколько прост psuedocode. тем не менее, когда я отображаю местоположение всех boids, некоторые из них имеют одинаковые координаты.

Псевдокод из ссылки:

PROCEDURE rule2(boid bJ)

Vector c = 0;

FOR EACH BOID b
IF b != bJ THEN
IF |b.position - bJ.position| < 100 THEN
c = c - (b.position - bJ.position)
END IF
END IF
END

RETURN c

END PROCEDURE

мой код:

std::pair <signed int, signed int> keep_distance(std::vector <Boid> & boids, Boid & boid){
signed int dx = 0;
signed int dy = 0;
for(Boid & b : boids){
if (boid != b){       // this checks an "id" number, not location
if (b.dist(boid) < MIN_DIST){
dx -= b.get_x() - boid.get_x();
dy -= b.get_y() - boid.get_y();
}
}
}
return std::pair <signed int, signed int> (dx, dy);
}

с

MIN_DIST = 100;

unsigned int Boid::dist(const Boid & b){
return (unsigned int) sqrt((b.x - x) * (b.x - x) + (b.y - y) * (b.y - y));
}

единственное основное различие между этими двумя кодами должно заключаться в том, что вместо vector cЯ использую компоненты вместо.

порядок функций, которые я использую для перемещения каждого boid:

    center_of_mass(boids, new_boids[i]);                      // rule 1
match_velocity(boids, new_boids[i]);                      // rule 3
keep_within_bound(new_boids[i]);
tendency_towards_place(new_boids[i], mouse_x, mouse_y);
keep_distance(boids, new_boids[i]);                       // rule 2

Есть ли что-то очевидное, чего я не вижу? может какая-то глупая векторная арифметика, которую я сделал неправильно?

2

Решение

Правило не говорит, что boids не может столкнуться. Они просто не хотят. 🙂

Как вы можете видеть в этом фрагменте:

    FOR EACH BOID b
v1 = rule1(b)
v2 = rule2(b)
v3 = rule3(b)

b.velocity = b.velocity + v1 + v2 + v3
b.position = b.position + b.velocity
END

Там нет проверки, чтобы убедиться, что они не сталкиваются. Если числа выйдут неблагоприятно, они все равно будут сталкиваться.

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

3

Другие решения

Позже в статье он имеет этот код:

ROCEDURE move_all_boids_to_new_positions()
Vector v1, v2, v3, ...
Integer m1, m2, m3, ...
Boid b
FOR EACH BOID b
v1 = m1 * rule1(b)
v2 = m2 * rule2(b)
v3 = m3 * rule3(b)
b.velocity = b.velocity + v1 + v2 + v3 + ...
b.position = b.position + b.velocity
END
END PROCEDURE

(Хотя реально я бы сделал m1 double а не Integer) Если rule1 это плохо названное правило, которое заставляет boids пытаться избегать друг друга, просто увеличивая значение m1 и они быстрее отвернутся друг от друга. Кроме того, увеличиваяMIN_DIST заставит их заметить, что они скоро столкнутся друг с другом, и уменьшит их максимальную скорость (vlim в функции limit_velocity) позволит им более разумно реагировать на ближние столкновения.

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

2