무게감의 정체 — 아케이드 이동과 점프
물리 엔진을 뺐으니 이동도 점프도 순수 함수로 직접 짰다.
핵심 발상은 플레이어 위치를 터널 단면의 극좌표로 표현하는 것이다.
각도(터널 둘레를 도는 위치)와 높이(벽 표면에서 중심 쪽으로 띄운 거리), 이 둘이면 충분했다.

왜 엔진을 안 썼나
물리 엔진을 붙이면 번들이 커지는 것도 있지만, 더 큰 이유는 결정성이었다.
이 게임엔 매일 모두에게 같은 지형이 열리는 데일리 런이 있는데, 엔진의 내부 적분이나 부동소수 누적에 결과가 좌우되면 "같은 맵"을 보장하기 어려워진다.
필요한 건 사실적인 충돌 응답이 아니라 예측 가능한 손맛이었고, 그건 함수 몇 개로 충분했다.
극좌표를 고른 것도 같은 맥락이다.
터널은 실제로는 좌우로 휘지만, 게임 로직은 그 곡선을 아예 모른다.
각도와 높이로만 계산하니 굴이 어떻게 휘든 이동·충돌 수식은 그대로다.
곡선은 화면에 그릴 때만 얹는다.
무게감은 감쇠에서 나온다
좌우 이동에서 손맛은 즉발이 아닌 데서 나온다.
구버전은 키를 누르면 각도가 휙 바뀌었다.
이번엔 키 입력이 각가속도를 주고, 키를 떼면 각속도가 감쇠로 서서히 줄어든다.
그래서 키를 떼도 토끼가 곧장 멈추지 않고 미끄러진다.
이 "안 멈추는 한 박자"가 바로 무게감의 정체다.
값은 각가속도 14rad/s², 감쇠 계수 7, 최대 각속도 3.2rad/s로 잡았다.
감쇠 7은 시정수로 치면 약 0.14초라, 키를 떼고 그 정도 시간 동안 속도가 눈에 띄게 남는다.
이 숫자가 작아지면 얼음판처럼 미끄럽고, 커지면 다시 즉발에 가까워진다.
결국 이 하나로 조작감의 성격이 정해졌다.
최대 각속도를 둔 건 벽을 도는 속도가 무한정 붙지 않게 하려는 것이다.
상한이 없으면 오래 누른 만큼 계속 빨라져서, 장애물을 보고 피하는 게 아니라 미리 외워야 하는 게임이 된다.
점프는 인공 중력으로
점프는 인공 중력으로 만들었다.
점프하면 위로 속도를 주고, 매 프레임 중력으로 그 속도를 깎는다.
위로 솟다가 자연스럽게 정점을 찍고 떨어진다.
let { height, radialVel, grounded } = p;
if (input.jump && grounded) { radialVel = PLAYER.JUMP_VELOCITY; grounded = false; }
if (!grounded) {
height += radialVel * dt;
radialVel -= PLAYER.GRAVITY * dt;
if (height <= 0) { height = 0; radialVel = 0; grounded = true; }
}
값은 JUMP_VELOCITY = 9, GRAVITY = 24로 잡았다.
그러면 자연 정점은 v²/2g ≈ 1.69m.
혹시 모를 폭주를 막으려고 상한 클램프(3.2m)를 두긴 했지만 일반 점프에선 안 닿는다.
상한을 3.2m로 잡은 데는 이유가 있다.
트램폴린을 밟으면 점프 속도가 12로 뛰는데, 같은 중력에서 정점이 144/48 = 3.0m다.
클램프가 이보다 낮으면 슈퍼 점프가 천장에 부딪힌 것처럼 잘려버린다.
안전망은 두되 정상 플레이의 최댓값보다는 위에 둬야 한다.
뿌리 장애물의 통과 높이를 1.1m로 잡은 것도 이 숫자들과 맞물려 있다.
일반 점프 정점이 1.69m니 여유가 0.6m쯤 남는데, 이 여유폭이 그대로 "아슬아슬하게 넘었다"는 판정 구간이 된다.
속도는 깊이에 따라 오른다
달리는 속도는 고정이 아니다.
12m/s에서 시작해 1m 내려갈 때마다 0.012씩 붙고, 30m/s에서 멈춘다.
계산해보면 1,500m 지점에서 최고 속도에 닿는다.
이 곡선이 난이도의 뼈대다.
초반은 조작을 익힐 만큼 느리고, 후반은 반응 속도가 한계에 부딪힌다.
장애물 밀도를 건드리지 않아도 속도 하나로 난이도가 올라가니, 밸런스를 잡을 손잡이가 단순해진다.
순수 함수라서 테스트할 수 있다
순수 함수로 짠 데는 이유가 있다.
Three.js에 묶이지 않으니 점프 궤적을 Jest로 그대로 검증할 수 있다.
입력과 dt를 넣고 높이가 솟았다 0으로 돌아오는지 단위 테스트로 확인한다 — 손맛을 눈이 아니라 테스트로 잡는 셈이다.
덕분에 상수를 만질 때 겁이 덜 난다.
중력이나 점프 속도를 바꿔도 "정점이 뿌리 통과 높이보다 높은가", "착지하면 높이가 정확히 0으로 돌아오는가" 같은 게 테스트로 걸린다.
값 하나 고치고 게임을 열 번 돌려보는 대신, 저장하면 답이 나온다.
다음 편은 이 좌표 위에서 부딪힘을 판정하는 충돌 이야기다.