WIN32 Resource(텍스쳐)

Date:     Updated:

카테고리:

태그:

11일차

- Default
    - Client.h
    - framework.h
    - Resouce.h
    - targetver.h
- Engine
    1. Header
        1. define.h
        2. struct.h
    2. Core
        **1. CCore.cpp**
        2. CCore.h
    3. Manager
        1. KeyMgr
            1. CkeyMgr.cpp
            2. CkeyMgr.h
        2. TimeMgr
            1. CTimeMgr.cpp
            2. CTimeMgr.h
        3. SceneMgr
            1. CSceneMgr.cpp
            2. CSceneMgr.h
    		**4. PathMgr
						1. CPathMgr.cpp
						2. CPathMgr.h**
    **4. Object
		    1. Monser
			    1. CMonster.cpp
			    2. CMonster.h**
			  2. Missle
				  1. Missile.cpp
				  2. Missile.h
				**3. Player
					1. CPlayer.cpp
					2. Cplayer.h**
        1. CObject.cpp
        2. CObject.h
    5. Scene
        1. Scene_Start
            1. CScene_Start.cpp
            2. CScene_Start.h
        2. Scene_Tool
        3. CScene.cpp
        4. CScene.h
    **6. Resource
		    1. Sound
		    2. Texture
			    1. CTexture.cpp
				  2. CTexture.h
		    3. CRes.cpp
		    4. CRes.h**
		    
- 리소스 파일
- main.cpp
- pch.h.
  1. 속성 → 구성 속성 → 디버깅의 작업 디렉터리를 “$(SolutionDir)Output\bin\”로 바꿔준다.
  2. Debug 구성에서 구성 속성의 출력 디렉터리를 Debug는“$(SolutionDir)Output\bin_debug\”로.
  3. Release는 “$(SolutionDir)Output\bin\”를 적어준다.

Resource의 경로 설정을 위해 이렇게 해준다.

그럼 수정된 부분을 알아보자!!

  1. CCore.cpp
int CCore::init(HWND _hWnd, POINT _ptResolution) {
	m_hWnd = _hWnd;
	m_ptResolution = _ptResolution;

	//해상도에 맞게 윈도우 크기 조정. 

	RECT rt = { 0,0,m_ptResolution.x, m_ptResolution.y };
	//테두리 포함해서, 크기 보정해주는 것. 
	//rt 포인터에다가 다시 값을 변환해서 넣어줌. 
	AdjustWindowRect(&rt, WS_OVERLAPPEDWINDOW, true);

	//타이틀이나 그런 걸 제외한, 순수하게 물체가 그려질 수 있는 영역.
	//첫 번째로 들어가는 건, 어떤 윈도우인지. 
	//SetWindow는 타이틀창이나 테두리까지 포함한 크기임. 
	SetWindowPos(m_hWnd, nullptr, 100, 100, rt.right - rt.left, rt.bottom - rt.top, 0);
	
	//어디다가 그려요? m_hWnd에다가 그려요. 
	m_hDC = GetDC(m_hWnd);

	//이중 버퍼링 용도의 비트맵과 DC를 만든다. 
	//그림을 그릴 수 있는 건 윈도우에 달려있는, 해상도만큼의 픽셀(묶어서 비트맵이라고 부름)

	//결국 똑같은 해상도로 비트맵을 가지면 되는 거 아닌가? 해서 똑같은 해상도의 비트맵을 만듬. 
	//Compatible은 호환성. (호환성을 가지고 있는 비트맵)
	//비트맵 아이디 값을 받았음. 
	m_hBit = CreateCompatibleBitmap(m_hDC, m_ptResolution.x, m_ptResolution.y);

	//새로 만든 목적지의 DC가 필요함. (어떤 구조인지에 대한 Device Context가 필요함)
	m_memDC = CreateCompatibleDC(m_hDC);

	//이번엔 그림을 그릴 타겟, 목적지를 교체해주는 것. 위에서 만든 비트맵을 전달해줌. 
	//되돌아 리턴되는 건 원래 비트맵이지 않을까? 기본적으로 들어가있는 1픽셀짜리 Default 비트맵. 
	HBITMAP holdBit = (HBITMAP)SelectObject(m_memDC, m_hBit);
	DeleteObject(holdBit);

	//Manager initialize
	CPathMgr::GetInstance()->init();
	CTimeMgr::GetInstance()->init();
	CkeyMgr::GetInstance()->init();
	CSceneMgr::GetInstance()->init();

	return S_OK;
}

void CCore::progress() {

	//Manager Update
	CTimeMgr::GetInstance()->update();
	CkeyMgr::GetInstance()->update();

	CSceneMgr::GetInstance()->update();

	// ============
	//	Rendering
	// ============

	//초기화(흰 사각형으로 덧 씌움)
	Rectangle(m_memDC, -1, -1, m_ptResolution.x + 1, m_ptResolution.y + 1);

	//어디다가 그려야하는지 알려주기. 
	CSceneMgr::GetInstance()->render(m_memDC);

	BitBlt(m_hDC, 0, 0, m_ptResolution.x, m_ptResolution.y, m_memDC, 0, 0, SRCCOPY);
	
	//CTimeMgr::GetInstance()->render();
}
  • CPathMgr을 넣어준다.
  1. CPathMgr.h
#pragma once

class CPathMgr
{
	SINGLE(CPathMgr);

private:
	wchar_t		m_szContentPath[255];

public:
	void init();
	const wchar_t* GetContentPath() { return m_szContentPath; }
};

  1. CPathMgr.cpp
#include "pch.h"
#include "CPathMgr.h"

#include "CCore.h"

CPathMgr::CPathMgr() 
	: m_szContentPath{}
{

}

CPathMgr::~CPathMgr() {

}

void CPathMgr::init()
{

	//Ctrl + F5쓰면, 혹은 일반적으로 해도 프로젝트 폴더가 됨.
	//즉 비주얼 스튜디오에서 실행하는거랑, 프로그램 자체 실행이랑
	//경로값이 달라짐. 
	GetCurrentDirectory(255, m_szContentPath);
	//상위폴더로 나가고(\\을 만날때까지 찾고 거기에 null문자 넣기.) 
	int dirLen = wcslen(m_szContentPath);
	for (int dirIDX = dirLen - 1; dirIDX >= 0; dirIDX--) {
		if ('\\' == m_szContentPath[dirIDX]) {
			m_szContentPath[dirIDX] = '\0';
			break;
		}
	}
	//  + bin\\content\\ 경로 붙여주기
	wcscat_s(m_szContentPath, 255, L"\\bin\\content\\");
	//상대 경로 설정 완료.
	//SetWindowText(CCore::GetInstance()->GetMainHwnd(), m_szContentPath);
}

  • 리소스가 있을 곳의 경로를 만들어준다.
  1. CMonster.h
#pragma once
#include "CObject.h"

class CMonster :
    public CObject
{
private:
    float       m_fSpeed;
    Vec2        m_vCenterPos;
    float       m_fMaxMoveDistance;
    int         m_iDir; // 1, -1 (1 : Right, -1 : Left);

public:
    virtual void update();
    float GetSpeed() { return m_fSpeed; }
    void SetSpeed(float _f) { m_fSpeed = _f; }

    void SetCenterPos(Vec2 _vPos) { m_vCenterPos = _vPos; }
    void SetMaxMoveDistance(float _f) { m_fMaxMoveDistance = _f; }

public:
    CMonster();
    ~CMonster();
};
  1. CMonster.cpp
#include "pch.h"
#include "CMonster.h"

#include "CTimeMgr.h"
#include "math.h"

CMonster::CMonster()
	: m_fSpeed(100.f)
	, m_vCenterPos(Vec2(0.f, 0.f))
	, m_fMaxMoveDistance(50.f)
	, m_iDir(1)
{

}

CMonster::~CMonster()
{

}

void CMonster::update()
{
	Vec2 vCurPos = GetPos();

	//진행 방향으로 시간당 m_fSpeed만큼 이동. 
	vCurPos.x += fDT * m_fSpeed * m_iDir;

	//배회 거리 기준점을 넘어섰는지 확인. 
	//부들부들 거릴때가 있음... 한번에 크게(105) 넘어섰는데, 
	//다음 프레임에 조금밖에(-1) 못 되돌아 갔을때. 

	float fDistance = abs(m_vCenterPos.x - vCurPos.x) - m_fMaxMoveDistance;
	if (0.f < fDistance) {
		m_iDir *= -1;
		vCurPos.x += fDT * m_fSpeed * m_iDir;
	}

	SetPos(vCurPos);
}
  • 사실 변경점이 없지만, 내가 코드를 다시 작성해서 올려놓는다.
  1. CPlayer.h
#pragma once
#include "CObject.h"

class CTexture;
class CPlayer :
    public CObject
{

private:
    CTexture* m_pTex;
public:
    virtual void update();
    virtual void render(HDC _dc);

private:
    void CreateMissile();

public:
    CPlayer();
    ~CPlayer();
};

  1. CPlayer.cpp
#include "pch.h"
#include "CPlayer.h"

#include "CSceneMgr.h"
#include "CScene.h"
#include "CkeyMgr.h"
#include "CTimeMgr.h"
#include "CPathMgr.h"

#include "CMissile.h"
#include "CTexture.h"

CPlayer::CPlayer()
	: m_pTex(nullptr)
{
	//Texture로딩하기
	m_pTex = new CTexture;

	//이렇게 로드하면 오브젝트마다 하나씩 로드하게 됨.
	//그러면 1개의 리소스를 여러 오브젝트가 쓴다는 대전제가 깨짐
	//따라서 리소스 매니저를 사용해야함. 
	wstring strFilePath = CPathMgr::GetInstance()->GetContentPath();
	strFilePath += L"texture\\Tenshi.bmp";
	m_pTex->Load(strFilePath);
}

CPlayer::~CPlayer()
{
	if (nullptr != m_pTex)
		delete m_pTex;
}

void CPlayer::update()
{
	Vec2 vPos = GetPos();
	if (KEY_HOLD(KEY::W)) {
		vPos.y -= 200.f * fDT;
	}
	if (KEY_HOLD(KEY::S)) {
		vPos.y += 200.f * fDT;
	}
	if (KEY_HOLD(KEY::A)) {
		vPos.x -= 200.f * fDT;
	}
	if (KEY_HOLD(KEY::D)) {
		vPos.x += 200.f * fDT;
	}

	if (KEY_TAP(KEY::SPACE)) {
		CreateMissile();
	}
	SetPos(vPos);
}

void CPlayer::render(HDC _dc)
{
	int iWidth = m_pTex->Width();
	int iHeight = m_pTex->Height();

	Vec2 vPos = GetPos();

	/*
	BitBlt(_dc,
		int(vPos.x - ((float)(iWidth / 2.f))),
		int(vPos.y - ((float)(iHeight / 2.f))),
		iWidth,
		iHeight,
		m_pTex->GetDC(), 
		0, 0, SRCCOPY);
	*/
	//일부 픽셀들을 옮겨서 가져오면 되지 않나?(배경 분홍색 같은 느낌)
	//Bitblt말고 다른 옮기기 함수가 있음
	TransparentBlt(_dc, 
		int(vPos.x - ((float)(iWidth / 2.f))),
		int(vPos.y - ((float)(iHeight / 2.f))),
		iWidth, iHeight,
		m_pTex->GetDC(),
		0, 0, iWidth, iHeight, 
		RGB(255, 0, 255));
}

void CPlayer::CreateMissile()
{
	Vec2 vMissilePos = GetPos();
	vMissilePos.y -= GetScale().y / 2.f;
	CMissile* pMissile = new CMissile;

	pMissile->SetPos(vMissilePos);
	pMissile->SetScale(Vec2(25.f, 25.f));
	pMissile->SetDir(Vec2(0.f, -1.f));

	CScene* pCurScene = CSceneMgr::GetInstance()->GetCurScene();
	pCurScene->AddObject(pMissile, GROUP_TYPE::DEFAULT);
}

  • TransparentBlt로 원하는 색(RGB(255,0,255)를 제외한 모든 색을 옮겨준다.
  1. CRes.h
#pragma once
class CRes
{

private:
	wstring		m_strKey;			//리소스의 고유한 키값
	wstring		m_strRelativePath;	//리소스 상대경로

public:
	void SetKey(const wstring& _strKey) { m_strKey = _strKey; }
	void SetRelativePath(const wstring& _strPath) { m_strRelativePath = _strPath; }

	const wstring& GetKey() { return m_strKey; }
	const wstring& GetRelativePath() { return m_strRelativePath; }

public:
	CRes();
	~CRes();
};

  1. CRes.cpp
#include "pch.h"
#include "CRes.h"

CRes::CRes()
{
}

CRes::~CRes()
{
}

  1. CTexture.h
#pragma once
#include "CRes.h"
class CTexture :
    public CRes
{

private:
    //이미지 데이터는 하나만 메모리에 올리고, 그걸 모든 오브젝트가 같이 쓰면 됨.
    //비트맵을 하나 만들었다가, 그걸 옮겨다가 색칠해주면됨
    HDC         m_dc;
    HBITMAP     m_hBit;

    //별도의 픽셀 데이터를 보유하고 있을 것. 그리고 그걸 연결지을 DC가 필요. 
    //비트맵 + dc가 텍스쳐. 

    BITMAP      m_bitInfo;

public:
    void Load(const wstring& _strFilePath);

    UINT Width() { return m_bitInfo.bmWidth; }
    UINT Height() { return m_bitInfo.bmHeight; }

    HDC GetDC() { return m_dc; }

public:
    CTexture();
    ~CTexture();
};

  1. CTexture.cpp
#include "pch.h"
#include "CTexture.h"
#include "CCore.h"

CTexture::CTexture()
	: m_hBit(0)
	, m_dc(0)
	, m_bitInfo{}
{
}

CTexture::~CTexture()
{
	DeleteDC(m_dc);
	DeleteObject(m_hBit);
}

//사용할 리소스는 Release버전이 에서 사용할 수 있을 것. 
//리소스도 bin파일에 그대로 있어야함. 

//디버그 버전에 실행할 때는 리소스 없는데? 
//bin -> content안에 있는 거 쓰면 되는데?
void CTexture::Load(const wstring& _strFilePath)
{
	//파일로부터 로딩한 데이터를 비트맵으로 생성. 
	m_hBit = (HBITMAP)LoadImage(nullptr, _strFilePath.c_str(), 
		IMAGE_BITMAP,
		0, 0, 
		LR_CREATEDIBSECTION | LR_LOADFROMFILE);
	assert(m_hBit);
	//비트맵과 연결할 DC
	m_dc = CreateCompatibleDC(CCore::GetInstance()->GetMainDC());

	//비트맵과 DC연결

	HBITMAP hPrevBit = (HBITMAP)SelectObject(m_dc, m_hBit);
	DeleteObject(hPrevBit);

	//비트맵 정보 알아오기. 
	GetObject(m_hBit, sizeof(BITMAP), &m_bitInfo);

}
  • 주요 작업은 상대경로를 알아내고 절대경로로 변환하는 PathMgr과
  • bmp파일을(jpg나 png등은 GDI+를 사용) 텍스쳐로 사용하는 CTexture 클래스다.
  • 이번엔 주석을 되게 열심히 달아놓아서 주석으로 전부 이해가 가능할 것이다.

WINAPI 카테고리 내 다른 글 보러가기

댓글 남기기