공 튕기기 놀이터베타

공 수천 개를 붓고 튕기고 터뜨리는 물리 놀이

이 도구는 아직 안정화 중인 베타 버전입니다. 결과가 예상과 다르면 알려주세요.

물리 엔진(WebAssembly)을 불러오는 중…

캔버스를 누른 채 움직여 보세요. ‘통 흔들기’ 모드에서는 드래그로 통을 흔들고, Shift+드래그나 휠로 돌릴 수 있습니다.

공 튕기기 놀이터 소개

이 샌드박스의 물체는 모두 원이다. 각 원은 속도를 따로 저장하지 않고 지금 위치와 직전 위치만 가지며(위치 베를레 적분), 한 프레임(1/60초)을 6개의 부분 스텝으로 나눠 움직인다. 부분 스텝마다 중력·공기 저항·포인터 힘으로 위치를 옮기고, 빠른 원은 이동 구간을 훑어 먼저 닿는 원에서 멈추게 한 뒤, 벽 밖으로 나간 원을 튕겨 되돌리고, 겹친 원끼리 밀어내기를 두 번 반복한다.

최대 6000개를 다루려면 모든 쌍을 비교할 수 없다. 화면을 가장 큰 원의 지름만 한 칸으로 나누고, 각 원은 자기 칸과 이웃 칸에 있는 원하고만 겹침을 검사한다(균일 격자 broadphase). 원이 고르게 퍼져 있으면 검사량이 원 개수에 거의 비례한다.

원은 회전하지 않고 표면 마찰도 없다. 그래서 굴러가는 공이나 쌓아 올린 벽돌 같은 강체 게임 엔진의 기능은 여기서 볼 수 없다. 이 도구가 보여 주는 것은 수천 개의 알갱이가 부딪히며 흐르는 모습과, 그것을 싸고 빠르게 계산하는 방법의 장단점이다.

겹침을 밀어내는 방식과 「벽 탄성」 슬라이더

두 원이 겹치면 겹친 깊이만큼 중심을 잇는 방향으로 서로 떼어 놓는다. 질량은 면적(반지름²)에 비례한다고 보고, 가벼운 원이 더 많이 밀린다. 충돌 순간의 속도를 직접 계산하지 않고 위치만 고치는 방식으로, Jakobsen(2001)이 「투영으로 충돌과 관통을 처리한다」고 설명한 방법이다. 위치를 옮긴 양이 그대로 다음 스텝의 속도가 되므로 따로 속도를 맞출 필요가 없다.

그 대가로 원끼리의 충돌은 거의 튀지 않는다. 겹친 만큼만 되돌려 놓으면 두 원의 접근 속도가 사라질 뿐 반대로 튕기는 속도는 생기지 않기 때문이다. 「벽 탄성」 슬라이더(반발계수)는 벽과 바닥에만 적용된다. 0.6이면 벽에 부딪힌 속도의 60%로 되돌아오고, 떨어진 원은 매번 이전 높이의 0.6² = 36%까지 튀어 오른다. 원끼리 부딪히는 모습이 모래나 곡식처럼 둔하게 보이는 것은 이 때문이다.

터널링: 빠른 물체가 벽을 뚫는 이유

충돌을 부분 스텝이 끝날 때 「지금 겹쳐 있는가」로만 판단하면, 한 스텝 사이에 상대를 통째로 지나쳐 버린 물체는 충돌을 놓친다. 이것을 터널링이라 한다. Box2D 같은 엔진은 이전 위치에서 새 위치까지 도형을 쓸어 보는 연속 충돌 검출(CCD)로 막고, 특히 빠른 물체를 「bullet」으로 지정하게 한다.

이 도구는 간단한 CCD(쓸어 보는 원 검사)를 쓴다. 한 부분 스텝(1/360초)에 자기 반지름보다 많이 움직인 원은 직전 위치에서 새 위치까지의 구간 전체를 다른 원과 비교해, 도중에 처음 닿는 원이 있으면 그 접촉 위치에 멈추고 부딪힌 방향의 상대 속도를 질량 비율로 나눠 없앤다(원끼리 충돌처럼 비탄성). 두 원이 모두 반지름 이하로 움직이면 상대 이동이 반지름 합을 넘지 않아 서로를 건너뛸 수 없으므로 검사하지 않는다. 그래서 폭발 세기를 최대로 올려도 원끼리 통과하지 않는다. 벽은 좌표를 잘라 되돌리므로 뚫리지 않는다. 다만 원은 여전히 회전하지 않고 마찰도 없다.

쌓인 더미가 살짝 물렁한 이유

한 쌍을 떼어 놓으면 옆 쌍이 다시 겹치므로, 겹침을 끝까지 풀려면 여러 번 반복해야 한다. 이 도구는 부분 스텝마다 모든 쌍의 겹침 해소를 두 번 반복한다. 반지름 5 px 원 2000개를 좁은 통에 쌓아 보면 가장 깊은 겹침이 한 번만 풀 때 약 10 px(원 지름만큼)에서 1 px 안팎으로 줄어든다. 네 번 반복하면 조금 더 줄지만 원 6000개에서 한 프레임 계산이 약 두 배 더 들어 두 번으로 정했다. 부분 스텝 수를 늘려도 줄어들지만 계산이 그만큼 늘어난다. 게임 엔진이 반복 횟수와 부분 스텝 수를 설정값으로 노출하는 것도 같은 이유다.

원에 마찰이 없어서 더미는 경사를 유지하지 못한다. 실제 모래는 일정한 안식각을 유지하며 쌓이지만, 여기서는 기울이면 물처럼 평평하게 퍼진다.

예시

벽 반발계수 0.6으로 떨어뜨리기

입력
벽 탄성 0.6, 공기 저항 무시, 높이 h에서 낙하
결과
튀어 오른 높이: 0.36h → 0.13h → 0.047h

속도가 매번 0.6배가 되고 높이는 속도의 제곱에 비례하므로 0.36배씩 줄어든다. 공기 저항(기본 0.15/s)이 있으면 조금 더 낮다.

이동 구간을 훑어 검사하는 속도

입력
반지름 3 px 원, 부분 스텝 1/360 s
결과
3 px × 360 = 1080 px/s보다 빠르면 이동 구간 전체를 다른 원과 비교

그보다 느린 원끼리는 한 스텝의 상대 이동이 반지름 합을 넘지 않아 서로를 건너뛸 수 없으므로 끝 위치의 겹침만 본다.

사용 방법

  1. 붓기·끌어당기기·밀어내기·폭발·흔들기 중 하나를 고른다.
  2. 화면을 누르거나 끌어 원을 쏟거나 힘을 가한다.
  3. 중력·벽 탄성·크기·세기·기울기를 바꿔 본다. 휴대폰에서는 기기를 기울여 중력 방향을 바꿀 수 있다.

주요 용어

Broadphase
모든 쌍을 비교하기 전에, 가까이 있을 가능성이 있는 쌍만 골라내는 단계. 여기서는 균일 격자를 쓴다.
터널링
한 시간 스텝 동안 너무 많이 움직여 충돌을 건너뛰는 현상.
반발계수
충돌 후 분리 속도 ÷ 충돌 전 접근 속도. 1이면 에너지 손실 없이 튄다.

자주 묻는 질문

벽 탄성을 1로 해도 원끼리는 잘 안 튀어요.

이름 그대로 벽과 바닥에만 적용된다. 원끼리의 충돌은 겹친 위치만 바로잡는 방식이라 거의 비탄성처럼 동작한다.

빠른 원이 다른 원을 통과하나요?

통과하지 않는다. 한 부분 스텝에 반지름보다 많이 움직이는 원은 이동 구간 전체를 검사해, 처음 닿는 원에서 멈추고 그 원을 밀어낸다. 벽도 좌표를 잘라 되돌리므로 뚫리지 않는다.

원이 많아지면 왜 느려지나요?

격자 덕분에 검사량은 원 개수에 거의 비례하지만, 한곳에 빽빽이 몰리면 한 칸의 원이 많아져 검사가 늘어난다. 최대 6000개다.

출처

기준일:

개인정보와 저장 방식