C++ 게임 루프 완벽 이해: 게임은 어떻게 계속 움직일까?

🚀 들어가며

이번 글에서는 C++ 게임 루프의 기본 구조와 게임이 어떻게 계속 실행되는지를 설명합니다.

게임을 실행하면 캐릭터가 움직이고, 화면이 계속 갱신됩니다.

그렇다면 이런 질문이 자연스럽게 떠오릅니다.

❓ 게임은 어떻게 “계속” 실행되는 걸까?

이 질문에 대한 답이 바로
👉 게임 루프(Game Loop)에 있습니다.


🎯 게임 루프란 무엇인가?

게임 루프는 간단하게 말하면:

게임을 계속 실행시키는 반복 구조

가장 단순한 형태는 다음과 같습니다.

while (running)
{
    Tick();
    Draw();
}

🔍 이 코드가 하는 일

✔ Tick

  • 게임 상태 업데이트
  • 캐릭터 이동
  • 충돌 처리
  • 입력 반영

✔ Draw

  • 화면 출력
  • 그래픽 업데이트

👉 즉:

게임 루프는 게임의 “심장” 역할을 합니다


⚠️ 하지만 이 구조에는 문제가 있습니다

이 코드 그대로 실행하면:

  • CPU를 100% 사용
  • 프레임 속도 제어 불가능
  • 실행 속도 불안정

🎯 문제의 핵심

👉 컴퓨터는 너무 빠르게 루프를 돌립니다

결과:

  • 어떤 PC에서는 너무 빠름
  • 어떤 PC에서는 느림

👉 게임이 일정하게 동작하지 않음


🔥 해결 방법: 시간 개념 도입

여기서 등장하는 개념이:

👉 deltaTime


🧠 deltaTime이란?

이전 프레임과 현재 프레임 사이의 시간

예:

position += speed * deltaTime;

👉 이렇게 하면:

  • FPS가 달라도
  • 움직임이 일정해짐

🧭 deltaTime 계산 흐름

deltaTime은 복잡한 개념이 아닙니다.

핵심은 다음과 같습니다.

이전 프레임 시간 ───── 현재 프레임 시간
        │                    │
        └──── 시간 차이 ─────┘

        deltaTime = 현재 프레임 시간 - 이전 프레임 시간

예를 들어보겠습니다.

1프레임 시작 시간: 0.000초
2프레임 시작 시간: 0.016초

deltaTime = 0.016 - 0.000
          = 0.016초

0.016초는 약 16ms입니다.

이는 1초에 약 60번 화면이 갱신되는 속도, 즉 60FPS에 가까운 값입니다.


🎮 deltaTime을 왜 곱할까?

캐릭터가 초당 100만큼 이동한다고 가정해보겠습니다.

float speed = 100.0f;
position += speed * deltaTime;

만약 deltaTime0.016666초라면:

이동 거리 = 100 * 0.016666
         = 1.6666

즉, 한 프레임 동안 캐릭터는 1.6666만큼 이동합니다.


🧩 프레임별로 보면 이렇게 됩니다

시간 흐름

0.000초 ── 0.016초 ── 0.032초 ── 0.048초
   │           │           │           │
  1프레임      2프레임      3프레임      4프레임

각 프레임 deltaTime ≒ 약 0.016666초

이 경우 매 프레임 이동량은 다음과 같습니다.

1프레임 이동량 = 100 * 0.016666 ≒ 1.6666
2프레임 이동량 = 100 * 0.016666 ≒ 1.6666
3프레임 이동량 = 100 * 0.016666 ≒ 1.6666

그래서 1초 동안 누적하면:

1.6666 * 60프레임 ≒ 100

오차를 제외하면 초당 대략 100만큼 이동하게 됩니다.


⚠️ deltaTime을 사용하지 않으면?

만약 이렇게 작성하면 어떻게 될까요?

position += speed;

이 코드는 프레임마다 100씩 이동합니다.

30FPS 환경  → 1초에 30번 이동 → 100 * 30 = 3000
60FPS 환경  → 1초에 60번 이동 → 100 * 60 = 6000
144FPS 환경 → 1초에 144번 이동 → 100 * 144 = 14400

즉, 게임이 실행되는 환경에 따라 같은 시간(1초)이 경과했을 때의 결과가 달라지고,
FPS가 높은 컴퓨터일수록 캐릭터가 더 빠르게 움직입니다.

실행되는 컴퓨터(하드웨어)의 환경이 달라지더라도 동일한 시간이 흘렀을 때 동일한 결과를 출력해야 합니다.


✅ deltaTime을 사용하면?

position += speed * deltaTime;

이렇게 작성하면 FPS가 달라도 이동 속도가 비슷하게 유지됩니다.

30FPS  → deltaTime 약 0.033초 → 100 * 0.033 * 30 ≒ 100
60FPS  → deltaTime 약 0.016초 → 100 * 0.016 * 60 ≒ 100
144FPS → deltaTime 약 0.0069초 → 100 * 0.0069 * 144 ≒ 100

🎯 왜 중요한가

게임 루프에서 deltaTime을 사용하면:

  • 프레임 독립성 확보
  • 다양한 환경에서 동일한 동작

결국 핵심은 이것입니다.

프레임마다 움직이는 양을 정하는 것이 아니라,
실제로 흐른 시간만큼 움직이게 만드는 것

C++ 게임 루프에서 deltaTime은
프레임 독립성을 유지하기 위한 핵심 요소입니다.

이러한 구조는 단순한 예제가 아니라,
실제 게임 엔진 내부에서 그대로 사용되는 방식입니다.


🎮 실제 엔진에서는 어떻게 동작할까?

Unity나 Unreal 같은 엔진에서도
👉 동일한 구조가 존재합니다.

예를 들어 Unity:

  • Update()
  • FixedUpdate()

Unreal:

  • Tick()

👉 내부적으로는 모두 게임 루프 기반입니다.


🧩 조금 더 발전된 구조

하지만 단순한 루프는 부족합니다.

실제 엔진에서는:

  • 입력 처리
  • 물리 처리
  • 렌더링
  • 시간 관리
  • 등등

👉 여러 단계로 나누어 프레임 처리를 실행합니다.


🔥 핵심 정리

  • 게임 루프는 게임에서 프레임을 처리하기 위한 반복 구조
  • Tick / Draw 등으로 구성된다
  • 프레임 시간(deltaTime)이 반드시 필요하다

🎮 마무리

게임 루프는 단순한 while문이 아니라
👉 게임 엔진 구조의 핵심 개념입니다.


🧠 한 단계 더 생각해보기

여기서 중요한 질문이 하나 더 있습니다.

❓ 프레임을 “고정”해야 할까?
❓ 아니면 “가변”으로 둬야 할까?

👉 이 부분은 게임 루프에서 매우 중요한 주제입니다.

참고로 게임 루프에 대한 더 깊은 이론적 배경은
Robert Nystrom의 『Game Programming Patterns』 중 Game Loop 장을 참고해보셔도 좋습니다.


🎯 다음 글 예고

다음 글에서는 단순한 개념이 아니라
C++로 실제 고정 프레임 게임 루프를 구현하면서
FPS 제어와 busy wait 방식까지 함께 살펴보겠습니다.

👉 C++ 게임 루프 구현 (고정 프레임 방식)

  • Fixed timestep
  • FPS 제어
  • Busy wait 방식

🚀 한 단계 더 나아가고 싶다면

게임 루프를 이해하는 것은 엔진 구조를 이해하는 출발점입니다.
이 구조를 단순히 개념으로 아는 것과 직접 구현해보는 것은 큰 차이가 있습니다.
엔진을 직접 만들어보는 과정에서 이 개념들이 어떻게 연결되는지 확인하고 싶으시다면
아래 강의도 참고해보셔도 좋습니다.

👉 강의 링크: C++로 만드는 게임 엔진 프레임워크 (소코반과 슈팅 게임으로 배우는 엔진 구조)

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Please turn AdBlock off

Notice for AdBlock users

Please turn AdBlock off