Post

2026-03-27 TIL (24일차)

2026-03-27 TIL (24일차)

팀 프로젝트

SceneManager 구현


싱글톤 패턴 (Singleton Pattern) 적용

씬 매니저는 게임 전반에 걸쳐 하나의 인스턴스만 존재해야 하며, 어디서든 쉽게 접근해 씬을 변경할 수 있어야 합니다.

  • 생성자 은닉: 생성자를 private으로 선언하여 외부에서 임의로 객체를 생성하는 것을 막았습니다.
  • 전역 접근점: static SceneManager& getInstance() 함수를 만들어 전역적으로 단일 객체에 접근할 수 있게 구현했습니다.
  • 복제 원천 차단: delete 키워드를 사용해 복사 생성자와 대입 연산자를 막아(Copy/Assignment 방지), 의도치 않은 인스턴스 복제를 완벽하게 차단했습니다.


Stack 자료구조를 이용한 씬 관리

나중에 들어온 씬이 먼저 나가는 LIFO(Last In First Out) 특성이 게임의 화면 전환 방식과 맞아떨어지기 때문입니다. (예: 인게임 ➡️ 인벤토리 창 열기 ➡️ 인벤토리 창 닫기(pop) ➡️ 다시 인게임)

핵심 기능 구현 상세

  • Render() & Update()
    • 스택이 비어있지 않다면 항상 SceneStack.top() (현재 가장 위에 있는 씬)의 렌더링과 업데이트만 수행합니다. 아래에 깔린 다른 씬들은 로직이 멈춰있는 일시정지 상태가 됩니다.
  • Add_Scene(Scene* newScene)
    • 현재 씬을 유지한 채 새로운 화면을 위에 띄워야 할 때 사용합니다. (예: 게임 중 팝업창 띄우기)
    • 기존 씬은 Exit() 시켜 일시정지 상태로 만들고, 새 씬을 push한 뒤 Init()으로 초기화합니다.
  • Return_Scene()
    • 현재 씬의 목적이 끝나고 이전 씬으로 돌아갈 때 사용합니다. (예: 메뉴 화면에서 뒤로 가기)
    • 현재 씬을 Exit() 하고, 동적 할당된 메모리를 delete로 해제한 뒤 스택에서 pop()하여 이전 씬을 다시 활성화합니다.
  • Replace_Scene(Scene* newScene)
    • 이전 씬의 데이터가 더 이상 필요 없을 때 사용합니다. (예: 타이틀 화면 ➡️ 본격적인 인게임 화면)
    • 현재 씬을 삭제 및 pop 한 후, 새로운 씬을 push하여 아예 화면을 완전히 교체해 버립니다.


메모리 누수 방지

  • 씬 전환(Return, Replace)이 일어날 때마다 스택에서 빼기 전에 잊지 않고 delete SceneStack.top();을 호출하여 메모리를 해제해 주었습니다.
  • 게임이 완전히 종료될 때는 SceneStack_Clear() 함수를 호출해 while문으로 스택 내부에 남아있는 모든 씬의 메모리를 해제하도록 구현했습니다.


UI 구현

BattleScene 과 MainScene 구현

콘솔 창 제어 함수 구현


원하는 위치로 이동: Console_gotoxy

1
2
3
4
5
6
7
void Console_gotoxy(int x , int y)
{
    COORD pos;
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE) , pos);
}

기능: 콘솔 창 내부의 커서(글자가 써지는 위치)를 지정한 (x, y) 좌표로 순간 이동시킵니다.

필요 이유: 이 함수가 없다면 글자를 출력할 때마다 화면이 밑으로 계속 내려갑니다(스크롤). 하지만 gotoxy를 사용하면 화면을 다 지우지 않고도 특정 위치의 글자만 덮어써서 업데이트할 수 있어, 체력바나 맵을 그릴 때 필수적입니다.

마우스 클릭 멈춤 방지

1
2
3
4
5
6
7
void DisableQuickEdit()
{
    HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
    DWORD prev_mode;
    GetConsoleMode(hInput , &prev_mode);
    SetConsoleMode(hInput , prev_mode & ~ENABLE_QUICK_EDIT_MODE);
}

기능: 콘솔 창의 빠른 편집 모드를 강제로 꺼버립니다.

필요 이유: 윈도우 콘솔 창은 기본적으로 마우스로 화면을 클릭하거나 드래그하면, 복사 대기 상태가 되면서 실행 중인 프로그램(게임 루프)이 일시 정지되어 버립니다. 유저가 실수로 화면을 클릭해서 게임이 멈추는 사고를 막으려면 게임 시작 시 반드시 이 함수를 호출해야 합니다.

깜빡이는 커서 숨기기

1
2
3
4
5
6
7
void SetCursorVisible(bool isVisible)
{
    CONSOLE_CURSOR_INFO cursorInfo;
    GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE) , &cursorInfo);
    cursorInfo.bVisible = isVisible; // true면 보임, false면 숨김
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE) , &cursorInfo);
}

기능: 콘솔 화면에서 글자를 입력할 때 깜빡거리는 언더바(_) 모양의 커서를 숨기거나 다시 나타나게 합니다. false를 넣으면 숨겨집니다.

필요 이유: gotoxy를 이용해 화면을 아주 빠르게 다시 그릴 때, 커서를 숨기지 않으면 화면 여기저기서 커서가 번쩍번쩍 깜빡거리는 현상이 발생합니다. 깔끔한 게임 화면을 위해 커서는 보통 렌더링 전에 숨겨둡니다.

This post is licensed under CC BY 4.0 by the author.