Astral Republic

✱ LABORATORY · 실험

Boids — 송사리 떼는 어떻게 한 몸처럼 움직일까

딱 세 가지 규칙만으로 수백 마리가 살아있는 듯 모이고 흩어진다. 직접 가중치를 만져보자.

🔍 이게 뭐야?

송사리 떼나 새 떼가 마치 한 몸처럼 출렁이며 움직이는 거, 누가 지휘하는 게 아니야. 각자가 주변 이웃만 보고 똑같은 규칙 몇 개를 따를 뿐인데, 전체가 살아있는 듯한 군집이 나온다. 1986년 Craig Reynolds가 이걸 “Boids”로 증명했어.

⚙️ 원리 — 딱 세 규칙

  1. 분리(Separation) — 너무 가까운 이웃과는 살짝 떨어진다. (안 부딪히게)
  2. 정렬(Alignment) — 이웃들이 가는 평균 방향에 내 방향을 맞춘다.
  3. 응집(Cohesion) — 이웃들의 중심 쪽으로 모인다.

이 셋의 가중치 균형만으로 떼의 성격이 완전히 바뀐다.

▶️ 직접 해보기

응집만 키우면 한 덩어리로 뭉치고, 분리를 키우면 흩어진다. 정렬을 0으로 내리면 제각각 — 떼가 아니라 그냥 점들이 된다.

💡 물속을 클릭해봐 — 떡밥을 던지면 잔물결이 일고, 송사리들이 우르르 몰려든다. 다 먹으면 다시 제 갈 길로.

● LIVE DEMO직접 만져보세요

🛠 내 재현

각 송사리가 매 프레임 반경 안 이웃을 훑어 세 힘(분리·정렬·응집)을 더하는 게 전부. 가중치를 슬라이더로 빼내고, 진행 방향으로 회전시킨 뒤 꼬리지느러미를 sin으로 좌우로 흔들어 헤엄치는 느낌을 줬다.

for (const o of neighbors) {
  separation += away(b, o) * sepW;   // 너무 가까우면 밀어내기
  alignment  += o.velocity * aliW;   // 이웃 평균 방향 따라가기
  cohesion   += (center - b.pos) * cohW; // 무리 중심으로 모이기
}
velocity += separation + alignment + cohesion;

떡밥 인터랙션 — 클릭하면 그 자리에 떡밥과 잔물결을 만들고, 모든 송사리에게 그쪽으로 향하는 강한 끌림을 더한다. 가까이 온 녀석이 떡밥을 조금씩 갉아 먹어(life 감소) 결국 사라지면, 끌림이 풀리며 다시 세 규칙만 남아 무리로 흩어진다.

if (food) {
  velocity += toward(food) * 0.5;     // 떡밥으로 몰림
  if (dist(b, food) < 14) food.life -= 3; // 가까운 물고기가 먹어 치움
}

📝 느낀 점

“중앙 통제 없이 규칙만으로 질서가 나온다”가 핵심. 떡밥 하나 던졌을 뿐인데 떼가 우르르 몰렸다 흩어지는 게, 누가 시킨 것도 아닌데 자연스럽다. 정렬 가중치 하나만 0으로 내려도 “떼”라는 느낌이 순식간에 사라지는 것도 인상적. 게임 AI(군중·물고기), 드론 군집, 군중 시뮬레이션이 다 이 사촌이다.