1. 포트리스 뼈대 잡기

a. UIManager 및 리소스 추가하기

  • Resources 추가: 받은 리소스를 프로젝트 내 Game 폴더에 넣음. 이는 리소스가 엔진 관련이 아니라 콘텐츠 관련임을 암시.
  • UIManager 역할: UI 요소의 좌표와 세부적인 설정 관리. 렌더링에 필요한 좌표와 설정값을 제공.

b. Values.h 파일 추가하기

  • Values.h: 자주 사용하는 상수나 설정값을 관리.
  • pch.h 추가: Values.h 파일을 pch.h(precompiled header)에 추가하여 모든 소스 파일에서 쉽게 접근 가능하게 함.

c. ResourceManager 수정하기

  • 받은 Resources 추가: 기존 플레이어 리소스를 삭제하고 새로운 리소스를 추가.

d. Fortress 게임 뼈대 잡기

  • 폴더 구조: GameFortress 폴더 생성.
  • 씬 클래스 구현:
    • MenuScene: 게임 시작 시 표시되는 메뉴 화면.
    • FortressScene: 게임 화면.
    • 둘 다 Scene 클래스를 상속받아 구현.

e. SceneManager에 Scene 추가하기

  • SceneManager 등록: MenuScene과 FortressScene을 SceneManager에 등록.
  • 초기화: 게임 시작 시 MenuScene이 기본적으로 표시되도록 설정.

2. 씬 구현하기

a. MenuScene 구현

  • Update 함수: 키 입력 이벤트를 처리하여 게임 화면으로 전환.
  • 렌더링 코드 생성: 화면 요소를 그리는 코드 작성.
  • 네트워크 통신: 온라인 게임이라면 이 부분에 네트워크 로직 추가.

b. FortressScene 구현

  • UI 설계: Fortress UI 구현.
    • UI를 Manager로 관리할지 고민.
    • 최적 설계는 Base UI 객체를 만들어 관리하는 방법.
    • 복잡성을 줄이기 위해 매니저 방식 채택.

3. 플레이어 등장

a. 플레이어 특성 생성

  1. 코드 정리:
    • 불필요한 코드 제거 및 기본 구조 생성.
  2. 플레이어 타입(enum):
    • enum을 사용하여 직업군 타입 관리.
    • 직업별로 별도 클래스 분리(유지보수성 향상).

b. 플레이어 등장

  • 포트리스씬에 플레이어 생성:
    • 원하는 값으로 멤버 변수 초기화.
    • 포지션 설정 및 렌더링.
  • DeltaTime 적용: 게임 루프에서 복사 방식 순회로 성능 최적화.

c. 플레이어 크기 수정

  1. 크기 수정:
    • 메쉬의 최대/최소 좌표값을 기반으로 비율 조정.
    • 음수값은 좌우반전을 처리.
  2. 렌더링 비율 조정:
    • 비율에 따라 파일의 가로, 세로값 보정.

4. 플레이어 이동 구현

a. 방향 특성 생성

  • Object에 방향 코드 추가:
    • 플레이어가 아닌 오브젝트 특성으로 이동.

b. 플레이어 방향 변경

  • 키 입력 처리:
    • 방향값 변경 후 다른 렌더링 적용.

5. 플레이어 턴제 구현

a. 플레이어 턴제 생성

  • 포신 각도 및 턴 데이터 추가:
    • 특정 플레이어 턴일 때만 이동 가능.
  • UI 초기화:
    • 턴별 UI 초기화 로직 구현.

b. UI 구현

  • 플레이어 활성화 표시:
    • UIManager에서 활성화된 플레이어를 렌더링.
  • 시간 관리 문제:
    • UI와 데이터가 중복 관리되는 문제 발생.

6. 포신과 총알 구현

a. 포신의 각도 조정

  • Clamp 함수 사용:
    • 각도 값 제한.

b. 총알 생성

  • 총알 클래스 설계:
    • 충돌 판정 및 속도 관리.
  • 총알 생성과 속도 설정:
    • 입력값 기반 속도 설정 및 이동 구현.

c. 포물선 및 바람 영향

  • 가속도와 중력:
    • 속도와 가속도를 기반으로 포물선 구현.
  • 바람:
    • X축 가속도 추가.

7. 충돌 처리

a. 충돌 감지

  • 충돌 로직 구현:
    • 소유주와의 충돌 방지 로직 포함.
    • 충돌 시 턴 종료.

8. 나머지 구현

a. 스테미너 UI

  • 스테미너 감소:
    • 플레이어 움직임에 따른 스테미너 감소 로직.

b. 다양한 미사일 구현

  • 미사일 유형 추가:
    • 유도탄 기능 추가.

전체적으로 방대한 코드와 설명을 완벽히 한 줄 한 줄 꼼꼼하게 설명하려면 상당한 분량과 시간이 소요됩니다. 지금부터 요청에 따라 한 줄 한 줄 꼼꼼하게 분석과 설명을 시작하겠습니다. 한 번에 모든 내용을 다루기보다는, 먼저 필요한 부분부터 진행하며 이후 요청에 따라 다른 부분으로 이어 나가겠습니다.

이 설명은 제공된 목차와 내용을 기반으로 차례대로 진행하며, 모든 코드의 의미를 세세히 다룹니다.


1. 헤더 파일과 상수 정의

#pragma once
const int32 GWinSizeX = 800;
const int32 GWinSizeY = 600;
const int32 GMinimapSizeX = 200;
const int32 GMinimapSizeY = 128;
const float PI = 3.1415926f;

한 줄씩 분석

  1. #pragma once

    • 역할: 헤더 파일의 중복 포함을 방지하기 위한 지시어입니다.
      예를 들어, 동일한 헤더 파일이 여러 번 포함될 경우 컴파일러가 중복 정의 에러를 방지하도록 해줍니다.
      추가 설명: 오래된 방식인 include guard(예: #ifndef ... #define)를 대체하는 현대적인 방식입니다.
  2. const int32 GWinSizeX = 800;

    • 역할: 게임 창의 가로 크기를 800으로 설정합니다.
      • 이유: 상수로 정의하여 코드 전역에서 게임 창 크기를 변경할 경우, 해당 값을 쉽게 수정할 수 있습니다.
      • int32: 32비트 정수형 타입(정확한 크기를 보장).
  3. const int32 GWinSizeY = 600;

    • 역할: 게임 창의 세로 크기를 600으로 설정합니다.
      • 게임 화면의 해상도 관련 작업에서 사용됩니다.
      • 4:3 비율의 해상도로 설정되어 있으며, 고정된 게임 화면 크기를 유지합니다.
  4. const int32 GMinimapSizeX = 200;

    • 역할: 미니맵의 가로 크기를 200으로 설정합니다.
      • 게임의 HUD(Heads-Up Display) 구성 요소인 미니맵에서 사용됩니다.
      • 미니맵의 크기를 고정값으로 설정하여 일관성을 유지합니다.
  5. const int32 GMinimapSizeY = 128;

    • 역할: 미니맵의 세로 크기를 128로 설정합니다.
      • 미니맵은 보조 UI로, 주로 위치 정보를 제공하는 역할을 합니다.
  6. const float PI = 3.1415926f;

    • 역할: 상수 PI 값을 정의하여 각도나 원 관련 수학 연산에서 사용됩니다.
      • float 타입으로 정의하여 소수점 계산 시 유효 숫자를 제한.
      • 게임 물리 연산(예: 발사체 궤적, 회전)에 유용합니다.

2. LineMesh 클래스

헤더 파일 분석

#pragma once
#include "ResourceBase.h"

class LineMesh : public ResourceBase
{
public:
    void Save(wstring path);
    void Load(wstring path);
    void Render(HDC hdc, Pos pos, float ratioX = 1.0f, float ratioY = 1.0f) const;

    vector<pair<POINT, POINT>>& GetLines() { return _lines; }

protected:
    vector<pair<POINT, POINT>> _lines;
    int32 _width = 0;
    int32 _height = 0;
};

한 줄씩 분석

  1. #pragma once

    • 중복 포함 방지를 위한 지시어입니다(위 설명과 동일).
  2. #include "ResourceBase.h"

    • 역할: LineMesh 클래스가 상속받는 ResourceBase 클래스의 정의를 가져옵니다.
      • 추정: ResourceBase는 모든 리소스의 공통 동작(로드, 저장 등)을 정의한 베이스 클래스입니다.
  3. class LineMesh : public ResourceBase

    • 역할: LineMeshResourceBase의 자식 클래스이며, 선 메쉬(Line Mesh)를 관리하는 역할을 합니다.
      • "선 메쉬": 선으로 이루어진 그래픽 데이터를 저장하고 관리.
      • 상속 이유: 공통 리소스 작업(예: 파일 저장/로드)을 재사용하기 위함.
  4. public:

    • 클래스 외부에서 접근 가능한 멤버와 함수를 선언.
  5. void Save(wstring path);

    • 역할: _lines 데이터를 주어진 경로(path)의 파일에 저장합니다.
      • wstring: 유니코드 문자열 타입으로, 다국어 파일 경로를 지원합니다.
  6. void Load(wstring path);

    • 역할: 지정된 파일에서 _lines 데이터를 읽어옵니다.
      • 게임 시작 시 미리 정의된 메쉬 데이터를 로드할 때 사용됩니다.
  7. void Render(HDC hdc, Pos pos, float ratioX = 1.0f, float ratioY = 1.0f) const;

    • 역할: HDC(디바이스 컨텍스트)를 사용해 _lines 데이터를 화면에 렌더링합니다.
      • Pos pos: 렌더링 시작 좌표를 설정합니다.
      • ratioX, ratioY: 가로 및 세로 비율로, 기본값은 1.0(기본 크기)입니다.
  8. vector<pair<POINT, POINT>>& GetLines();

    • 역할: _lines 멤버 변수(선 데이터 벡터)의 참조를 반환합니다.
      • pair<POINT, POINT>: 각 선의 시작점(POINT)과 끝점(POINT)을 저장.
      • 외부에서 _lines를 수정하거나 읽어야 할 때 사용됩니다.
  9. protected:

    • 자식 클래스에서 접근할 수 있는 멤버와 함수를 선언.
  10. vector<pair<POINT, POINT>> _lines;

    • 역할: 선 데이터를 저장하는 멤버 변수입니다.
      • POINT: Windows API에서 사용하는 2D 좌표 구조체.
      • 각 선은 시작점과 끝점을 한 쌍(pair)으로 표현합니다.
  11. int32 _width = 0;

    • 역할: 메쉬의 가로 크기입니다.
      • 초기값 0으로 설정.
  12. int32 _height = 0;

    • 역할: 메쉬의 세로 크기입니다.
      • 초기값 0으로 설정.

구현 파일 분석

Save 함수

void LineMesh::Save(wstring path)
{
    wofstream file;
    file.open(path);

    int32 minX = INT32_MAX, maxX = INT32_MIN, minY = INT32_MAX, maxY = INT32_MIN;

    for (auto& line : _lines)
    {
        POINT from = line.first;
        POINT to = line.second;

        minX = min(min(minX, from.x), to.x);
        maxX = max(max(maxX, from.x), to.x);
        minY = min(min(minY, from.y), to.y);
        maxY = max(max(maxY, from.y), to.y);
    }

    int32 midX = (maxX + minX) / 2;
    int32 midY = (maxY + minY) / 2;

    file << static_cast<int32>(_lines.size()) << endl;

    for (auto& line : _lines)
    {
        POINT from = line.first;
        from.x -= midX;
        from.y -= midY;

        POINT to = line.second;
        to.x -= midX;
        to.y -= midY;

        wstring str = std::format(L"({0},{1})->({2},{3})", from.x, from.y, to.x, to.y);
        file << str << endl;
    }

    file.close();
}

한 줄씩 분석

  1. wofstream file;

    • 역할: 유니코드 텍스트 파일을 쓰기 모드로 열기 위한 파일 스트림 객체입니다.
  2. file.open(path);

    • 역할: 주어진 경로(path)의 파일을 엽니다.
      • 경로에 해당 파일이 없으면 새로 생성됩니다.
  3. int32 minX = INT32_MAX, maxX = INT32_MIN, minY = INT32_MAX, maxY = INT32_MIN;

    • 역할: _lines의 모든 선 데이터를 기준으로 최소/최대 x, y 좌표값을 초기화합니다.
  4. for (auto& line : _lines)

    • 역할: _lines 벡터를 순회하며 각 선 데이터를 처리합니다.
  5. POINT from = line.first;

    • 역할: 선의 시작점 좌표를 가져옵니다.
  6. POINT to = line.second;

    • 역할: 선의 끝점 좌표를 가져옵니다.

Save 함수**

  1. minX = min(min(minX, from.x), to.x);

    • 역할:
      • 현재 minX(최소 x 좌표값)를 업데이트합니다.
      • 현재 선의 시작점(from.x)과 끝점(to.x) 중 더 작은 값을 비교하고, minX보다 작으면 업데이트합니다.
    • 사용 이유:
      • _lines 내 모든 선의 좌표를 정규화(중앙 좌표 기준 변환)하기 위해 최소값을 계산합니다.
  2. maxX = max(max(maxX, from.x), to.x);

    • 역할:
      • 현재 maxX(최대 x 좌표값)를 업데이트합니다.
      • 현재 선의 시작점(from.x)과 끝점(to.x) 중 더 큰 값을 비교하고, maxX보다 크면 업데이트합니다.
    • 사용 이유:
      • 정규화 시 최대 x 좌표값이 필요합니다.
  3. minY = min(min(minY, from.y), to.y);

    • 역할:
      • 현재 minY(최소 y 좌표값)를 업데이트합니다.
      • 현재 선의 시작점(from.y)과 끝점(to.y) 중 더 작은 값을 비교하고, minY보다 작으면 업데이트합니다.
  4. maxY = max(max(maxY, from.y), to.y);

    • 역할:
      • 현재 maxY(최대 y 좌표값)를 업데이트합니다.
      • 현재 선의 시작점(from.y)과 끝점(to.y) 중 더 큰 값을 비교하고, maxY보다 크면 업데이트합니다.

정규화 작업

  1. int32 midX = (maxX + minX) / 2;

    • 역할:
      • 모든 선의 x 좌표를 중앙 기준으로 정규화하기 위해 중앙 x 좌표(midX)를 계산합니다.
    • 사용 이유:
      • (maxX + minX) / 2는 x 좌표의 중앙값입니다.
      • 정규화할 때, 각 x 좌표에서 midX를 빼면 중앙 기준으로 이동합니다.
  2. int32 midY = (maxY + minY) / 2;

    • 역할:
      • 모든 선의 y 좌표를 중앙 기준으로 정규화하기 위해 중앙 y 좌표(midY)를 계산합니다.

선 데이터 저장

  1. file << static_cast<int32>(_lines.size()) << endl;

    • 역할:
      • _lines에 저장된 선의 개수를 파일의 첫 번째 줄에 기록합니다.
      • 이후 데이터를 읽을 때 저장된 선의 개수를 알고 있어야 반복적으로 데이터를 읽을 수 있습니다.
  2. for (auto& line : _lines)

    • 역할: _lines 벡터를 순회하며 각 선 데이터를 파일에 저장합니다.
  3. POINT from = line.first;

    • 역할: 현재 선의 시작점 좌표를 가져옵니다.
  4. from.x -= midX; from.y -= midY;

    • 역할:
      • 선의 시작점 좌표를 중앙 기준으로 이동시킵니다(정규화).
      • from.x -= midX: x 좌표에서 중앙 x 좌표(midX)를 빼서 정규화.
      • from.y -= midY: y 좌표에서 중앙 y 좌표(midY)를 빼서 정규화.
  5. POINT to = line.second;

    • 역할: 현재 선의 끝점 좌표를 가져옵니다.
  6. to.x -= midX; to.y -= midY;

    • 역할:
      • 선의 끝점 좌표를 중앙 기준으로 이동시킵니다(정규화).
  7. wstring str = std::format(L"({0},{1})->({2},{3})", from.x, from.y, to.x, to.y);

    • 역할:
      • 정규화된 시작점과 끝점 좌표를 특정 형식으로 변환합니다.
      • 출력 형식: (from.x, from.y)->(to.x, to.y).
  8. file << str << endl;

    • 역할:
      • 형식화된 선 데이터를 파일에 기록합니다.
      • 각 선은 파일의 새로운 줄에 저장됩니다.
  9. file.close();

    • 역할:
      • 파일 스트림을 닫고 메모리 리소스를 해제합니다.

Load 함수 분석

void LineMesh::Load(wstring path)
{
    wifstream file;
    file.open(path);

    int32 count;
    file >> count;

    _lines.clear();

    for (int32 i = 0; i < count; i++)
    {
        POINT pt1 = {}, pt2 = {};
        wstring str;
        file >> str;

        ::swscanf_s(str.c_str(), L"(%d,%d)->(%d,%d)", &pt1.x, &pt1.y, &pt2.x, &pt2.y);
        _lines.push_back(make_pair(pt1, pt2));
    }

    file.close();
}

한 줄씩 분석

  1. wifstream file;

    • 역할: 유니코드 텍스트 파일을 읽기 모드로 열기 위한 파일 스트림 객체입니다.
  2. file.open(path);

    • 역할: 주어진 경로(path)의 파일을 엽니다.
  3. int32 count;

    • 역할: 파일에서 읽어올 선의 개수를 저장하기 위한 변수입니다.
  4. file >> count;

    • 역할: 파일의 첫 번째 줄에서 선의 개수를 읽어옵니다.
  5. _lines.clear();

    • 역할: 기존에 저장된 _lines 데이터를 모두 제거합니다.
      • 새 데이터를 로드하기 전에 초기화 과정.
  6. for (int32 i = 0; i < count; i++)

    • 역할: 읽어온 선의 개수만큼 반복하며 데이터를 처리합니다.
  7. POINT pt1 = {}, pt2 = {};

    • 역할: 현재 선의 시작점(pt1)과 끝점(pt2) 좌표를 저장할 변수를 선언 및 초기화합니다.
  8. wstring str;

    • 역할: 한 줄씩 읽어온 데이터를 저장할 유니코드 문자열 변수입니다.
  9. file >> str;

    • 역할: 파일에서 한 줄의 데이터를 읽어옵니다.
  10. ::swscanf_s(str.c_str(), L"(%d,%d)->(%d,%d)", &pt1.x, &pt1.y, &pt2.x, &pt2.y);

    • 역할:
      • 읽어온 문자열(str)을 파싱하여 시작점(pt1)과 끝점(pt2)의 좌표값을 추출합니다.
      • (%d,%d)->(%d,%d) 형식을 사용하여 좌표 데이터를 구분합니다.
  11. _lines.push_back(make_pair(pt1, pt2));

    • 역할:
      • 시작점과 끝점을 pair로 묶어 _lines 벡터에 추가합니다.
  12. file.close();

    • 역할:
      • 파일 스트림을 닫고 메모리 리소스를 해제합니다.

계속해서 요청하신 다른 함수와 클래스에 대해 꼼꼼히 설명하겠습니다. 이어서 다룰 함수와 클래스 목록을 명시하거나 요청하시면 그 순서대로 진행하겠습니다. 우선 요청에 포함될 가능성이 높은 부분부터 차례로 진행하겠습니다.


LineMesh::Render 함수

void LineMesh::Render(HDC hdc, Pos pos, float ratioX, float ratioY) const
{
    for (auto& line : _lines)
    {
        POINT pt1 = line.first;
        POINT pt2 = line.second;

        Pos pos1 = { pos.x + static_cast<float>(pt1.x) * ratioX, pos.y + static_cast<float>(pt1.y) * ratioY };
        Pos pos2 = { pos.x + static_cast<float>(pt2.x) * ratioX, pos.y + static_cast<float>(pt2.y) * ratioY };

        Utils::DrawLine(hdc, pos1, pos2);
    }
}

한 줄씩 분석

  1. void LineMesh::Render(HDC hdc, Pos pos, float ratioX, float ratioY) const
    • 역할:
      • LineMesh에 저장된 선 데이터를 화면에 그립니다.
    • 매개변수:
      • HDC hdc:
        • 디바이스 컨텍스트 핸들로, 화면에 그림을 그릴 수 있는 Windows GDI(Graphics Device Interface) 객체입니다.
      • Pos pos:
        • 렌더링 시작 좌표로, 모든 선의 좌표를 이 위치를 기준으로 이동하여 그립니다.
      • float ratioX, float ratioY:
        • x축 및 y축 비율로, 선 크기를 조정하는 데 사용됩니다.
      • const:
        • 이 함수는 객체 상태를 변경하지 않음을 명시합니다.

  1. for (auto& line : _lines)

    • 역할:
      • _lines 벡터를 순회하며 각 선을 화면에 그립니다.
    • _lines는 선 데이터(시작점과 끝점의 좌표)를 저장한 vector<pair<POINT, POINT>>입니다.
  2. POINT pt1 = line.first;

    • 역할:
      • 현재 선의 시작점 좌표를 pt1에 저장합니다.
  3. POINT pt2 = line.second;

    • 역할:
      • 현재 선의 끝점 좌표를 pt2에 저장합니다.
  4. Pos pos1 = { pos.x + static_cast<float>(pt1.x) * ratioX, pos.y + static_cast<float>(pt1.y) * ratioY };

    • 역할:
      • 시작점 좌표(pt1)를 기준 위치(pos)와 비율(ratioX, ratioY)에 따라 조정합니다.
    • 작동 방식:
      • pt1.x 좌표를 ratioX로 조정하고, 기준 x 좌표(pos.x)를 더합니다.
      • pt1.y 좌표도 동일하게 조정합니다.
  5. Pos pos2 = { pos.x + static_cast<float>(pt2.x) * ratioX, pos.y + static_cast<float>(pt2.y) * ratioY };

    • 역할:
      • 끝점 좌표(pt2)를 기준 위치(pos)와 비율(ratioX, ratioY)에 따라 조정합니다.
  6. Utils::DrawLine(hdc, pos1, pos2);

    • 역할:
      • Utils 클래스의 DrawLine 함수를 호출하여, 시작점(pos1)과 끝점(pos2)을 연결하는 선을 화면에 그립니다.
    • 세부 동작:
      • Windows GDI를 사용해 디바이스 컨텍스트(hdc)에 선을 그립니다.

Object 클래스

class Object
{
public:
    Object(ObjectType type);
    virtual ~Object();

    virtual void Init() abstract;
    virtual void Update() abstract;
    virtual void Render(HDC hdc) abstract;

    ObjectType GetObjectType() { return _type; }
    Vector GetPos() { return _pos; }
    void SetPos(Vector pos) { _pos = pos; }
    float GetRadius() { return _radius; }

protected:
    ObjectType _type = ObjectType::None;
    MoveDir _dir = MoveDir::Right;
    Stat _stat = {};
    Vector _pos = {};
    float _radius = 0.f;
};

한 줄씩 분석

  1. class Object

    • 역할:
      • 모든 게임 오브젝트(플레이어, 총알 등)의 공통 속성과 동작을 정의한 추상 클래스입니다.
    • 추상 클래스 이유:
      • Init, Update, Render는 순수 가상 함수(= abstract)로 선언되어 있습니다. 이를 상속받은 클래스에서 반드시 구현해야 합니다.
  2. public:

    • 공개 멤버 선언: 외부에서 접근 가능한 함수와 멤버를 정의합니다.
  3. Object(ObjectType type);

    • 생성자:
      • 객체 유형(type)을 초기화합니다.
      • ObjectType플레이어, 발사체 등 객체의 종류를 나타내는 열거형(enum) 타입으로 추정됩니다.
  4. virtual ~Object();

    • 가상 소멸자:
      • 객체가 삭제될 때, 자식 클래스의 소멸자가 올바르게 호출되도록 합니다.
  5. virtual void Init() abstract;

    • 순수 가상 함수:
      • 오브젝트 초기화 작업을 수행하는 함수로, 상속받은 클래스에서 구현됩니다.
  6. virtual void Update() abstract;

    • 순수 가상 함수:
      • 매 프레임 오브젝트의 상태를 갱신하는 함수입니다.
      • 예: 플레이어 이동, 총알의 위치 업데이트 등.
  7. virtual void Render(HDC hdc) abstract;

    • 순수 가상 함수:
      • 오브젝트를 화면에 그리는 함수입니다.
      • 상속받은 클래스에서 GDI 또는 DirectX 등을 사용하여 구현합니다.
  8. ObjectType GetObjectType() { return _type; }

    • 역할:
      • 객체 유형(_type)을 반환합니다.
      • 용도:
        • 게임 로직에서 객체를 구분할 때 사용.
        • 예: 충돌 감지 시, 객체가 플레이어인지 발사체인지 확인.
  9. Vector GetPos() { return _pos; }

    • 역할:
      • 객체의 현재 위치(_pos)를 반환합니다.
      • Vector 타입:
        • x, y 좌표를 나타내는 2D 벡터 구조체로 추정됩니다.
  10. void SetPos(Vector pos) { _pos = pos; }

    • 역할:
      • 객체의 위치를 설정합니다.
  11. float GetRadius() { return _radius; }

    • 역할:
      • 객체의 충돌 반지름(_radius)을 반환합니다.
      • 용도:
        • 충돌 판정 시 사용.

멤버 변수 분석

  1. ObjectType _type = ObjectType::None;

    • 역할:
      • 객체의 유형을 저장합니다.
      • 예: ObjectType::Player, ObjectType::Bullet 등.
    • 초기값: ObjectType::None(기본값).
  2. MoveDir _dir = MoveDir::Right;

    • 역할:
      • 객체의 이동 방향을 저장합니다.
      • 예: MoveDir::Left, MoveDir::Right.
  3. Stat _stat = {};

    • 역할:
      • 객체의 상태(속성)를 저장합니다.
      • 추정:
        • 체력(hp), 속도(speed) 등의 데이터를 포함하는 구조체.
  4. Vector _pos = {};

    • 역할:
      • 객체의 현재 위치를 저장합니다.
  5. float _radius = 0.f;

    • 역할:
      • 충돌 판정을 위한 객체 반지름을 저장합니다.

요청하실 클래스 또는 함수

다음으로 다룰 클래스 또는 함수에 대한 요청 사항을 알려주시면, 이어서 꼼꼼히 한 줄씩 분석해 드리겠습니다.
예:

  • Player 클래스
  • SceneManager 클래스
  • 특정 메서드 (Bullet::Update, FortressScene::ChangePlayerTurn 등)

이제 설명하지 않은 클래스와 함수들을 계속해서 꼼꼼히 설명하겠습니다. 아래는 남은 클래스와 함수들의 목록입니다. 순서대로 진행하며 한 줄 한 줄 설명하겠습니다.


Player 클래스

헤더 파일

class Player : public Object
{
public:
    Player();
    virtual ~Player() override;

    virtual void Init() override;
    virtual void Update() override;
    virtual void Render(HDC hdc) override;

    wstring GetMeshKey();
    void SetPlayerId(int32 playerId);
    void SetPlayerType(PlayerType playerType);
    void SetPlayerTurn(bool playerTurn);

    int32 GetPlayerId();
    PlayerType GetPlayerType();
    bool GetPlayerTurn();

private:
    void UpdateFireAngle();

private:
    int32 _playerId = 0;
    PlayerType _playerType = PlayerType::MissileTank;
    bool _playerTurn = false;
    float _fireAngle = 0.f;
};

한 줄씩 분석

  1. class Player : public Object

    • 역할:
      • Player는 게임의 플레이어 오브젝트를 나타내며, Object 클래스를 상속받아 구현되었습니다.
    • 상속 이유:
      • Object 클래스의 공통 기능(위치, 충돌 반지름, 렌더링 등)을 재사용.
  2. public:

    • 공개 멤버 선언: 외부에서 접근 가능한 함수 및 변수를 정의합니다.
  3. Player();

    • 역할:
      • Player 클래스의 생성자로, 초기화를 담당합니다.
  4. virtual ~Player() override;

    • 역할:
      • Player 클래스의 소멸자로, 부모 클래스의 소멸자와 함께 호출됩니다.
  5. virtual void Init() override;

    • 역할:
      • 플레이어 객체의 초기 상태(위치, 속성 등)를 설정합니다.
  6. virtual void Update() override;

    • 역할:
      • 매 프레임 호출되며, 플레이어의 상태를 갱신합니다.
      • : 이동, 발사 각도 조정, 키 입력 처리 등.
  7. virtual void Render(HDC hdc) override;

    • 역할:
      • 플레이어를 화면에 그리는 함수입니다.
      • hdc를 사용하여 그래픽을 그립니다.
  8. wstring GetMeshKey();

    • 역할:
      • 플레이어의 현재 상태나 타입에 따라 메쉬 키 값을 반환합니다.
  9. void SetPlayerId(int32 playerId);

    • 역할:
      • 플레이어의 고유 ID를 설정합니다.
  10. void SetPlayerType(PlayerType playerType);

    • 역할:
      • 플레이어의 유형(MissileTank, CannonTank 등)을 설정합니다.
  11. void SetPlayerTurn(bool playerTurn);

    • 역할:
      • 현재 플레이어가 턴을 가졌는지 여부를 설정합니다.
  12. int32 GetPlayerId();

    • 역할:
      • 플레이어의 고유 ID를 반환합니다.
  13. PlayerType GetPlayerType();

    • 역할:
      • 플레이어의 유형(MissileTank, CannonTank 등)을 반환합니다.
  14. bool GetPlayerTurn();

    • 역할:
      • 현재 플레이어가 턴을 가졌는지 여부를 반환합니다.
  15. void UpdateFireAngle();

    • 역할:
      • 발사 각도를 업데이트합니다.

구현 파일

Player::Init 함수
void Player::Init()
{
    _stat.hp = 100;
    _stat.maxHp = 100;
    _stat.speed = 500;
    _pos.x = 0;
    _pos.y = 0;
    _radius = 50.f;
    _fireAngle = 30.f;
}
  1. _stat.hp = 100;

    • 역할:
      • 플레이어의 초기 체력을 100으로 설정합니다.
  2. _stat.maxHp = 100;

    • 역할:
      • 플레이어의 최대 체력을 100으로 설정합니다.
  3. _stat.speed = 500;

    • 역할:
      • 플레이어의 이동 속도를 설정합니다.
      • 단위: 초당 픽셀 이동 거리.
  4. _pos.x = 0;, _pos.y = 0;

    • 역할:
      • 플레이어의 초기 위치를 (0, 0)으로 설정합니다.
  5. _radius = 50.f;

    • 역할:
      • 플레이어의 충돌 판정을 위한 반지름을 설정합니다.
  6. _fireAngle = 30.f;

    • 역할:
      • 플레이어의 초기 발사 각도를 30도로 설정합니다.

Player::Update 함수
void Player::Update()
{
    float deltaTime = GET_SINGLE(TimeManager)->GetDeltaTime();

    if (GET_SINGLE(InputManager)->GetButton(KeyType::A))
    {
        _pos.x -= _stat.speed * deltaTime;
        _dir = MoveDir::Left;
    }

    if (GET_SINGLE(InputManager)->GetButton(KeyType::D))
    {
        _pos.x += _stat.speed * deltaTime;
        _dir = MoveDir::Right;
    }

    if (GET_SINGLE(InputManager)->GetButton(KeyType::SpaceBar))
    {
        float percent = GET_SINGLE(UIManager)->GetPowerPercent();
        percent = min(100, percent + 100 * deltaTime);
        GET_SINGLE(UIManager)->SetPowerPercent(percent);
    }
}
  1. float deltaTime = GET_SINGLE(TimeManager)->GetDeltaTime();

    • 역할:
      • 현재 프레임의 경과 시간을 가져옵니다.
      • 용도:
        • 프레임 독립적인 움직임(속도와 시간을 곱해 이동 거리를 계산).
  2. if (GET_SINGLE(InputManager)->GetButton(KeyType::A))

    • 역할:
      • 키보드의 A 키가 눌렸는지 확인합니다.
  3. _pos.x -= _stat.speed * deltaTime;

    • 역할:
      • 플레이어를 왼쪽으로 이동합니다.
      • 이동 거리 = 속도 × 경과 시간.
  4. _dir = MoveDir::Left;

    • 역할:
      • 이동 방향을 왼쪽으로 설정합니다.
  5. if (GET_SINGLE(InputManager)->GetButton(KeyType::D))

    • 역할:
      • 키보드의 D 키가 눌렸는지 확인합니다.
  6. _pos.x += _stat.speed * deltaTime;

    • 역할:
      • 플레이어를 오른쪽으로 이동합니다.
  7. _dir = MoveDir::Right;

    • 역할:
      • 이동 방향을 오른쪽으로 설정합니다.
  8. if (GET_SINGLE(InputManager)->GetButton(KeyType::SpaceBar))

    • 역할:
      • 키보드의 스페이스바가 눌렸는지 확인합니다.
  9. float percent = GET_SINGLE(UIManager)->GetPowerPercent();

    • 역할:
      • 현재 발사력을 가져옵니다.
  10. percent = min(100, percent + 100 * deltaTime);

    • 역할:
      • 발사력을 시간에 따라 증가시킵니다.
      • 최대값 100으로 제한.
  11. GET_SINGLE(UIManager)->SetPowerPercent(percent);

    • 역할:
      • 갱신된 발사력을 UI에 반영합니다.

SceneManager 클래스

헤더 파일

class SceneManager
{
    DECLARE_SINGLE(SceneManager);

public:
    void Init();
    void Update();
    void Render(HDC hdc);
    void Clear();
    void ChangeScene(SceneType sceneType);
    Scene* GetCurrentScene();

private:
    Scene* _scene;
    SceneType _sceneType = SceneType::None;
};

한 줄씩 분석

  1. DECLARE_SINGLE(SceneManager)

    • 역할:
      • 싱글톤 패턴을 선언합니다.
      • SceneManager는 하나의 인스턴스만 생성됩니다.
  2. void Init();

    • 역할:
      • 씬 매니저를 초기화합니다.
  3. void Update();

    • 역할:
      • 현재 활성화된 씬을 업데이트합니다.
  4. void Render(HDC hdc);

    • 역할:
      • 현재 활성화된 씬을 렌더링합니다.
  5. void Clear();

    • 역할:
      • 씬 매니저를 정리합니다.
  6. void ChangeScene(SceneType sceneType);

    • 역할:
      • 현재 씬을 새 씬으로 변경합니다.
  7. Scene* GetCurrentScene();

    • 역할:
      • 현재 활성화된 씬을 반환합니다.
  8. Scene* _scene;

    • 역할:
      • 현재 활성화된 씬을 가리키는 포인터입니다.
  9. SceneType _sceneType = SceneType::None;

    • 역할:
      • 현재 씬의 타입을 저장합니다.

남은 요청

위 클래스와 함수에 이어 분석하지 않은 부분(예: Bullet, FortressScene)을 포함하여 계속 분석하겠습니다.
추가 요청 사항을 알려주시면 해당 내용을 우선적으로 진행합니다!

계속해서 남은 클래스와 함수에 대해 꼼꼼히 설명하겠습니다. 아래는 아직 다루지 않은 주요 클래스와 함수에 대한 분석입니다.


Bullet 클래스

헤더 파일

class Bullet : public Object
{
public:
    Bullet();
    ~Bullet();

    virtual void Init() override;
    virtual void Update() override;
    virtual void Render(HDC hdc) override;

    Vector GetSpeed();
    void SetSpeed(Vector speed);

    void SetOwner(Object* owner);
    Object* GetOwner();

protected:
    Vector _speed = {};
    Object* _owner = nullptr;
};

한 줄씩 분석

  1. class Bullet : public Object

    • 역할:
      • Bullet은 게임 내 발사체(총알, 미사일 등)를 나타내며, Object를 상속받아 구현되었습니다.
    • 상속 이유:
      • 위치, 충돌 반지름, 렌더링 같은 공통 동작을 Object로부터 상속받아 재사용합니다.
  2. Bullet();

    • 역할:
      • Bullet의 생성자로, 초기화를 수행합니다.
  3. ~Bullet();

    • 역할:
      • Bullet의 소멸자로, 리소스 해제를 처리합니다.
  4. virtual void Init() override;

    • 역할:
      • 발사체의 초기 상태를 설정합니다.
  5. virtual void Update() override;

    • 역할:
      • 매 프레임마다 발사체의 위치와 상태를 업데이트합니다.
  6. virtual void Render(HDC hdc) override;

    • 역할:
      • 발사체를 화면에 렌더링합니다.
  7. Vector GetSpeed();, void SetSpeed(Vector speed);

    • 역할:
      • 발사체의 속도를 가져오거나 설정합니다.
  8. void SetOwner(Object* owner);, Object* GetOwner();

    • 역할:
      • 발사체의 소유자(플레이어 등)를 설정하거나 반환합니다.
      • 용도:
        • 발사체가 소유자와 충돌하지 않도록 예외 처리할 때 사용됩니다.

구현 파일

Bullet::Init 함수
void Bullet::Init()
{
    _radius = 10.f;
}
  • 역할:
    • 발사체의 충돌 반지름을 설정합니다.

Bullet::Update 함수
void Bullet::Update()
{
    float deltaTime = GET_SINGLE(TimeManager)->GetDeltaTime();

    _pos += _speed * deltaTime; // 현재 속도와 경과 시간을 기반으로 위치 갱신
    _speed.y += 1000 * deltaTime; // 중력 효과 추가

    const vector<Object*>& objects = GET_SINGLE(ObjectManager)->GetObjects();
    for (Object* object : objects)
    {
        if (object->GetObjectType() != ObjectType::Player)
            continue;

        if (object == _owner)
            continue;

        Vector dir = _pos - object->GetPos();
        if (dir.Length() < _radius + object->GetRadius())
        {
            auto* scene = dynamic_cast<FortressScene*>(GET_SINGLE(SceneManager)->GetCurrentScene());
            if (scene)
                scene->ChangePlayerTurn();

            GET_SINGLE(ObjectManager)->Remove(this);
            return;
        }
    }

    if (_pos.y > GWinSizeY * 1.5f)
    {
        auto* scene = dynamic_cast<FortressScene*>(GET_SINGLE(SceneManager)->GetCurrentScene());
        if (scene)
            scene->ChangePlayerTurn();

        GET_SINGLE(ObjectManager)->Remove(this);
        return;
    }
}
  1. float deltaTime = GET_SINGLE(TimeManager)->GetDeltaTime();

    • 역할:
      • 현재 프레임의 경과 시간을 가져옵니다.
  2. _pos += _speed * deltaTime;

    • 역할:
      • 발사체의 위치를 속도와 경과 시간에 따라 갱신합니다.
  3. _speed.y += 1000 * deltaTime;

    • 역할:
      • 발사체에 중력 효과를 추가합니다.
  4. 충돌 감지 루프

    • 역할:
      • 발사체가 플레이어와 충돌했는지 확인합니다.
    • 세부 조건:
      • object->GetObjectType() != ObjectType::Player:
        • 충돌 대상이 플레이어가 아닌 경우 건너뜁니다.
      • object == _owner:
        • 발사체의 소유자인 경우 건너뜁니다.
      • dir.Length() < _radius + object->GetRadius():
        • 발사체와 플레이어의 중심 거리(dir.Length())가 두 객체의 반지름 합보다 작으면 충돌로 간주합니다.
  5. GET_SINGLE(ObjectManager)->Remove(this);

    • 역할:
      • 발사체를 게임에서 제거합니다.
  6. if (_pos.y > GWinSizeY * 1.5f)

    • 역할:
      • 발사체가 화면 아래로 벗어났는지 확인합니다.

FortressScene 클래스

헤더 파일

class FortressScene : public Scene
{
public:
    FortressScene();
    virtual ~FortressScene() override;

    virtual void Init() override;
    virtual void Update() override;
    virtual void Render(HDC hdc) override;

    void ChangePlayerTurn();

private:
    int32 _playerTurn = 0;
    float _sumTime = 0.f;
};

한 줄씩 분석

  1. class FortressScene : public Scene

    • 역할:
      • 포트리스 게임의 주요 씬으로, Scene 클래스를 상속받아 구현되었습니다.
    • 상속 이유:
      • Init, Update, Render와 같은 공통 작업을 재사용.
  2. FortressScene();

    • 역할:
      • FortressScene의 생성자로, 초기화를 수행합니다.
  3. virtual ~FortressScene() override;

    • 역할:
      • FortressScene의 소멸자로, 리소스 해제를 처리합니다.
  4. virtual void Init() override;

    • 역할:
      • 씬 초기화 작업을 수행합니다.
  5. virtual void Update() override;

    • 역할:
      • 매 프레임 씬 상태를 업데이트합니다.
  6. virtual void Render(HDC hdc) override;

    • 역할:
      • 씬을 화면에 렌더링합니다.
  7. void ChangePlayerTurn();

    • 역할:
      • 현재 플레이어 턴을 변경합니다.

구현 파일

FortressScene::Init 함수
void FortressScene::Init()
{
    GET_SINGLE(UIManager)->Init();

    Player* player1 = GET_SINGLE(ObjectManager)->CreateObject<Player>();
    player1->SetPlayerId(0);
    player1->SetPos({100, 400});
    player1->SetPlayerTurn(true);
    GET_SINGLE(ObjectManager)->Add(player1);

    Player* player2 = GET_SINGLE(ObjectManager)->CreateObject<Player>();
    player2->SetPlayerId(1);
    player2->SetPos({700, 400});
    player2->SetPlayerTurn(false);
    GET_SINGLE(ObjectManager)->Add(player2);

    _playerTurn = 0;
}
  1. GET_SINGLE(UIManager)->Init();

    • 역할:
      • UI 매니저를 초기화합니다.
  2. 플레이어 생성

    • 역할:
      • 두 명의 플레이어를 생성하고 위치와 ID를 설정합니다.

FortressScene::ChangePlayerTurn 함수
void FortressScene::ChangePlayerTurn()
{
    _playerTurn = (_playerTurn + 1) % 2;

    const auto& objects = GET_SINGLE(ObjectManager)->GetObjects();
    for (auto* object : objects)
    {
        if (object->GetObjectType() != ObjectType::Player)
            continue;

        Player* player = static_cast<Player*>(object);
        player->SetPlayerTurn(player->GetPlayerId() == _playerTurn);
    }

    GET_SINGLE(UIManager)->SetRemainTime(10);
}
  1. _playerTurn = (_playerTurn + 1) % 2;

    • 역할:
      • 플레이어 턴을 변경합니다. 턴은 두 명의 플레이어(0, 1) 사이에서 순환합니다.
  2. 플레이어 상태 업데이트

    • 역할:
      • 현재 턴의 플레이어를 활성화하고, 다른 플레이어는 비활성화합니다.

요청할 추가 클래스/함수

위에 설명하지 않은 다른 부분에 대해 더 요청하시면 계속해서 상세히 분석하겠습니다.
아직 다루지 않은 클래스와 함수들을 모두 설명하겠습니다. 아래는 분석이 필요한 모든 클래스를 꼼꼼히 다룬 목록입니다. 각각의 클래스와 함수에 대해 한 줄 한 줄 세세히 분석하겠습니다.


Scene 클래스

헤더 파일

class Scene
{
public:
    Scene() = default;
    virtual ~Scene() = default;

    virtual void Init() = 0;
    virtual void Update() = 0;
    virtual void Render(HDC hdc) = 0;
};

한 줄씩 분석

  1. class Scene

    • 역할:
      • 모든 씬 클래스(MenuScene, FortressScene 등)의 기본 구조를 제공하는 추상 클래스입니다.
      • Init, Update, Render를 자식 클래스에서 반드시 구현해야 합니다.
  2. Scene() = default;

    • 역할:
      • 기본 생성자를 컴파일러가 자동으로 생성합니다.
  3. virtual ~Scene() = default;

    • 역할:
      • 기본 소멸자를 컴파일러가 자동으로 생성합니다.
      • 가상 소멸자: 상속받은 클래스의 소멸자가 올바르게 호출되도록 합니다.
  4. virtual void Init() = 0;

    • 역할:
      • 씬 초기화를 담당하며, 자식 클래스에서 반드시 구현해야 하는 순수 가상 함수입니다.
  5. virtual void Update() = 0;

    • 역할:
      • 씬 업데이트 작업을 담당합니다(프레임마다 호출).
      • 자식 클래스에서 반드시 구현해야 합니다.
  6. virtual void Render(HDC hdc) = 0;

    • 역할:
      • 씬의 렌더링 작업을 담당합니다.
      • 자식 클래스에서 반드시 구현해야 합니다.

헤더 파일

class MenuScene : public Scene
{
public:
    MenuScene();
    virtual ~MenuScene() override;

    virtual void Init() override;
    virtual void Update() override;
    virtual void Render(HDC hdc) override;
};

한 줄씩 분석

  1. class MenuScene : public Scene

    • 역할:
      • 게임의 메뉴 화면을 나타내는 클래스이며, Scene을 상속받아 구현되었습니다.
  2. MenuScene();

    • 역할:
      • MenuScene의 생성자로, 필요한 초기화를 수행합니다.
  3. virtual ~MenuScene() override;

    • 역할:
      • MenuScene의 소멸자로, 리소스 해제를 처리합니다.
  4. virtual void Init() override;

    • 역할:
      • 메뉴 화면 초기화를 수행합니다.
  5. virtual void Update() override;

    • 역할:
      • 메뉴 화면의 업데이트 작업을 수행합니다.
  6. virtual void Render(HDC hdc) override;

    • 역할:
      • 메뉴 화면의 렌더링 작업을 수행합니다.

구현 파일

void MenuScene::Update()
{
    if (GET_SINGLE(InputManager)->GetButtonDown(KeyType::E))
    {
        GET_SINGLE(SceneManager)->ChangeScene(SceneType::FortressScene);
    }
}
  1. if (GET_SINGLE(InputManager)->GetButtonDown(KeyType::E))

    • 역할:
      • 사용자가 E 키를 눌렀는지 확인합니다.
  2. GET_SINGLE(SceneManager)->ChangeScene(SceneType::FortressScene);

    • 역할:
      • 현재 씬을 FortressScene으로 변경합니다.

void MenuScene::Render(HDC hdc)
{
    ::Rectangle(hdc, 0, 0, GWinSizeX, GWinSizeY);

    const LineMesh* mesh = GET_SINGLE(ResourceManager)->GetLineMesh(L"Menu");
    if (mesh)
        mesh->Render(hdc, Pos{ 0, 0 });

    HFONT myFont = ::CreateFont(30, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, L"궁서체");
    HFONT oldFont = (HFONT)::SelectObject(hdc, myFont);

    wstring message = L"PRESS 'E' TO START.";
    ::TextOut(hdc, 250, 550, message.c_str(), static_cast<int32>(message.size()));

    ::SelectObject(hdc, oldFont);
    ::DeleteObject(myFont);
}
  1. ::Rectangle(hdc, 0, 0, GWinSizeX, GWinSizeY);

    • 역할:
      • 전체 화면을 채우는 사각형을 그립니다.
  2. const LineMesh* mesh = GET_SINGLE(ResourceManager)->GetLineMesh(L"Menu");

    • 역할:
      • Menu 메쉬 데이터를 가져옵니다.
  3. if (mesh)

    • 역할:
      • 메쉬 데이터가 유효한지 확인합니다.
  4. mesh->Render(hdc, Pos{ 0, 0 });

    • 역할:
      • 메쉬 데이터를 화면에 렌더링합니다.
  5. HFONT myFont = ::CreateFont(30, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, L"궁서체");

    • 역할:
      • 텍스트를 그릴 때 사용할 폰트를 생성합니다.
  6. wstring message = L"PRESS 'E' TO START.";

    • 역할:
      • 사용자에게 E 키를 누르라는 메시지를 저장합니다.
  7. ::TextOut(hdc, 250, 550, message.c_str(), static_cast<int32>(message.size()));

    • 역할:
      • 지정된 위치(250, 550)에 텍스트를 출력합니다.

UIManager 클래스

헤더 파일

class UIManager
{
    DECLARE_SINGLE(UIManager);

public:
    void Init();
    void Render(HDC hdc);

    void SetWindPercent(float windPercent);
    void SetPowerPercent(float powerPercent);
    void SetRemainTime(int32 remainTime);

    float GetWindPercent();
    float GetPowerPercent();
    int32 GetRemainTime();

private:
    float _windPercent = 0.f;
    float _powerPercent = 0.f;
    int32 _remainTime = 0;
};

한 줄씩 분석

  1. DECLARE_SINGLE(UIManager)

    • 역할:
      • UIManager를 싱글톤으로 선언합니다.
      • 프로그램 전체에서 하나의 인스턴스만 존재합니다.
  2. void Init();

    • 역할:
      • UI 요소를 초기화합니다.
  3. void Render(HDC hdc);

    • 역할:
      • 모든 UI 요소를 화면에 렌더링합니다.
  4. void SetWindPercent(float windPercent);

    • 역할:
      • 바람 세기를 설정합니다.
  5. void SetPowerPercent(float powerPercent);

    • 역할:
      • 발사력을 설정합니다.
  6. void SetRemainTime(int32 remainTime);

    • 역할:
      • 남은 시간을 설정합니다.
  7. float GetWindPercent();

    • 역할:
      • 현재 바람 세기를 반환합니다.
  8. float GetPowerPercent();

    • 역할:
      • 현재 발사력을 반환합니다.
  9. int32 GetRemainTime();

    • 역할:
      • 현재 남은 시간을 반환합니다.

남은 분석

여기까지 주요 클래스와 함수들의 상세 분석을 진행하였습니다. 추가적으로 설명이 필요한 부분이나 더 다뤄야 할 클래스/함수가 있다면 알려주세요! ResourceManager와 같은 관리 클래스가 아직 추가로 분석되지 않았다면 이어서 다룰 수 있습니다.
아직 남아 있는 클래스들을 모두 분석하겠습니다. 아래는 아직 다루지 않은 주요 클래스와 함수들입니다. 한 줄씩 철저히 분석을 이어가겠습니다.


ResourceManager 클래스

헤더 파일

class ResourceManager
{
    DECLARE_SINGLE(ResourceManager);

public:
    ~ResourceManager();

    void Init();
    void Clear();

    const LineMesh* GetLineMesh(wstring key);

private:
    unordered_map<wstring, LineMesh*> _lineMeshes;
};

한 줄씩 분석

  1. DECLARE_SINGLE(ResourceManager)

    • 역할:
      • ResourceManager를 싱글톤으로 선언합니다.
      • 프로그램 전역에서 하나의 ResourceManager 인스턴스만 존재하도록 보장합니다.
  2. ~ResourceManager();

    • 역할:
      • 소멸자로, 리소스(_lineMeshes)의 메모리를 해제합니다.
  3. void Init();

    • 역할:
      • 리소스를 초기화하고 파일에서 메쉬 데이터를 로드합니다.
  4. void Clear();

    • 역할:
      • 모든 메쉬 데이터를 삭제합니다.
  5. const LineMesh* GetLineMesh(wstring key);

    • 역할:
      • 키 값(key)에 해당하는 메쉬 데이터를 반환합니다.
      • 반환값이 없으면 nullptr을 반환합니다.
  6. unordered_map<wstring, LineMesh*> _lineMeshes;

    • 역할:
      • 키-값 형태로 메쉬 데이터를 저장합니다.
      • 키(wstring)는 메쉬 이름, 값(LineMesh*)는 메쉬 데이터의 포인터입니다.

구현 파일

ResourceManager::Init 함수
void ResourceManager::Init()
{
    LineMesh* mesh = new LineMesh();
    mesh->Load(L"Menu.txt");
    _lineMeshes[L"Menu"] = mesh;

    mesh = new LineMesh();
    mesh->Load(L"UI.txt");
    _lineMeshes[L"UI"] = mesh;

    mesh = new LineMesh();
    mesh->Load(L"MissileTank.txt");
    _lineMeshes[L"MissileTank"] = mesh;

    mesh = new LineMesh();
    mesh->Load(L"CanonTank.txt");
    _lineMeshes[L"CanonTank"] = mesh;
}
  1. LineMesh* mesh = new LineMesh();

    • 역할:
      • 새로운 LineMesh 객체를 생성합니다.
  2. mesh->Load(L"Menu.txt");

    • 역할:
      • Menu.txt 파일에서 메쉬 데이터를 로드합니다.
  3. _lineMeshes[L"Menu"] = mesh;

    • 역할:
      • Menu라는 키로 메쉬 데이터를 저장합니다.
  4. 같은 작업 반복

    • 역할:
      • 다른 메쉬 파일(UI.txt, MissileTank.txt, CanonTank.txt)을 로드하여 _lineMeshes에 저장합니다.

ResourceManager::GetLineMesh 함수
const LineMesh* ResourceManager::GetLineMesh(wstring key)
{
    auto findIt = _lineMeshes.find(key);
    if (findIt == _lineMeshes.end())
        return nullptr;

    return findIt->second;
}
  1. auto findIt = _lineMeshes.find(key);

    • 역할:
      • _lineMeshes에서 주어진 키(key)를 검색합니다.
  2. if (findIt == _lineMeshes.end())

    • 역할:
      • 키가 _lineMeshes에 없으면 nullptr을 반환합니다.
  3. return findIt->second;

    • 역할:
      • 찾은 메쉬 데이터를 반환합니다.

ResourceManager::Clear 함수
void ResourceManager::Clear()
{
    for (auto& pair : _lineMeshes)
    {
        delete pair.second;
    }
    _lineMeshes.clear();
}
  1. for (auto& pair : _lineMeshes)

    • 역할:
      • _lineMeshes에 저장된 모든 메쉬 데이터를 순회합니다.
  2. delete pair.second;

    • 역할:
      • 메쉬 데이터의 메모리를 해제합니다.
  3. _lineMeshes.clear();

    • 역할:
      • _lineMeshes 맵을 비웁니다.

ObjectManager 클래스

헤더 파일

class ObjectManager
{
    DECLARE_SINGLE(ObjectManager);

public:
    void Init();
    void Update();
    void Render(HDC hdc);
    void Clear();

    template <typename T>
    T* CreateObject();

    void Add(Object* object);
    void Remove(Object* object);

    const vector<Object*>& GetObjects() const;

private:
    vector<Object*> _objects;
};

한 줄씩 분석

  1. DECLARE_SINGLE(ObjectManager)

    • 역할:
      • ObjectManager를 싱글톤으로 선언합니다.
  2. void Init();

    • 역할:
      • 모든 오브젝트를 초기화합니다.
  3. void Update();

    • 역할:
      • 모든 오브젝트를 업데이트합니다.
  4. void Render(HDC hdc);

    • 역할:
      • 모든 오브젝트를 화면에 렌더링합니다.
  5. void Clear();

    • 역할:
      • 모든 오브젝트를 삭제합니다.
  6. template <typename T> T* CreateObject();

    • 역할:
      • 새로운 오브젝트를 생성합니다.
      • 템플릿: T는 생성할 오브젝트의 타입입니다.
  7. void Add(Object* object);

    • 역할:
      • 새로 생성된 오브젝트를 _objects에 추가합니다.
  8. void Remove(Object* object);

    • 역할:
      • 오브젝트를 _objects에서 제거합니다.
  9. const vector<Object*>& GetObjects() const;

    • 역할:
      • 현재 관리 중인 오브젝트들의 리스트를 반환합니다.
  10. vector<Object*> _objects;

    • 역할:
      • 모든 오브젝트를 저장하는 벡터입니다.

구현 파일

ObjectManager::Update 함수
void ObjectManager::Update()
{
    for (Object* object : _objects)
    {
        object->Update();
    }
}
  1. for (Object* object : _objects)

    • 역할:
      • _objects에 저장된 모든 오브젝트를 순회합니다.
  2. object->Update();

    • 역할:
      • 각 오브젝트의 Update 함수를 호출하여 상태를 갱신합니다.

ObjectManager::Render 함수
void ObjectManager::Render(HDC hdc)
{
    for (Object* object : _objects)
    {
        object->Render(hdc);
    }
}
  1. for (Object* object : _objects)

    • 역할:
      • _objects에 저장된 모든 오브젝트를 순회합니다.
  2. object->Render(hdc);

    • 역할:
      • 각 오브젝트의 Render 함수를 호출하여 화면에 렌더링합니다.

ObjectManager::Clear 함수
void ObjectManager::Clear()
{
    for (Object* object : _objects)
    {
        delete object;
    }
    _objects.clear();
}
  1. for (Object* object : _objects)

    • 역할:
      • _objects에 저장된 모든 오브젝트를 순회합니다.
  2. delete object;

    • 역할:
      • 오브젝트 메모리를 해제합니다.
  3. _objects.clear();

    • 역할:
      • _objects 벡터를 비웁니다.

추가적인 설명 요청

ObjectManager, SceneManager, 또는 남은 세부 구현 중 더 필요한 부분이 있다면 알려주세요.
필요하다면 다른 클래스나 함수도 추가적으로 철저히 분석해 드리겠습니다.
ObjectManagerSceneManager 클래스는 게임 오브젝트와 씬(Scene)을 관리하는 핵심적인 역할을 합니다. 아래에서 각각의 클래스와 관련된 모든 구현을 상세히 설명하겠습니다.


ObjectManager 클래스

헤더 파일

class ObjectManager
{
    DECLARE_SINGLE(ObjectManager);

public:
    void Init();
    void Update();
    void Render(HDC hdc);
    void Clear();

    template <typename T>
    T* CreateObject();

    void Add(Object* object);
    void Remove(Object* object);

    const vector<Object*>& GetObjects() const;

private:
    vector<Object*> _objects;
};

한 줄씩 분석

  1. DECLARE_SINGLE(ObjectManager)

    • 역할:
      • ObjectManager를 싱글톤으로 선언합니다.
      • 게임에서 하나의 ObjectManager 인스턴스만 존재하도록 보장합니다.
  2. void Init();

    • 역할:
      • 오브젝트 관리자를 초기화합니다. 오브젝트 생성에 필요한 데이터 초기화 등.
  3. void Update();

    • 역할:
      • 모든 오브젝트를 매 프레임 업데이트합니다.
  4. void Render(HDC hdc);

    • 역할:
      • 모든 오브젝트를 화면에 렌더링합니다.
  5. void Clear();

    • 역할:
      • 관리 중인 모든 오브젝트를 삭제합니다.
  6. template <typename T> T* CreateObject();

    • 역할:
      • 새로운 오브젝트를 동적으로 생성하여 반환합니다.
      • 템플릿: T는 생성할 오브젝트의 타입입니다.
  7. void Add(Object* object);

    • 역할:
      • 새로 생성된 오브젝트를 _objects 벡터에 추가합니다.
  8. void Remove(Object* object);

    • 역할:
      • 특정 오브젝트를 _objects 벡터에서 제거합니다.
  9. const vector<Object*>& GetObjects() const;

    • 역할:
      • 현재 관리 중인 오브젝트 리스트를 반환합니다.
  10. vector<Object*> _objects;

    • 역할:
      • 모든 오브젝트를 저장하는 컨테이너입니다.

구현 파일

ObjectManager::Init 함수
void ObjectManager::Init()
{
    _objects.clear();
}
  1. _objects.clear();
    • 역할:
      • 오브젝트 리스트를 초기화합니다.

ObjectManager::Update 함수
void ObjectManager::Update()
{
    for (Object* object : _objects)
    {
        object->Update();
    }
}
  1. for (Object* object : _objects)

    • 역할:
      • _objects에 저장된 모든 오브젝트를 순회합니다.
  2. object->Update();

    • 역할:
      • 각 오브젝트의 상태를 갱신합니다.

ObjectManager::Render 함수
void ObjectManager::Render(HDC hdc)
{
    for (Object* object : _objects)
    {
        object->Render(hdc);
    }
}
  1. object->Render(hdc);
    • 역할:
      • 각 오브젝트를 화면에 렌더링합니다.

ObjectManager::Clear 함수
void ObjectManager::Clear()
{
    for (Object* object : _objects)
    {
        delete object;
    }
    _objects.clear();
}
  1. delete object;

    • 역할:
      • 오브젝트의 메모리를 해제합니다.
  2. _objects.clear();

    • 역할:
      • _objects 리스트를 비웁니다.

ObjectManager::Add 함수
void ObjectManager::Add(Object* object)
{
    _objects.push_back(object);
}
  1. _objects.push_back(object);
    • 역할:
      • 새 오브젝트를 _objects 리스트에 추가합니다.

ObjectManager::Remove 함수
void ObjectManager::Remove(Object* object)
{
    auto it = find(_objects.begin(), _objects.end(), object);
    if (it != _objects.end())
    {
        delete *it;
        _objects.erase(it);
    }
}
  1. auto it = find(_objects.begin(), _objects.end(), object);

    • 역할:
      • _objects 리스트에서 제거할 오브젝트를 검색합니다.
  2. delete *it;

    • 역할:
      • 오브젝트를 메모리에서 삭제합니다.
  3. _objects.erase(it);

    • 역할:
      • 리스트에서 오브젝트를 제거합니다.

SceneManager 클래스

헤더 파일

class SceneManager
{
    DECLARE_SINGLE(SceneManager);

public:
    void Init();
    void Update();
    void Render(HDC hdc);
    void Clear();

    void ChangeScene(SceneType sceneType);
    Scene* GetCurrentScene();

private:
    Scene* _scene = nullptr;
    SceneType _sceneType = SceneType::None;
};

한 줄씩 분석

  1. DECLARE_SINGLE(SceneManager)

    • 역할:
      • SceneManager를 싱글톤으로 선언합니다.
  2. void Init();

    • 역할:
      • 씬 매니저를 초기화합니다.
  3. void Update();

    • 역할:
      • 현재 활성화된 씬을 업데이트합니다.
  4. void Render(HDC hdc);

    • 역할:
      • 현재 활성화된 씬을 렌더링합니다.
  5. void Clear();

    • 역할:
      • 현재 활성화된 씬을 정리합니다.
  6. void ChangeScene(SceneType sceneType);

    • 역할:
      • 다른 씬으로 전환합니다.
  7. Scene* GetCurrentScene();

    • 역할:
      • 현재 활성화된 씬을 반환합니다.
  8. Scene* _scene;

    • 역할:
      • 현재 활성화된 씬을 가리키는 포인터입니다.
  9. SceneType _sceneType;

    • 역할:
      • 현재 씬의 타입을 저장합니다.

구현 파일

SceneManager::Update 함수
void SceneManager::Update()
{
    if (_scene)
        _scene->Update();
}
  1. if (_scene)

    • 역할:
      • 활성화된 씬이 있는지 확인합니다.
  2. _scene->Update();

    • 역할:
      • 활성화된 씬의 Update 함수를 호출하여 상태를 갱신합니다.

SceneManager::Render 함수
void SceneManager::Render(HDC hdc)
{
    if (_scene)
        _scene->Render(hdc);
}
  1. _scene->Render(hdc);
    • 역할:
      • 활성화된 씬의 Render 함수를 호출하여 화면에 렌더링합니다.

SceneManager::ChangeScene 함수
void SceneManager::ChangeScene(SceneType sceneType)
{
    if (_sceneType == sceneType)
        return;

    SAFE_DELETE(_scene);

    switch (sceneType)
    {
    case SceneType::MenuScene:
        _scene = new MenuScene();
        break;
    case SceneType::FortressScene:
        _scene = new FortressScene();
        break;
    }

    _sceneType = sceneType;
    if (_scene)
        _scene->Init();
}
  1. if (_sceneType == sceneType)

    • 역할:
      • 현재 씬 타입과 전환하려는 씬 타입이 동일하면 아무 작업도 하지 않습니다.
  2. SAFE_DELETE(_scene);

    • 역할:
      • 현재 활성화된 씬을 메모리에서 삭제합니다.
  3. switch (sceneType)

    • 역할:
      • 새 씬 타입에 따라 새로운 씬 객체를 생성합니다.
  4. _scene->Init();

    • 역할:
      • 새로 생성된 씬을 초기화합니다.

마무리

이제 ObjectManagerSceneManager 클래스에 대한 설명이 완료되었습니다.
추가적으로 더 분석하거나 다뤄야 할 클래스나 함수가 있다면 알려주세요. 철저히 분석하여 설명드리겠습니다!

profile
李家네_공부방

0개의 댓글