발자국은 동그라미가 아니다: AvoidNow 판정 모양을 좌표로 못 박은 시험
억울하게 맞지 않으려면 '공정함'을 느낌이 아니라 좌표로 고정해야 했다. AvoidNow의 발자국·충격파·꼬리 판정 모양을 GDScript와 TypeScript 양쪽에서 똑같이 검사한 기록.
· 5분 읽기
공룡 발자국이 박자에 맞춰 떨어집니다. AvoidNow는 쥬라기 시대 원시인이 되어 거대한 공룡이 찍어 누르는 발을 피하며 최대한 오래 살아남는 웹 피하기 게임입니다. MMORPG 레이드의 "장판"에서 출발했습니다. 바닥에 빨간 발자국이 먼저 그려지고, 그 안이 차오르는 동안 몸을 빼면 됩니다. 한 판은 짧게는 수십 초, 길게는 몇 분이고, 브라우저에서 설치 없이 바로 시작합니다. 혼자서도, 친구와 넷이 협동으로도, 넷이 서로 밀치며 경쟁으로도 할 수 있습니다.
조작은 이동과 대시 두 가지입니다. PC에서는 WASD나 방향키로 여덟 방향을 움직이고, 스페이스로 대시합니다. Esc는 일시정지입니다. 휴대폰에서는 화면 왼쪽을 손가락으로 끌면 가상 조이스틱처럼 움직이고, 오른쪽 아래 대시 버튼을 누릅니다. 폰을 세로로 들면 아레나도 세로로 바뀝니다.
주인공 위협은 거대 공룡의 발입니다. 초식공룡이 아레나를 가로질러 걸어가며 왼발과 오른발을 번갈아 찍고, 35초부터 두 마리, 90초부터 세 마리가 엇갈려 지나갑니다. 4초가 지나면 "나를 노리는 발"이 섞입니다. 이 발은 내 위치를 따라오다가 한 자리에 고정된 뒤 내려찍고, 찍힌 자리에서 둥근 충격파가 퍼집니다. 충격파는 멀리 달아나거나 대시 무적으로 넘어갑니다. 여기에 낙석, 티라노 돌진, 익룡 급강하, 꼬리 휩쓸기, 돌비가 조연으로 가끔 끼어듭니다.
오래 버틸수록 어려워집니다. 다음 공격까지의 간격은 처음 1.3초에서 150초에 걸쳐 0.6초까지 줄고, 걸어가는 공룡은 35초와 90초에 한 마리씩 늘어나며, 경고 시간도 점점 짧아집니다. 걷는 속도는 음악 박자에 맞춰 한 박에 한 걸음으로 고정되어 있습니다. 처음 만든 곡선은 초반이 느슨하다는 평가를 받아서, 원래 40초쯤의 긴장감에서 시작하도록 앞당겼습니다.
배경 음악은 100 BPM, 한 박이 0.6초인 곡입니다. 공룡 발이 바닥에 닿는 순간은 전부 이 박자에 맞춰 밀립니다. 걸어가는 공룡은 한 박에 한 걸음을 딛습니다. 판을 시작할 때 음악을 처음부터 다시 틀기 때문에, 음악을 듣다 보면 "쿵" 하는 순간을 귀로 먼저 알게 됩니다. 20초에서 90초 사이에는 타악기 층이 점점 커지고, 이벤트 구간에서는 가장 크게 울립니다.
점수는 생존 1초에 10점이 기본입니다. 발자국 가장자리 34픽셀 안으로 스치고 살아남으면 "아슬아슬" 50점, 대시 무적으로 장판을 뚫고 지나가면 80점, 공룡 알을 주우면 100점, 가끔 나오는 황금알은 500점입니다. 아슬아슬과 알마다 콤보가 1씩 오르고, 콤보 하나에 배율이 0.25씩 붙어 최대 6배까지 갑니다. 4초 안에 다음 아슬아슬이나 알이 없거나 한 번 맞으면 콤보가 끊깁니다. 알은 일부러 위험한 발자국 옆에 생기기 때문에, 점수를 노릴수록 위험한 자리에 서게 됩니다.
30초마다 2.5초 동안 조용해지며 경고 배너가 뜨고, 이어서 하이라이트 구간이 옵니다. 공룡 떼 행진, 빈 줄 하나만 남기고 달려오는 티라노 떼 돌진, 운석우, 거대 발 연타 네 가지가 순서대로 돌아갑니다. 끝까지 버티면 "버텨냈다!"와 함께 300점을 받습니다.
한 판 안에서 시간이 흐릅니다. 45초에 노을이 지고, 90초에 밤이 되어 반딧불이 날리며, 140초가 되면 바닥이 붉어지고 불티가 날리는 화산 분위기로 바뀝니다. 화면 색만 봐도 지금 얼마나 버텼는지 알 수 있게 한 장치입니다.
멀티플레이는 빠른 매칭이나 4자리 방 코드로 모입니다. 빠른 매칭은 4명이 차거나 15초가 지나면 자동으로 시작하고, 방 만들기는 방장이 시작 버튼을 누릅니다. 시작한 방에는 중간에 들어갈 수 없고, 접속이 끊기면 그 자리에서 탈락합니다.
로그인 없이 닉네임만 적으면 됩니다. 랭킹은 싱글(오늘·이번 주·전체), 오늘의 도전, 협동, 경쟁으로 나뉘고, 일간 기록은 UTC 자정(한국 시간 오전 9시)에 초기화됩니다. 닉네임은 겹쳐도 되지만 비속어는 걸러집니다. 기록은 브라우저가 아니라 게임 서버가 직접 제출한 것만 올라가서, 점수를 조작해 보내는 방법이 통하지 않습니다. 이 밖에 공룡 알을 누적 30개, 100개 모으면 캐릭터의 새 옷 색이 열리고, "2분 버티기", "콤보 10", "황금알 발견" 같은 업적 8개가 있습니다.
캐릭터는 넷입니다. 배불뚝이 곤봉맨 우가, 앞니 빠진 꼬마 꼬미, 수염 할아버지 할배, 갈기머리 언니 불꽃. 능력은 모두 같고 생김새와 대시 동작만 다릅니다. 우가는 배치기로 미끄러지고, 꼬미는 공중제비를 돕니다.
아래 화면은 게임에 들어 있는 자동 플레이 모드로 한 판을 녹화한 것입니다. 시간이 지나며 공룡 수와 분위기가 어떻게 바뀌는지 순서대로 골랐습니다.






AvoidNow는 Godot 4.7로 만들고 웹으로 내보낸 게임입니다. 처음에는 로컬에서만 도는 싱글 플레이 MVP였고, 같은 날 캐릭터 아트, 멀티플레이 서버, 운영 배포까지 이어졌습니다. 게임 규칙은 화면을 모르는 시뮬레이션 코드로 따로 두었고, 같은 규칙을 TypeScript로 한 벌 더 써서 서버가 씁니다. 장판이 언제 어디에 떨어지는지, 누가 맞았는지, 부활과 밀치기는 모두 서버가 판정합니다. 규칙을 바꿀 때는 Godot 쪽과 서버 쪽을 함께 고치고, 판정 테스트도 양쪽에 같은 값으로 둡니다.
서버는 두 곳입니다. 한국 이용자는 서울에 둔 작은 서버로, 해외 이용자는 Cloudflare Durable Objects로 접속합니다. 게임을 켜면 두 서버에 핑을 재서 더 빠른 쪽을 고릅니다. 한국에서 해외 서버로 붙으면 응답이 약 324ms였는데, 서울 서버로 약 14ms가 되었습니다. 월 5달러짜리 서버 한 대에 몇 명이 들어갈 수 있는지는 부하 테스트로 쟀고, 그 과정은 $5짜리 서버 한 대에 몇 명이 들어갈까에 적었습니다.
처음 배포했을 때 첫 로딩이 약 18.5MB였습니다. 엔진에서 쓰지 않는 3D·물리 기능을 빼고 다시 빌드하고, 캐릭터 색 변형을 셰이더로 바꾸고, 음악 비트레이트를 낮춰 약 7MB로 줄였습니다. 첫 로딩 18.5MB를 7MB로 줄인 방법에 단계별로 정리했습니다.
가장 오래 붙잡은 문제는 "억울함"이었습니다. 피하기 게임에서 화면으로는 피했는데 맞았다고 나오면 다시 하지 않습니다. 티라노가 경고 중에 보이지 않다가 화면 밖에서 튀어나오던 문제, 꼬리 판정이 그림보다 길던 문제, 온라인에서 내 입력이 서버에 늦게 닿아 생기던 차이를 하나씩 고친 이야기는 "보이는 곳, 보이는 때에만 맞게"에 있습니다.
원시인과 공룡 그림은 AI 이미지 생성으로 네 가지 화풍을 뽑아 비교한 뒤, 굵은 외곽선의 "인디 게임 카툰"(스타일 C)으로 정했습니다. 그 비교 과정은 원시인과 공룡 아트: 스타일 C 카툰을 고른 과정에서 볼 수 있고, 오래 버티는 요령은 AvoidNow 공략에 모았습니다.
설치 없이 PC와 휴대폰 브라우저에서 바로 합니다. 게임 안에 결제는 없습니다. 두 번째 방문부터는 엔진 파일이 브라우저에 저장되어 있어 훨씬 빨리 열립니다.
판정은 캐릭터 그림 전체가 아니라 발밑의 작은 원으로 봅니다. 몸이 겹쳐 보여도 발이 장판 밖이면 안전하고, 반대로 발이 가장자리에 걸치면 맞습니다. 온라인에서는 내 입력이 서버에 닿는 시간만큼 장판을 늦춰 그려서, 화면에서 피한 것이 서버 판정과 맞도록 맞춰 두었습니다.
서버에 연결되지 않아 오프라인 연습으로 한 판은 랭킹에 올라가지 않습니다. 화면에 "오프라인 연습 중" 문구가 떴는지 확인해 주세요. 일간 랭킹은 한국 시간 오전 9시(UTC 자정)에 새로 시작합니다.
멀티플레이에서 "방 만들기"를 누르면 4자리 방 코드가 나옵니다. 친구가 그 코드를 넣고 참가하면 되고, 방장이 시작 버튼을 누릅니다. 협동과 경쟁 모두 최대 4명입니다. 이미 시작한 방에는 들어갈 수 없습니다.
네 캐릭터의 속도, 대시, 판정은 모두 같습니다. 생김새와 대시 동작만 다르니 마음에 드는 캐릭터를 고르면 됩니다. 공룡 알을 모아 여는 옷 색도 겉모습만 바꿉니다.
설명보다 한 판이 빠릅니다. 빨간 발자국이 차오르면 그 자리를 비우세요. avoidnow.salmonholic.com에서 바로 시작할 수 있습니다.
억울하게 맞지 않으려면 '공정함'을 느낌이 아니라 좌표로 고정해야 했다. AvoidNow의 발자국·충격파·꼬리 판정 모양을 GDScript와 TypeScript 양쪽에서 똑같이 검사한 기록.
· 5분 읽기
AvoidNow 멀티플레이의 JSON 프레임을 바이너리로 바꾼 과정을 정리했다. 플레이어 한 명을 48바이트에 담는 레이아웃, 6바이트 입력, 그리고 GDScript와 TypeScript가 같은 바이트를 읽는지 확인한 방법까지.
· 5분 읽기
피하기 게임에서 가장 나쁜 경험은 피했는데 맞는 것이다. AvoidNow에서 티라노 돌진 예고, 꼬리 판정, 충격파, 온라인 입력 지연을 하나씩 점검해 고친 기록.
· 6분 읽기
월 5달러짜리 서울 서버 한 대로 AvoidNow 멀티플레이를 얼마나 받을 수 있는지 부하 테스트로 쟀다. 1명당 CPU 0.4%, 그리고 버스트 CPU 때문에 오래 버티는 인원은 생각보다 적다는 결론까지.
· 5분 읽기
AvoidNow는 게임 규칙이 Godot(GDScript)과 서버(TypeScript)에 한 벌씩 있다. 두 벌을 어떻게 맞추는지, 서버 두 곳이 한 코드를 어떻게 나눠 쓰는지, 실제로 어긋났던 버그 세 가지를 정리했다.
· 5분 읽기
Salmonholic, AvoidNow, 랜선포차, PallMark가 각각 어떤 서버 위에서 도는지 한 장으로 정리했다. 같은 부품을 골라 쓰면서도 게임마다 구성이 달라진 이유와, 서로 건드리지 않게 정한 분리 규칙을 적었다.
· 5분 읽기