나는 Node.js로 게임 엔진을 만들고 있습니다 (네, 정말)
I’m happy to help translate the article, but I don’t see the article text in your message—only the source line. Could you please paste the content you’d like translated? Once I have the text, I’ll provide the Korean translation while preserving the formatting, markdown, and code blocks as requested.
제목이 미친 듯이 들리지만… 실제로 일어나고 있습니다.
그리고 정말 멋져 보입니다.
결과
Godot‑like scene tree
Dual screen + culling
Physics
Character controller with a procedurally generated map
Node.js 소스 코드를—혹은 실제로는 어떤 런타임이든—읽다 보면 이 기술이 얼마나 새롭고 강력한지 깨닫게 됩니다. 그 순간 스스로를 멈출 수 없게 되고, 반드시 만들어야만 합니다.
그래서 Nexus가 탄생했으며, 이는 또 다른 프로젝트인 Node.js용 C++ N‑API 렌더러를 기반으로 합니다. 자세한 내용은 여기에서 확인하세요:
How I built a Renderer for Node.js
하지만 모든 프로젝트마다 문제는 존재합니다. 저는 70 %는 보일러플레이트, 30 %는 실제 프로그래밍이라고 말하고 싶으며, 그 30 %가 바로 새롭고 고통스럽고 결정이 많이 필요한 부분입니다.
그 30 % 중 큰 비중을 차지한 것이 물리 엔진과 카메라였습니다.
스포일러: 매우 어렵습니다.
솔직히 말하면, 저는 이전에 C로 물리 엔진을 처음부터 만든 경험이 있지만, JavaScript는 전혀 다른 이야기입니다. 표현력이 떨어지고, 가비지 컬렉션이 있으며, 단일 스레드이고, 완전히 새로운 문제 영역을 가지고 있습니다.
그럼에도… 결과는 괜찮아 보입니다.
또한 저는 공격적으로 최적화할 계획을 가지고 있습니다—자세한 내용은 I Tried to Beat WebAssembly With Node.js 를 참고하세요.
Camera
The problem: your screen is static. It doesn’t move. It doesn’t resize.
So what happens when the player is at screen size + 1 pixel?
- The world is infinite.
- The screen is finite.
I can’t move the real screen, but what if I create a pseudo screen? A simulated one—not real—that can move freely.
World (large area)
+-------------------------------------------------------------+
| |
| . . . . . . . . . . . . . . . . . . . . . . . . . . . |
| |----------------------- Screen ---------------------| |
| | | |
| | | |
| | | |
| | | |
| | | |
| |---------------- (real screen) -------------------| |
| ^ |
| | |
| (player P) |
| P |
| C|
| [Camera viewport] ------------------ |
| .----------------------------------. |
| | | |
| | CAMERA (C) | |
| | | |
| '----------------------------------' |
| |
+-------------------------------------------------------------+
Legend:
- Big box = World
- Inner rectangle labeled “Screen” = the real screen (inside the world)
- “P” = Player point placed outside the real screen
- Dashed/smaller rectangle near P labeled Camera = the pseudo screen / camera viewport that can move freely
Enter fullscreen mode Exit fullscreen mode
Whatever this pseudo screen sees gets translated onto the real screen. That’s your frustum → viewport → screen translation.
Sounds simple, until you realize you now have two coordinate systems for every object and component:
| System | Origin |
|---|---|
| Top‑left | renderer |
| Free‑flowing, center‑based | camera |
The real pain is translating to and from these systems. And that’s not even the end of it.
Once the camera exists, it has to be useful:
- a controller that actually follows the player smoothly,
- culling pixels outside the frustum/viewport,
- translating every pixel into screen space (and back, if needed).
On top of translation madness, you add follow behavior, shake, culling, multiple cameras…
Still, it’s looking decent, as you saw from the character controller demo.
Source: …
물리 엔진
이전
실시간이라서 어려운 것이 아니라, 시뮬레이션된 실시간이라서 어렵다. 물체가 빠르게 움직이고, 충돌도 빠르게 일어난다. console.log 로는 해결할 수 없다.
그래서 이번엔 Matter.js 를 사용했다 – 순수 JavaScript 기반의 견고한 라이브러리다. 잘 동작했다.
그런데 키네마틱 바디 를 지원하지 않는다는 것을 깨달았다. 거의 모든 2D 게임의 핵심인 센서, AI, 움직이는 플랫폼 등은 모두 키네마틱 바디다.
엔진이 보통 제공하는 바디 타입
| 유형 | 설명 |
|---|---|
| Static | 움직이지 않음; 지형/배경에 사용, 힘에 영향을 받지 않음 |
| Dynamic | 완전 시뮬레이션; 힘과 충돌에 영향을 받음 |
| Kinematic | 스크립트/제어에 의해 움직임; 충돌은 하지만 물리 힘에 의해 구동되지 않음 |
키네마틱 바디는 게임플레이의 핵심이다.
하지만 나는 개발자라서 이렇게 생각했다:
“쉽다. 키네마틱 바디는 움직이는 정적 바디일 뿐이다.”
엄청난 실수.
정적 바디는 다른 정적 바디와 충돌하지 않는다(예를 들어, 총알이 키네마틱 적이나 움직이는 플랫폼과 충돌하지 않는다). 엔진은 정적 이면 절대 움직이지 않는다고 가정하기 때문이다. 이제 나는 Matter.js 를 억지로 구부려서 충돌을 직접 처리하려 하고 있다.
결과는 좋지 않았다.
시뮬레이터 밖에서 시뮬레이션을 수행하고, 오염된 결과를 다시 넣어 물리 엔진이 잘 동작하길 바라고 있다.
가능하긴 하다.
하지만 굉장히 짜증난다.
그래서 사흘을 더 쓰는 대신, planck.js 로 엔진을 바꾸었다. 이 엔진은 내가 필요한 모든 것을 지원한다.
Planck.js 로 바꾸면서 생긴 새로운 문제
-
Planck 의 좌표계는 좌하단이다.
-
이제 세 가지 시스템 사이를 변환해야 한다:
- 좌상단 ← 렌더러
- 중앙 ← 카메라
- 좌하단 ← planck.js
-
Planck 은 미터 단위로 동작하고, 렌더러와 카메라는 픽셀 단위로 동작한다.
또 다른 변환 레이어가 추가된 것이다.
지금 내가 하고 있는 일은 새로운 물리 엔진으로 마이그레이션하고, 완전 새로운 변환 레이어를 구축하는 … 그리고 여전히 재미있게 작업하는 것이다.




