2013-04-30 4 views
2

Я искал некоторый псевдокод для boids и написал его на C++. Однако я нахожу, что бои иногда будут сталкиваться друг с другом. Я думал, что я запрограммировал его правильно, учитывая, насколько прост в 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 

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

+0

'int' подписан по умолчанию, поэтому вы можете написать' int' вместо 'signed int', если хотите. –

+1

, что серьезно не полезно – calccrypto

ответ

3

Правило не говорит, что боиды не могут столкнуться. Они просто не хотят. :)

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

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 

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

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

+0

Я думаю, что только я вижу не более 2 boids collide в любой момент времени – calccrypto

+0

Да, но как вы определяете collide? Если вы выполняете арифметику с плавающей запятой, получение того же значения дважды будет очень маловероятным. О, вы используете ints. Игнорируй меня! : D – Sarien

+0

oh. im используя пиксели с целыми значениями. Должен ли я изменить их на поплавки? – calccrypto

2

Далее в статье он имеет следующий код:

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% гарантирует, что столкновения не произойдет, но эти настройки уменьшат вероятность столкновения.

Смежные вопросы