D2D와 게임엔진

엔진공부 2일차 ( Static Library 만들기 ... feat. 윈도우 생성오류)

햄시나 2024. 8. 7. 09:54

Direct2D 관련 코드를 분리하여 D2DRenderer Class화 하기.

 대충 main엔 이렇게만 코드가 실행될 예정이다.

Winmain()
{
   DemoApp App;
   App.Initialize();        	// 윈도우 생성, D2DRenderer 초기화
   App.Run();       		// 게임 루프
   App.Uninitialize();     	// D2DRenderer 해제
}

여기서 DemoApp이 뭐냐면, 이제부터 만들 정적 라이브러리의 GameApp을 상속받아 만들어진 클래스다.

GameApp 클래스의 기능은 위의 주석에서 파악 할 수 있다.

 

Renderer를 만들기전에 생각해본 것들...

일단 D2D는 윈도우 화면에 띄워지는 것들이기 때문에 너무나 당연한 말 일 수 있지만, 윈도우 등록 및 초기화를 해야한다.

그리고 등록된 윈도우를 통해서 D2D에 필요한 요소들을 불러내어야 하기에, 먼저 GameApp에서 윈도우 초기화가 진행되도록 큰 틀을 잡았다.

#pragma once
#include "D2DRenderer.h"
class GameApp
{
public:
	GameApp();
	~GameApp();

	virtual void Initialize(HINSTANCE _hInstance);
	virtual void Run();
	virtual void Update();
	virtual void Render();
	virtual void Uninitialize();

	HWND RegisterWindow(HINSTANCE _hInstance);

	static LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

protected:
	D2DRenderer m_Render;

private:
	WNDCLASSEX wc{ 0 };
	HINSTANCE m_hInstance;                          // 현재 인스턴스입니다.
	//WCHAR szTitle[MAX_LOADSTRING];                  // 제목 표시줄 텍스트입니다.
	//WCHAR szWindowClass[MAX_LOADSTRING];            // 기본 창 클래스 이름입니다.
};

내가 생각하기에 전체적인 흐름 상 필요한 함수들을 미리 만들었고, 내용없이 아직 선언만 되어있는 상태다.

GameApp은 DemoApp의 부모가 될 예정이므로 다형성을 위해 virtual을 붙여 재정의가 가능하도록 해뒀다.

#include "framework.h"
#include "GameApp.h"


GameApp::GameApp()
{
    
}
GameApp::~GameApp()
{

}
void GameApp::Initialize(HINSTANCE _hInstance)
{
    m_hInstance = _hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
    HWND hwnd = RegisterWindow(_hInstance);
    
    m_Render.Initialize(hwnd);
}
HWND GameApp::RegisterWindow(HINSTANCE _hInstance)
{

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;	// 윈도우 프로시저 함수
    wc.hInstance = m_hInstance;   // 인스턴스 핸들
    // NULL을 사용하면 현재 실행 중인 프로그램의 인스턴스 핸들을 사용하게 됩니다.두 번째 인자는 로드할 커서의 ID입니다.
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = L"DefaultWindow";

     //윈도우 클래스 등록
    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, L"윈도우 클래스 등록 실패", L"에러", MB_OK | MB_ICONERROR);
    }

    HWND hWnd;
    hWnd = CreateWindowEx(
        0,
        L"DefaultWindow",
        L"D2DHam",      //상단바에 뜨는 제목
        WS_OVERLAPPEDWINDOW,
        0 ,0,
        1920, 1280,
        NULL, NULL, _hInstance, NULL);

    ShowWindow(hWnd, SW_SHOWNORMAL);
    UpdateWindow(hWnd);
    if (!hWnd)
    {
        MessageBox(NULL, L"윈도우 생성 실패", L"에러", MB_OK | MB_ICONERROR);
    }
    return hWnd;
}

void GameApp::Run()
{
	MSG msg;
	// 기본 메시지 루프입니다:
	while (TRUE)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
				break;

			//윈도우 메시지 처리 
			TranslateMessage(&msg); // 키입력관련 메시지 변환  WM_KEYDOWN -> WM_CHAR
			DispatchMessage(&msg);
		}
		else
		{
            Render();
		}
	}
}

void GameApp::Update()
{
}

void GameApp::Render()
{
    m_Render.BeginDraw();

    m_Render.EndDraw();
}

void GameApp::Uninitialize()
{
    m_Render.UnInitailize();
}

LRESULT GameApp::WndProc(HWND _hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(_hwnd, msg, wParam, lParam);
    }
    return 0;
}

 

⭐⭐⭐윈도우 등록이 안된다면,,, 윈도우 초기화 때의 wc.lpszClassName = L"DefaultWindow"; 이 부분이

윈도우 생성할때의 값과 일치하는지를 확인해보자...

아주 기초적인 것을 놓쳐서 어제 마무리 짓는데 실행이 안되고 오류가 자꾸 바뀌어가며 나길래 돌아버리는줄 앎...