전체 문서 색인은 llms.txt를 참조하세요. 문서 페이지 URL 끝에 .md 를 추가하면 해당 페이지의 Markdown 버전을 볼 수 있습니다.
기본 탐색 메뉴
Theme
Sep 4, 2026 Codex

Astra로 게임 만들기

Codex에서 콘셉트 아트부터 착륙할 수 있는 행성까지 구현해 절차적 우주 탐험 게임을 만든 과정을 소개합니다.

작성자: Thomas Ricouard

Astra로 게임 만들기

이제 Astra는 제가 머릿속에 그린 모습을 게임플레이와 아트 방향에 꽤 잘 담아냅니다. 저는 Codex에서 Astra와 함께 Void Explorer를 만들고 있습니다. 먼 별까지 날아가 낯선 행성의 지표면으로 내려갈 수 있는 우주 탐험 게임입니다.

Void Explorer의 주요 플레이 장면을 모은 영상입니다.

게임에는 항성계가 2,048개 있고, 절차적으로 생성한 행성은 10,000개가 넘습니다. 그중에는 지구만 한 행성도 있습니다. 눈에 보이는 별은 모두 게임 속 우주에 실제로 존재하며 목적지로 지정할 수 있습니다. 저 멀리 보이는 빛 한 점을 골라 그곳까지 날아갈 수 있습니다.

우주에서 행성에 접근해 대기권을 통과하고 계속 고도를 낮추다 보면 어느새 해안선 위를 날고 있습니다. 착륙한 뒤 우주선에서 내려 주변을 걷다가 다시 이륙할 수도 있습니다. 이 여정을 구현하려면 공간의 규모부터 지형, 조종, 렌더링까지 함께 풀어야 했습니다.

개발 과정에서 사용한 프롬프트 몇 가지를 길이와 표현을 다듬어 실었습니다. 제가 원하는 것을 어떻게 설명했고 거기서 기술적인 작업이 어떻게 이어졌는지 보여 줍니다.

플레이 경험부터 정하기

처음에는 플레이어가 무엇을 할 수 있어야 하는지 설명했습니다.

눈에 보이는 곳은 어디든 갈 수 있어야 합니다. 실제 거리는 그대로 유지하면서 공간의 규모에 맞게 속도를 조절해 그 거리를 이동할 수 있도록 해 주세요. 우주에서 행성의 대기권으로 진입해 지면까지 비행하고 싶습니다. 행성은 지구만큼 클 수 있으니 절차적으로 생성하는 지형과 청크 단위로 처리하는 렌더러가 필요합니다.

이렇게 하니 Astra가 따라야 할 조건이 구체적으로 정해졌습니다. 별을 배경에 점으로 그려 넣는 것만으로는 부족했습니다. 행성에 가까워졌을 때 별도의 레벨로 넘어가서도 안 됐습니다. 실제 거리를 이동하되, 가상의 펄스 항법과 하이퍼드라이브로 플레이어가 그 거리를 감당할 수 있어야 했습니다.

게임을 본격적으로 구현하기 전에는 이미지 생성으로 어떤 분위기가 어울릴지 살펴봤습니다. 첫 콘셉트는 지나치게 사실적이었고, 다음 시안은 너무 단순했습니다. 그래서 이렇게 수정을 요청했습니다.

이번에는 조금 지나치게 단순해졌네요. 두 시안의 중간쯤이면 좋겠습니다. 색감을 다듬고 네온빛을 더하고 대비를 높여 깊은 우주의 느낌을 살려 주세요. 별과 먼지가 우주선 주위에 보이는 상태에서 고속으로 비행하면 어떤 모습인지 보여 주세요.

마음에 드는 이미지가 나오자 Astra에 이미지를 저장하고 그 안에 담긴 아트 방향을 게임 제작에 참고할 수 있도록 정리해 달라고 했습니다. 궤도 비행, 고속 비행, 대기권 진입, 착륙 장면마다 목표로 삼을 모습이 생겼습니다. 덕분에 다음 빌드를 평가하기가 훨씬 쉬워졌습니다.

각진 청록색 행성 위에 상아색 우주선이 떠 있고, 자홍색 포인트와 따뜻한 빛을 내는 두 태양이 보이는 콘셉트 아트

이미지 생성으로 만든 이 콘셉트 아트를 기준으로 게임의 색상 팔레트와 시각적 방향을 정했습니다.

아키텍처 제안은 Astra에 맡기기

제가 제약 조건을 정하면 Astra가 구현 방식을 제안했습니다. 애플리케이션은 TypeScript와 Vite로 만들고 렌더링에는 Three.js를 사용합니다. 이 구성에서는 메시, 머티리얼, 조명, 절차적 지오메트리를 코드에서 직접 제어할 수 있습니다. 이 게임의 시각적 요소 대부분이 여기서 만들어집니다.

처음으로 플레이할 수 있었던 버전의 렌더러는 WebGL2를 사용했습니다. 나중에 Three.js 때문에 그래픽 개선에 한계가 있는지 물었습니다. Astra는 시뮬레이션은 유지하면서 렌더러를 Three.js의 WebGPU 아키텍처로 옮기자고 제안했습니다. 우주, 항법, 지형 시스템을 그대로 두고 렌더링 계층을 교체했습니다.

렌더러는 Three.js의 노드 머티리얼과 Three.js Shading Language(TSL)를 사용해 대기, 물, 조명 효과를 코드로 정의합니다.

지형 생성은 Web Workers에서 실행합니다. 덕분에 입력과 그리기를 처리하는 스레드와 별개로 지오메트리를 준비할 수 있습니다. Vitest로는 같은 조건에서 같은 지형이 생성되는지, 좌표 계산이 정확한지, 지형 시스템이 정해진 규약을 지키는지 등을 검사합니다. Playwright로는 브라우저에서 게임을 실제로 구동해 테스트합니다. 이렇게 Astra가 내부 시스템을 점검하는 동안 저는 계속 게임을 플레이하며 조작감을 확인했습니다.

작업 내내 기준은 처음 정한 아트 방향이었습니다. 행성을 감싼 대기, 고리의 은은한 빛, 별에서 비치는 다양한 색의 조명, Neon Phosphor 효과가 어우러져 게임의 분위기를 만듭니다. 이 필터는 항법 정보를 선명하게 유지하면서 옛날 디스플레이 특유의 질감을 더합니다.

날개가 네 개인 우주선, 청록색 행성, 자홍색 고리, 두 태양, 항법 화면이 보이는 Void Explorer 플레이 장면

Neon Phosphor 효과를 켠 상태에서 캡처한 게임 화면입니다.

Astra가 직접 살펴보고 플레이할 수 있게 하기

저도 계속 직접 플레이했지만, Astra에도 제 설명을 읽는 것 외에 문제를 조사할 방법이 필요했습니다. 게임은 브라우저 테스트에서 호출할 수 있는 작은 JavaScript 인터페이스 window.__VOID_EXPLORER__를 제공합니다. 이 인터페이스로 현재 접근 중인 천체, 비행 모드, 지형 준비 여부, 활성 카메라를 확인할 수 있습니다. 드로 콜 수, 삼각형 수, 대기 중인 지형 작업 수, 버퍼에 저장된 지형 데이터 등 렌더링과 스트리밍 지표도 조회할 수 있습니다.

궤도 비행, 펄스 항법, 대기권 하강, 해안 착륙에 해당하는 테스트 장면에는 각각 이름을 붙였습니다. Astra는 매번 우주를 가로질러 비행할 필요 없이 원하는 출발 지점으로 돌아갈 수 있습니다. Playwright로 장면을 불러오고, 지형이 준비될 때까지 기다린 다음, 스크린샷을 찍고 그때의 내부 상태를 확인합니다. 별도의 여정 테스트에서는 실제 조종 입력을 사용하고 게임이 실행되는 동안 위치와 상태 변화를 기록합니다. 이렇게 해야 착륙 장면을 불러오는 데 그치지 않고 착륙 과정 자체를 테스트할 수 있습니다.

테스트 범위에는 착륙, 하선, 걷기, 저장과 다시 불러오기, 탑승, 이륙이 포함됩니다. 충돌 판정에 쓰는 표면이 아직 준비되지 않았거나 상태가 전환되는 순간 우주선의 위치가 갑자기 바뀌는 문제처럼, 스크린샷 한 장으로는 알기 어려운 현상도 발견할 수 있습니다.

제가 플레이 중인 브라우저 탭을 살펴봐 달라고 Astra에 요청할 수도 있었습니다. Aurelia의 구름이 여전히 보이는지 물었더니, Astra가 당시 제 화면을 캡처하고 화면에 표시된 비행 정보를 읽었습니다. 요청한 시점의 화면을 확인한 것이며, 비행하는 내내 모든 프레임을 지켜본 것은 아닙니다.

문제를 재현하고, 스크린샷과 상태를 살펴보고, 관련 코드를 추적해 수정한 다음, 같은 검사를 다시 실행하는 과정을 반복했습니다. 다른 게임을 만든다면 재현 가능한 장면 몇 개, 상태와 성능을 파악할 지표, 주요 상호작용을 검증하는 브라우저 테스트부터 마련할 생각입니다. 이런 도구가 있으면 제가 화면과 조작감을 살피는 동안 Astra가 스스로 문제를 조사하고 변경 사항을 테스트할 수 있습니다.

여러 축척으로 우주 표현하기

행성이 수천 개 있다고 해서 정밀한 메시를 수천 개 불러올 필요는 없습니다. 처음에 행성은 반지름, 궤도, 대기, 시드 같은 정보로만 정의됩니다. 시드가 같으면 같은 지형이 생성됩니다. 게임은 제가 접근하는 지역 주변의 지오메트리를 생성하고, 나중에 돌아오면 같은 풍경을 다시 만들어 냅니다.

좌표도 세심하게 다뤄야 합니다. 광년 단위의 거리와 우주선 옆에 서 있는 사람의 위치는 규모가 전혀 다릅니다. 그렇게 큰 좌표값을 그대로 GPU에 넘기면 지면 가까이에서 필요한 정밀도를 잃게 됩니다.

Astra는 우주 공간에서의 실제 위치와 화면을 그릴 때 사용하는 위치를 분리했습니다. 우주는 정수 좌표로 구분한 큰 셀과 각 셀 안에서의 작은 오프셋으로 위치를 나타냅니다. 렌더링하기 전에 관측자의 위치를 빼므로 카메라는 원점에 있고 주변 물체의 좌표값은 작게 유지됩니다. 화면에 표시되는 거리와 물체 간 크기 비율도 일관됩니다.

움직이는 물체는 시간 기준도 일치해야 합니다. 항성과 행성, 위성은 수식으로 정의된 궤도를 따릅니다. 렌더러는 관측자의 위치를 계산할 때와 동일한 시뮬레이션 시각을 기준으로 각 천체의 위치를 구합니다. 착륙해 세워 둔 우주선은 행성이 자전해도 지표면의 같은 자리에 있습니다. 항성의 위치와 색을 조명에 반영하므로, 쌍성계의 지표면에서 지는 두 태양은 궤도에서 보았던 바로 그 별들입니다.

우주에서 지표면까지 끊김 없이 하강하기

Void Explorer에서 우주를 비행하다 위성의 표면으로 접근하는 장면입니다.

우주에서 지표면까지 자연스럽게 이어지도록 여러 차례 수정했습니다. 행성 표면과 거의 평행한 각도로 접근하다가 이런 프롬프트를 작성했습니다.

행성 표면과 거의 평행하게 접근할 때는 여전히 진입 속도가 너무 빠를 때가 있고, 지형을 불러오는 동안 행성이 거의 사라져 버립니다. 속도 곡선과 지형 스트리밍을 함께 손봐 주세요. 대기 효과로 원거리 LOD에서 정밀한 지형으로 더 자연스럽게 전환할 수 있을까요? 접근하는 동안에는 행성이 한순간도 사라져서는 안 됩니다.

이제 비행 컨트롤러는 낮은 각도로 접근할 때 별도의 속도 상한을 적용합니다. 현재 고도와 행성의 반지름 및 중력으로 추정한 궤도 속도를 기준으로 상한을 정합니다. 지면에 가까워지면 진행 방향의 지형도 샘플링해 감속 정도를 조절합니다.

게임은 여러 단계의 디테일 수준(LOD)을 사용합니다. 멀리서는 렌더링 비용이 낮고 각진 구 형태의 프록시로 행성을 표현합니다. 행성이 화면에서 차지하는 면적이 커지면 렌더러가 디테일을 더합니다. 표면에 접근하면 정육면체의 여섯 면을 구에 투영해 만든 지형이 활성화됩니다. 각 면을 네 개의 작은 정사각형으로 나누고 이 분할을 반복할 수 있습니다. 이것이 쿼드트리 구조입니다.

덕분에 지구만 한 표면 전체를 걸어 다닐 때 필요한 해상도로 생성하지 않고도 눈에 보이는 영역과 진행 방향의 지형을 정밀하게 표현할 수 있습니다. 지면 가까이에서는 우주선과 플레이어 주변에 작은 지형 패치를 배치해 더 촘촘한 지오메트리를 제공합니다.

어떤 방식으로 표현하든 같은 행성 데이터를 샘플링합니다. 공통 함수가 대륙과 산등성이, 크레이터, 작은 지형의 기복을 조합합니다. 이 함수에서 지형을 표현하는 데 필요한 고도, 물, 생물군계 등의 정보를 얻습니다. 성긴 메시와 촘촘한 메시는 같은 데이터를 서로 다른 해상도로 근사합니다. 색을 정하는 규칙은 공유하므로 행성의 외관이 일관되게 유지됩니다.

지형을 생성하는 것만큼이나 새 지형으로 교체하는 방식이 중요합니다. 저해상도 지형 여섯 면이 모두 준비될 때까지는 원거리에서 보이던 행성을 계속 표시합니다. 각 지형 타일도 하위 타일 네 개가 모두 준비될 때까지 유지합니다. 전환 중에는 서로 보완하는 픽셀 마스크를 사용해 각 픽셀에 기존 표면과 새 표면 중 하나를 표시합니다. 이렇게 하면 새 표면을 불러오는 동안 행성 전체가 투명해지는 일을 피할 수 있습니다.

대기의 모습은 실제 고도에 따라 달라지고 구름은 행성 지형 위를 흐릅니다. 덕분에 궤도에서 본 모습과 지표면의 풍경이 자연스럽게 이어집니다. 렌더러는 정밀한 지형이 준비된 부분에서만 저해상도 지형을 제거합니다. 그래도 더 정밀한 지오메트리가 나타날 때 산의 윤곽은 달라질 수 있습니다.

착륙하려면 더 엄격한 조건을 충족해야 합니다. 접촉 영역에 표시되는 지면, 충돌 판정용 삼각형, 액체 위험 구역은 모두 같은 지형 생성 결과에서 가져와 동시에 사용할 수 있어야 합니다. 보행은 Rapier를 사용해 좁은 범위의 로컬 물리 공간에서 처리합니다. 우주선의 착륙 로직은 별도로 착륙 다리의 접촉 상태, 지면의 경사, 기체와 지면 사이의 여유 공간을 검사합니다.

여기에는 의도적으로 둔 한계가 있습니다. 행성은 중심에서 표면을 향하는 각 방향에 고도값을 하나씩 두는 높이 필드를 사용합니다. 넓은 지형에는 적합하지만 동굴, 돌출된 절벽, 파괴할 수 있는 터널은 표현할 수 없습니다.

느린 프레임에서 어떤 작업이 일어나는지 측정하기

같은 비행에서 화면과 성능 문제가 함께 드러나는 경우가 있어 두 가지를 묶어 피드백하기도 했습니다.

제가 우주에서 지면을 향해 비행할 때 게임이 행성을 어떻게 불러오고 렌더링하는지 살펴봐 주세요. 멀리서 본 행성의 모습과 가까이에서 본 정밀한 지형이 서로 달라서 전환이 어색합니다. 특히 색이 바뀔 때 두드러집니다. 하강 장면이 더 자연스럽고 매끄럽게 이어지도록, 화면이 갑자기 달라지는 원인과 더 정밀한 지형을 불러올 때 작업량을 줄일 수 있는 부분을 알고 싶습니다.

Astra는 Three.js의 렌더러 카운터로 드로 콜, 삼각형, 지오메트리, 텍스처 수를 확인했습니다. Playwright 테스트에서는 프레임 간격을 90회 측정하고 평균과 백분위수 값을 이들 지표와 함께 기록했습니다. 화면에 문제가 있으면 특정 효과를 켰을 때와 껐을 때의 렌더링 결과를 픽셀 단위로 비교할 수도 있었습니다. 예를 들어 겹친 지면을 숨기는 마스크를 적용한 지형과 적용하지 않은 지형을 비교했습니다. 덕분에 문제가 발생한 장면의 스크린샷에만 의존하지 않고 지면이 사라진 원인을 좁혀 갈 수 있었습니다.

앞서 우주선을 교체했을 때도 이런 측정이 도움이 됐습니다. 절차적으로 생성한 우주선을 Blender에서 만든 첫 번째 AURORA 모델로 교체하자 장면의 삼각형 수는 늘었지만 드로 콜 수는 줄었습니다. Astra는 교체 전후에 WebGPU 백엔드에서 동일한 90프레임 궤도 비행 테스트를 실행했습니다.

측정 항목 변경 전 변경 후
장면 전체 드로 콜 수 119 77
장면 전체 삼각형 수 48,809 61,092
평균 프레임 간격 251.48 ms 199.26 ms

이 비교는 아래에 나오는 날개 네 개짜리 우주선을 만들기 전에 헤드리스 Chromium에서 SwiftShader 소프트웨어 렌더링으로 진행했습니다. 수치는 해당 테스트 환경에서의 변화를 나타내며, 제 GPU의 프레임 레이트를 측정한 값은 아닙니다. 도구를 통해 Astra가 확인한 것은 브라우저에서 측정한 시간, 렌더링된 이미지, 리소스 수였습니다. 개별 GPU 명령이나 셰이더 실행 시간은 측정하지 않았습니다.

Astra는 로딩과 하강 중에 어떤 작업이 일어나는지 조사했습니다. 지오메트리를 얼마나 생성하는지, 워커와 렌더러 사이에 데이터가 얼마나 오가는지, 생성한 지형을 쓰기도 전에 작업을 폐기하는 일이 얼마나 잦은지 확인했습니다.

한 가지 변경 사항은 멀리 있는 행성의 디테일을 화면에서 차지하는 크기에 맞춰 배분하는 것이었습니다. 화면을 가득 채우는 행성은 처음부터 윤곽이 뚜렷해야 합니다. 반면 한 픽셀보다 작은 행성에 그만큼의 지오메트리를 쓸 필요는 없습니다. 조건을 통제해 시작 장면을 비교한 결과, 새 규칙을 적용했을 때 프록시 삼각형 수가 51,200개에서 7,040개로 줄었습니다. 두 규칙 모두 같은 지오메트리 생성기를 사용했으므로 어떤 디테일을 불러올지 결정하는 방식의 효과만 따로 확인할 수 있었습니다.

또 다른 개선에서는 지형의 삼각형 수를 그대로 유지했습니다. 인덱스 메시는 이웃한 삼각형이 공유하는 정점의 위치, 색상, 법선 데이터를 반복해서 저장하지 않고 정점을 재사용합니다. 지형 품질을 높음으로 설정한 테스트에서 지면 레이어 여섯 개의 삼각형 241,952개를 모두 유지하면서 전송한 버퍼의 총크기를 약 35 MB에서 15 MB로 줄였습니다. 지면 생성과 주변 경관 생성도 별도 작업으로 나눴습니다. 이제 장식 요소를 기다리지 않고 지면 지오메트리를 준비할 수 있습니다.

지형을 선택하는 로직에도 불필요한 작업이 있었습니다. 청크를 요청했다가 판단이 바뀌면 해당 청크를 폐기하고 다른 청크를 요청하곤 했습니다. Astra는 세분화 여부에 대한 판단이 자주 뒤집히지 않도록 조정하고, 할당된 자원으로 하위 타일 네 개를 모두 처리할 수 있을 때만 타일을 분할하도록 했습니다. 워커 지연 시간을 고정한 시뮬레이션에서 6초간 하강한 뒤 3초간 안정화될 때까지 기다렸더니 폐기된 작업이 6,074개에서 13개로 줄었습니다.

시뮬레이션 시간 9초 동안 예약 후 폐기된 지형 작업 수를 나타낸 선 그래프. 기존 선택 로직에서는 6,074개까지 늘어나지만 개선한 로직에서는 13개에 머뭅니다. 카메라는 6초 후 멈춥니다.

워커 두 개를 두고 워커 지연 시간을 100 ms로 설정한 시뮬레이션에서 예약 후 폐기된 작업이 6,074개에서 13개로 줄었습니다. 프레임 레이트가 아니라 지형 작업 스케줄링을 측정한 결과입니다.

워커만으로 모든 끊김을 해결할 수는 없습니다. 메인 스레드에서 지형을 대신 생성하는 경로에서도 다른 작업에 실행 기회를 넘겨줘야 했습니다. Astra는 생성 과정을 중단했다가 이어서 실행할 수 있는 단계로 나누고 프레임당 약 4 ms를 할당했습니다. 덕분에 큰 지형 작업을 한 번에 끝낼 필요가 없어졌습니다. 렌더러는 게임 세계의 해상도 상한도 인터페이스와 별도로 설정하므로 그래픽 품질을 낮춰도 항법 정보의 글자는 선명합니다.

지형 측정 결과를 보면 지오메트리와 데이터 전송량, 폐기된 작업이 모두 줄었습니다. 다만 이 수치들은 하드웨어의 프레임 레이트를 측정한 벤치마크가 아닙니다. 셰이더 컴파일, GPU 업로드, 움직임, 실제 화면에서의 전환 효과를 확인하려면 여전히 브라우저에서 직접 플레이해 봐야 합니다.

저는 플레이하면서 어디가 느리게 느껴지는지, 무엇이 이상해 보이는지, 어떤 부분을 개선하고 싶은지 피드백했습니다. Astra는 코드를 추적하고 재현 가능한 지형 테스트를 스크립트로 작성해 측정값을 기록했습니다. 제가 방향을 승인하면 변경 사항을 구현한 뒤 같은 테스트를 다시 실행해 결과를 비교했습니다. 조사와 구현의 각 단계를 제가 일일이 지정할 필요는 없었습니다. 그동안 저는 게임 화면과 플레이 감각을 계속 확인했습니다.

콘셉트 아트로 게임 에셋 만들기

행성, 지형, 구름, 고리, 별 등 우주의 대부분은 코드로 생성합니다. 반면 플레이어의 우주선은 직접 모델링한 대표적인 3D 에셋으로, 다른 방식으로 제작했습니다.

우주선을 게임에 넣기 전에 생성한 콘셉트 이미지와 Blender 렌더링 결과로 디자인을 검토했습니다. 날개가 제가 생각한 모양과 달라서 모델링에 더 도움이 될 참고 이미지를 요청했습니다.

이 우주선의 형태가 잘 보이도록 여러 각도에서 본 이미지를 만들어 주세요. 특히 앞날개와 뒷날개에 신경 써 주세요. 이 이미지들을 참고해 3D 모델을 다시 만들 예정입니다. 지금 모델은 날개가 서로 이어져 있고 둥글게 처리된 점이 마음에 들지 않습니다.

저는 날개 네 개가 각각 분리되어 있고 좌우 대칭이며 날개 끝에 분홍색 조명이 달린 시안을 골랐습니다. 그런 다음 Astra에 게임의 아트 스타일을 유지하면서 Blender로 새 모델을 만들어 게임에 넣어 달라고 했습니다.

참고 이미지의 형태를 지오메트리로 옮기고, 윤곽과 머티리얼을 검토한 뒤, 게임 실행 시 사용할 에셋을 준비했습니다. Blender 원본에는 편집 가능한 메시가 193개 있습니다. 내보낸 우주선 모델은 삼각형 14,968개로 구성되며 불투명 머티리얼 배치 8개로 묶여 있습니다. 저는 모델에 원하는 디테일을 요청하고, Astra는 내보낸 모델의 렌더링 비용을 관리했습니다.

우주선을 위에서 본 모습을 생성한 콘셉트 이미지. 분리된 날개 네 개, 날개 끝의 분홍색 조명, 상아색 선체, 초록색 캐노피가 보입니다.

생성한 우주선 콘셉트 중 제가 선택한 시안입니다.

세라믹 선체, 분리된 날개 네 개, 청록색 엔진 두 개가 보이는 우주선의 Blender 렌더링 이미지

게임에 사용한 모델을 Blender로 렌더링한 모습입니다.

절차적으로 생성한 물 실험하기

작은 배를 조종해 절차적으로 생성한 바다를 항해하는 게임 Sunwake에서도 물을 표현하는 데 많은 시간을 들였습니다. 제가 원한 것은 각진 면으로 이루어지면서도 부드럽게 움직이는 파도와 스테인드글라스 같은 색감이었습니다. Astra는 Three.js로 전용 물 렌더러를 만들고, 화면에 보이는 바다와 배의 부력에 같은 파도 모델을 적용했습니다. 파도에 따라 선체가 떠오르고 앞뒤와 좌우로 기웁니다. 배 주변에서는 시뮬레이션에 따라 잔물결과 거품이 흘러가고, 배가 지나간 자리에는 물살과 물보라가 생깁니다. 나중에는 Astra에 Blender로 배를 더 정교하게 만들어 게임에 넣어 달라고 했습니다. Void Explorer와 마찬가지로 환경은 절차적으로 생성하고 탈것은 직접 모델링한 뒤 시뮬레이션으로 둘을 연결했습니다.

분홍빛 해가 떠오르는 가운데 주황색 배가 각진 푸른 파도를 가르며 거품 섞인 물살을 남기는 Sunwake 플레이 장면

Sunwake에서는 절차적으로 생성한 바다 위에 Blender로 모델링한 배를 띄웠습니다.

Hollowflux에서는 다른 방향으로 실험했습니다. 빛나는 지하 강을 중심으로 펼쳐지는 작은 2D 액션 RPG입니다. 외부 스프라이트 시트를 가져오지 않고 동굴, 캐릭터, 장비를 모두 코드로 그립니다. 걷거나 돌진하거나 공격할 때 물이 더 그럴듯하게 반응하도록 Astra에 여러 차례 요청했습니다. 격자의 각 셀에서 수면 높이, 물의 흐름, 거품, 전하를 추적합니다. 발을 디디면 잔물결이 생기고, 창을 내지르면 물이 좁게 갈라지며, 망치를 내리치면 둥근 파문이 퍼집니다. 물살은 강둑을 따라 휘돌면서 거품을 하류로 실어 나르고, 그 흐름에 플레이어와 적도 밀려납니다. 물은 전투에도 영향을 줍니다. 뱀장어가 방전하면 물이 이어진 곳을 따라 전기가 퍼지므로 마른 바위에 올라서면 감전을 피할 수 있습니다.

Hollowflux에서 픽셀 아트로 그린 모험가가 청록빛을 내는 강을 헤치고 걷는 장면. 주변에 잔물결과 생물들, 어두운 동굴 벽이 보입니다.

Hollowflux는 게임 속 모습을 코드로 그리며, 물은 움직임과 전투에 반응합니다.

게임 만들고 공유하기

Astra와 작업하면서 마음에 드는 점은 제가 원하는 플레이 경험에서 출발해 이미지로 시각적 방향을 구체화하고, 직접 플레이해 본 느낌을 바탕으로 피드백할 수 있다는 것입니다. 비행 중 행성이 사라진다는 한마디가 스트리밍과 지오메트리, 이동 방식의 개선으로 이어질 수 있습니다. 물을 더 그럴듯하게 표현해 달라는 요청은 화면 표현과 게임플레이가 공유하는 시뮬레이션으로 발전할 수 있습니다. 원하는 느낌이 나는지는 여전히 제가 판단해야 하지만, Astra는 그 판단을 코드와 에셋, 테스트에 반영할 수 있습니다.

브라우저 게임은 공유하기도 간단합니다. Sites 플러그인을 사용하면 Astra에 이렇게 요청할 수 있습니다.

@Sites로 이 게임을 배포하고 링크를 알려 주세요.

누구나 접근할 수 있도록 공개하면 브라우저에서 바로 플레이할 수 있습니다.

Void Explorer, Sunwake, Hollowflux를 브라우저에서 직접 플레이해 보세요.

머릿속에 게임 아이디어가 있다면 Astra와 함께 직접 플레이할 수 있는 작은 버전부터 만들어 보세요. 원하는 느낌을 꼭 살리고 싶은 요소 하나를 정하고, 참고 이미지 몇 장을 건넨 뒤 결과를 테스트해 보세요. 배 한 척, 방 하나, 상호작용 하나면 시작하기에 충분합니다. 직접 플레이하고 무엇을 바꾸고 싶은지 구체적으로 설명하면서 게임을 발전시켜 보세요.