WIN32 Resource(텍스쳐)
카테고리: WINAPI
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.
- 속성 → 구성 속성 → 디버깅의 작업 디렉터리를 “$(SolutionDir)Output\bin\”로 바꿔준다.
- Debug 구성에서 구성 속성의 출력 디렉터리를 Debug는“$(SolutionDir)Output\bin_debug\”로.
- Release는 “$(SolutionDir)Output\bin\”를 적어준다.
Resource의 경로 설정을 위해 이렇게 해준다.
그럼 수정된 부분을 알아보자!!
- 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을 넣어준다.
- CPathMgr.h
#pragma once
class CPathMgr
{
SINGLE(CPathMgr);
private:
wchar_t m_szContentPath[255];
public:
void init();
const wchar_t* GetContentPath() { return m_szContentPath; }
};
- 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);
}
- 리소스가 있을 곳의 경로를 만들어준다.
- 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();
};
- 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);
}
- 사실 변경점이 없지만, 내가 코드를 다시 작성해서 올려놓는다.
- 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();
};
- 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)를 제외한 모든 색을 옮겨준다.
- 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();
};
- CRes.cpp
#include "pch.h"
#include "CRes.h"
CRes::CRes()
{
}
CRes::~CRes()
{
}
- 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();
};
- 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 클래스다.
- 이번엔 주석을 되게 열심히 달아놓아서 주석으로 전부 이해가 가능할 것이다.
댓글 남기기