WIN32 Tile

Date:     Updated:

카테고리:

태그:

18일차

- Default
    - Client.h
    - framework.h
    - Resouce.h
    - targetver.h
- Engine
    1. Header
        **1. define.h**
        2. struct.h
        3. func.h
        4. func.cpp
        5. global.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
				5. ResMgr
						1. CResMgr.cpp
						2. CResMgr.h
	****			6. CollisionMgr
						1. CCollisionMgr.cpp
						2. CCollisionMgr.h
				7. EventMgr
						1. CEventMgr.cpp
****						2. CEventMgr.h
				8. Camera
						1. CCamera.cpp
						2. CCamera.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
				**4. Tile
					1. CTile.cpp
					2. CTile.h**
        1. CObject.cpp
        2. CObject.h
    5. Scene
        1. Scene_Start
            1. CScene_Start.cpp
            2. CScene_Start.h
        **2. Scene_Tool
		        1. CScene_Tool.cpp
		        2. CScene_Tool.h**
        **3. CScene.cpp
        4. CScene.h**
    6. Resource
		    1. Sound
		    2. Texture
			    1. CTexture.cpp
				  2. CTexture.h
		    3. CRes.cpp
		    4. CRes.h
		7. Component
				1. Collider
					1. CCollider.cpp
					2. CCollider.h
				2. Animator
					1. Animation
						1. CAnimation.cpp
						2. CAnimation.h
					1. CAnimator.cpp
					2. CAnimation.h
		8. Module
				1. SelectGDI.cpp
				2. SelectGDI.h
- 리소스 파일
**- main.cpp**
- pch.h.
  • 리소스 뷰에서 작업이 많다. Dialog에서 “IDD_TILE_COUNT”라는 새 리소스 추가.

Image

  • 이런 화면을 만들어준다. 그러면 Resource.h에 추가될 것이다. (인풋 박스, 버튼등등이 모두 개별의 윈도우이다)
  1. main.cpp
INT_PTR __stdcall TileCountProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND://왠만한 메시지(단축키)는 이렇게 여기에서 처리함. 
    {
        int wmId = LOWORD(wParam);
        // 메뉴 선택을 구문 분석합니다:
        switch (wmId)
        {
        case IDM_ABOUT:
            //여기가 도움말. 모달 방식(도움말에서 전부 주목(입력)을 다 가져감. -> 모달에서 리턴이 안되기 때문. 
            //Visual Studio에도 리소스라는 것이 있음. About은 함수 포인터. 
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;

        case ID_MENU_TILE:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_TILE_COUNT), hWnd, TileCountProc);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;
    ...
    ...
    ...
  • IDD_TILE_COUNT라는 새로운 윈도우를 등록해준다.

0-1. Resource.h

//
// Microsoft Visual C++에서 생성한 포함 파일입니다.
// Client.rc에서 사용되고 있습니다.
//
#define IDC_MYICON                      2
#define IDD_CLIENT_DIALOG               102
#define IDS_APP_TITLE                   103
#define IDD_ABOUTBOX                    103
#define IDM_ABOUT                       104
#define IDM_EXIT                        105
#define IDI_CLIENT                      107
#define IDI_SMALL                       108
#define IDC_CLIENT                      109
#define IDR_MAINFRAME                   128
#define IDD_DIALOG1                     130
#define IDD_TILE_COUNT                  130
#define IDCANCEL                        1000
#define IDC_EDIT1                       1001
#define IDC_EDIT2                       1002
#define ID_32771                        32771
#define ID_MENI_TILE                    32772
#define ID_MENU_TILE                    32773
#define IDC_STATIC                      -1

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC                     1
#define _APS_NEXT_RESOURCE_VALUE        131
#define _APS_NEXT_COMMAND_VALUE         32774
#define _APS_NEXT_CONTROL_VALUE         1003
#define _APS_NEXT_SYMED_VALUE           110
#endif
#endif

  • 내가 삽질을 조금 했지만, 대략적으로 이렇다.
  1. define.h

#define TILE_SIZE 64
  • TILE_SIZE 추가.
  1. CTile.h
#pragma once
#include "CObject.h"

class CTexture;
class CTile :
    public CObject
{

private:
    CTexture*       m_pTileTex;
    int             m_iImgIdx;

public:
    void SetTexture(CTexture* _pTex) {
        m_pTileTex = _pTex;
    }

    void AddImgIdx() {
        ++m_iImgIdx;
    }

private:
    virtual void update();
    virtual void render(HDC _dc);
    CLONE(CTile);
public:
    CTile();
    ~CTile();
};

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

#include "CTexture.h"

CTile::CTile()
	: m_pTileTex(nullptr)
	, m_iImgIdx(0)
{
	SetScale(Vec2(TILE_SIZE, TILE_SIZE));
}

CTile::~CTile()
{
	
}
//Tool Scene을 통해서 타일의 배치를 자신이 코드가 아닌 방식으로 배치할 수 있어야 하는데.
//타일을 개별적으로 건드려서, 각 타일의 모양새를 바꿀 수 있어야함. 

//그리고 저장 & 로드가 가능해야함. 
void CTile::update()
{

}

void CTile::render(HDC _dc)
{

	if (m_pTileTex == nullptr || -1 == m_iImgIdx) {
		return;
	}

	UINT iWidth = m_pTileTex->Width();
	UINT iHeight = m_pTileTex->Height();

	UINT IMaxCol = iWidth / TILE_SIZE;
	UINT IMaxRow = iHeight / TILE_SIZE;

	UINT iCurRow = (UINT)(m_iImgIdx / IMaxCol);
	UINT iCurCol = (UINT)(m_iImgIdx % IMaxCol);

	Vec2 vRenderPos = CCamera::GetInstance()->GetRenderPos(GetPos());
	Vec2 vScale = GetScale();

	if (IMaxRow <= iCurRow) {
		assert(nullptr);
	}
	
	BitBlt(_dc,
		(int)(vRenderPos.x),
		(int)(vRenderPos.y),
		(int)(vScale.x),
		(int)(vScale.y),
		m_pTileTex->GetDC(),
		iCurRow * TILE_SIZE,
		iCurCol * TILE_SIZE,
		SRCCOPY);
}

  1. CScene.h
#pragma once

#include "global.h"
//전방선언하는 이유는 컴파일 속도에 영향을 주지 않기 위해. 
class CObject;

class CScene
{

private:
	vector<CObject*> m_arrObj[(UINT)GROUP_TYPE::END];		//벡터 안에 모든 오브젝트 집어 넣겠다. 이런 특성(요소)를 가진만큼 나눠주기.
	//달리말하면 그룹 갯수만큼 나눠주기.

	wstring			m_strName; //Scene 이름

	UINT			m_iTileX;		//타일 가로 개수
	UINT			m_iTileY;		//타일 세로 개수. 

public:
	void SetName(const wstring& _strName) { m_strName = _strName; }
	const wstring& GetName() { return m_strName; }

	UINT GetTileX() { return m_iTileX; }
	UINT GetTileY() { return m_iTileY; }

	virtual void update();
	virtual void finalupdate();
	virtual void render(HDC _dc);
	
	virtual void Enter() = 0;		//해당 Scene에 진입 시 호출.
	virtual void Exit() = 0;		//해당 Scene에 탈출 시 호출.

public:
	//클래스는 헤더에 구현하면 인라인 처리가 됨. 
	//따라서 함수 호출 비용이 사라짐. 
	void AddObject(CObject* _pObj, GROUP_TYPE _eType)
	{
		m_arrObj[(UINT)_eType].push_back(_pObj);
	}

	const vector<CObject*>& GetGroupObject(GROUP_TYPE _eType) 
	{
		return m_arrObj[(UINT)_eType];
	}

	void DeleteGroup(GROUP_TYPE _eGroup);
	void DeleteAll();

	void CreateTile(UINT _IXCount, UINT _IYCount);

public:
	CScene();

	//소멸자의 가상함수 해줘야함. 씬 매니저가 모든 Scene을 부모 포인터로 관리함.
	// CSceneMgr에서 씬을 소멸시킬때, 소멸자는 부모인 CScene만 호출됨.  
	virtual ~CScene();
};

  1. CScene.cpp
#include "pch.h"
#include "CScene.h"
#include "CObject.h"
#include "func.h"
#include "CTile.h"
#include "CTimeMgr.h"
#include "CResMgr.h"

CScene::CScene()
	: m_iTileX(0)
	, m_iTileY(0)
{
}

CScene::~CScene()
{
	for (UINT typeIDX = 0; typeIDX < (UINT)GROUP_TYPE::END; typeIDX++) {
		for (size_t objIDX = 0; objIDX < m_arrObj[typeIDX].size(); objIDX++) {
			//m_arrObj[그룹][물체] 삭제. 
			delete m_arrObj[typeIDX][objIDX];
		}
		
		//씬이 사라지면, 그 씬의 벡터들도 다 사라짐. 
		//STL의 RAII가 알아서 삭제하기 때문. 
	}
}

void CScene::update()
{
	for (UINT typeIDX = 0; typeIDX < (UINT)GROUP_TYPE::END; typeIDX++) {
		for (size_t objIDX = 0; objIDX < m_arrObj[typeIDX].size(); objIDX++) {
			if (!m_arrObj[typeIDX][objIDX]->IsDead()) {
				m_arrObj[typeIDX][objIDX]->update();
			}
		}
	}
}
//움직이고 했던 걸, 마지막으로 업데이트 함. 
//충돌체가 플레이어 따라가게 함, 충돌 처리. 
void CScene::finalupdate()
{
	for (UINT typeIDX = 0; typeIDX < (UINT)GROUP_TYPE::END; typeIDX++) {
		for (size_t objIDX = 0; objIDX < m_arrObj[typeIDX].size(); objIDX++) {

			//Final Update는 돌려줌. 내부적으로 Component들의 마무리 단계 업데이트(충돌처리나, 참조관계등)
			m_arrObj[typeIDX][objIDX]->finalupdate();
		}
	}
}

void CScene::render(HDC _dc)
{
	for (UINT typeIDX = 0; typeIDX < (UINT)GROUP_TYPE::END; typeIDX++) {
		auto ObjVecIter = m_arrObj[typeIDX].begin();

		for (; ObjVecIter != m_arrObj[typeIDX].end();) {
			if (!(*ObjVecIter)->IsDead()) {
				(*ObjVecIter)->render(_dc);
				ObjVecIter++;
			}
			else {
				//Dead상태일 경우엔 렌더링에서 삭제하기. 
				ObjVecIter = m_arrObj[typeIDX].erase(ObjVecIter);
			}

		}
	}
}

void CScene::DeleteGroup(GROUP_TYPE _eGroup)
{
	Safe_Delete_Vec<CObject*>(m_arrObj[(UINT)_eGroup]);
}

void CScene::DeleteAll()
{

	for (UINT GroupIdx = 0; GroupIdx < (UINT)GROUP_TYPE::END; GroupIdx++) {
		DeleteGroup((GROUP_TYPE)GroupIdx);
	}
}

void CScene::CreateTile(UINT _IXCount, UINT _IYCount)
{
	m_iTileX = _IXCount;
	m_iTileY = _IYCount;

	//타일 생성
	CTexture* pTileTex = CResMgr::GetInstance()->LoadTexture(L"Tile", L"texture\\tera2.bmp");
	
	for (UINT tileIDX = 0; tileIDX < _IXCount; tileIDX++) {
		for (UINT tileJDX = 0; tileJDX < _IYCount; tileJDX++) {
			CTile* pTile = new CTile();

			pTile->SetPos(Vec2((float)(tileJDX * TILE_SIZE), (float)(tileIDX * TILE_SIZE)));
			pTile->SetTexture(pTileTex);

			AddObject(pTile, GROUP_TYPE::TILE);
		}
	}
}

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

댓글 남기기