レンズ

10202 ワード

仮想化を実装し、仮想化によって画面を変更および構成します.
レンズ
まず、親として使用されるシンを作成します.
-Scene.cpp-

#include "stdafx.h"
#include "Scene.h"


CScene::CScene()
{
}


CScene::~CScene()
{
}
-Scene.h


#pragma once
class CScene abstract
{
public:
	explicit CScene();
	virtual ~CScene();

public:
	virtual int Ready_Scene() =0;
	virtual void Update_Scene() = 0; 
	virtual void Render_Scene(HDC hDC) =0; 
	virtual void Release_Scene() = 0;
};

これは、純粋な仮想関数を構成するゲームオブジェクトなどのシーンの親を作成するクラスです.
シンマネージャ
用途に応じてゲームで使用されるさまざまなシーン(ゲームオブジェクトなど)を変更できるマネージャが必要です.仮想マネージャで実現します.
-Scene_Manager.cpp-

#include "stdafx.h"
#include "Scene_Manager.h"
#include "Loading.h"
#include "Stage.h"
#include "MyMenu.h"

//스택틱 변수를 널포인터로 초기화해줍니다.
CScene_Manager* CScene_Manager::m_pInstance = nullptr; 


CScene_Manager::CScene_Manager()
//이니셜라이저를 통해 멤버 변수들을 초기화해줍니다.
	:m_eCurScene(SCENE_END)
	, m_eNextScene(SCENE_END)
	, m_pScene(nullptr)
{
}


CScene_Manager::~CScene_Manager()
{
	Release_Scene_Manager(); 
}

void CScene_Manager::Scene_Change(ID eNextID)
{
	//FSM 유한 상태 기계 
	m_eNextScene = eNextID; 
	// 이경우는 어떤 경우 ? 즉 씬이 변경되야 하는 상황.
    
    	// 현재씬과 다음씬(들어온값)이 다른경우에만 씬을 교체해주어야합니다
        // 같은 값이 들어온다면 유지해주고 교체해주지않습니다.
        
	if (m_eCurScene != m_eNextScene)
	{
    		//우선 씬을 교체해주기위해 현재 씬을 삭제해줍니다.
		Safe_Delete(m_pScene); 
       		//스위치문을통해 들어온값에 맞는 씬을 추가해줍니다.
		switch (m_eNextScene)
		{
		case CScene_Manager::SCENE_LOADING:
			m_pScene = CLoading::Create(); 
			break;
		case CScene_Manager::SCENE_STAGE:
			m_pScene = CStage::Create(); 
			break;

		case CScene_Manager::SCENE_MENU:
			m_pScene = CMyMenu::Create(); 
			break;
		default:
			break;
		}
        	//다음 같은값이 들어오면 씬을 교체하지않을것이기때문에 
            	//커렌트씬을 변경해줍니다.
		m_eCurScene = m_eNextScene; 
	}
}
//업데이트와 렌더 릴리즈입니다.
//메인앱에서 게임오브젝트를 타지않고 이제 메인엡에서 씬을 탄후
//게임오브젝트를 탑니다.
void CScene_Manager::Update_Scene_Manager()
{
	m_pScene->Update_Scene(); 
}

void CScene_Manager::Render_Scene_Manager(HDC hDC)
{
	m_pScene->Render_Scene(hDC); 
}

void CScene_Manager::Release_Scene_Manager()
{
	Safe_Delete(m_pScene); 
}
-Scene_Manager.h-

#pragma once
class CScene; 
class CScene_Manager final
{
public:
	//각 씬에 맞는 열거체를 만들어줍니다.
	enum ID {SCENE_LOADING, SCENE_MENU,SCENE_STAGE, SCENE_END};
public:
	//씬 매니저는 싱글톤을 이용해 구성합니다.
	static CScene_Manager* Get_Instance()
	{
		if (nullptr == m_pInstance)
			m_pInstance = new CScene_Manager; 
		return m_pInstance; 
	}
	static void Destroy_Instance()
	{
		if (m_pInstance)
		{
			delete m_pInstance; 
			m_pInstance = nullptr; 
		}
	}
private:
	static CScene_Manager* m_pInstance; 
private:
	CScene_Manager();
	~CScene_Manager();
public:
	void Scene_Change(ID eNextID); 
	void Update_Scene_Manager(); 
	void Render_Scene_Manager(HDC hDC); 
	void Release_Scene_Manager(); 
private:
	// m_pScene이 실질적으로 가지고있는 씬이고 cur,next로 씬을 변경할때
    	// 사용합니다.
	CScene* m_pScene; 
	ID m_eCurScene; 
	ID m_eNextScene; 

};

モノトーンで、必要に応じてシーンを交換して表示できます.
≪ロード|Load|emdw≫
まず、ゲームで最初に登場するシーンを作成してシーンを読み込みましょう.
-Loading.cpp-

#include "stdafx.h"
#include "Loading.h"


CLoading::CLoading()
{
}


CLoading::~CLoading()
{
	Release_Scene(); 
}

int CLoading::Ready_Scene()
{
	return 0;
}

void CLoading::Update_Scene()
{
	if (CKey_Manager::Get_Instance()->Key_Up(KEY_RIGHT))
	{
		CScene_Manager::Get_Instance()->Scene_Change(CScene_Manager::SCENE_MENU);
	}
    //로딩은 초기화면 이기때문에 여기선 오른쪽키를 입력받으면 씬을 바꾸도록 했습니다.
    
}

void CLoading::Render_Scene(HDC hDC)
{
	HDC hMemDC = CBitmap_Manager::Get_Instance()->FindImage(L"Logo"); 
    //메인앱에서 미리 받아온 이미지를 가져와 화면에 그려줍니다.
	if (nullptr == hMemDC)
	{
		return; 
	}
	BitBlt(hDC, 0, 0, WINCX, WINCY, hMemDC, 0, 0, SRCCOPY); 
}

void CLoading::Release_Scene()
{
}

CScene* CLoading::Create()
{
	CScene* pInstance = new CLoading; 
	if (0 > pInstance->Ready_Scene())
		Safe_Delete(pInstance); 

	return pInstance;
}
-Loading.h-

#pragma once
#include "Scene.h"
class CLoading final:
	public CScene
{
private:
	explicit CLoading();
public:
	virtual ~CLoading();
public:
	// CScene을(를) 통해 상속됨
	virtual int Ready_Scene() override;
	virtual void Update_Scene() override;
	virtual void Render_Scene(HDC hDC) override;
	virtual void Release_Scene() override;
public:
	static CScene* Create(); 
};

既にロードが完了している場合は、既存のゲームコンポーネントをMainCPPで変更する必要があります.
以前は、メインアプリケーション→ゲームオブジェクトマネージャ→ゲームオブジェクトの順に行っていましたが
メインアプリケーション->仮想マネージャ->仮想ゲームオブジェクトマネージャ->ゲームオブジェクト.
まず、既存の要素がシーン内のステージクラスを作成して移動します.
更新およびレンダリングセクションでは、ゲームオブジェクトマネージャではなく仮想マネージャによって呼び出され、仮想マネージャのシーンでは対応するゲームオブジェクトマネージャが呼び出されます.
-MainApp.cpp-


#include "stdafx.h"
#include "MainApp.h"
#include "Player.h"
#include "Monster.h"
#include "Collision_Manager.h"
#include "Mouse.h"
#include "GameObject_Manager.h"
#include "Line_Manager.h"
#include "Bitmap_Manager.h"
#include "Scene_Manager.h"
CMainApp::CMainApp()
	:m_iFPS(0)
	, m_szFPS(L"")
	, m_dwFPSTime(0)
	,m_hDC(nullptr)
{
}
/*
원래 구조 
Client -> MainApp -> 각각의 오브젝트들 Update, Render 수행. 
Client -> MainApp -> GameObject_Manager-> 각각의 오브젝트들 Update, Render 수행. 
client -> Mainapp -> Scene_Manager -> Scene -> GameObject_Manager - > 각각의 오브젝트들 Update, Render 수행
*/

CMainApp::~CMainApp()
{
	Release_MainApp(); 
}

int CMainApp::Ready_MainApp()
{
	m_hDC = GetDC(g_hWnd); 
	m_dwFPSTime = GetTickCount(); 



	CBitmap_Manager::Get_Instance()->Insert_Bitmap(L"../Image/BackBuffer.bmp", L"BackBuffer"); 

	CBitmap_Manager::Get_Instance()->Insert_Bitmap(L"../Image/Back.bmp", L"DubleBuffer");
	CBitmap_Manager::Get_Instance()->Insert_Bitmap(L"../Image/maja2.bmp", L"maja2");
	CBitmap_Manager::Get_Instance()->Insert_Bitmap(L"../Image/Logo/Logo.bmp", L"Logo");

	CBitmap_Manager::Get_Instance()->Insert_Bitmap(L"../Image/Menu/Menu.bmp", L"Menu");
	CBitmap_Manager::Get_Instance()->Insert_Bitmap(L"../Image/Button/Start.bmp", L"Start");
	CBitmap_Manager::Get_Instance()->Insert_Bitmap(L"../Image/Button/Edit.bmp", L"Edit");
	CBitmap_Manager::Get_Instance()->Insert_Bitmap(L"../Image/Button/Exit.bmp", L"Exit");

	CScene_Manager::Get_Instance()->Scene_Change(CScene_Manager::SCENE_LOADING);

	return READY_OK; 
}

void CMainApp::Update_MainApp()
{
	CKey_Manager::Get_Instance()->Key_Update();
	CScene_Manager::Get_Instance()->Update_Scene_Manager();
}

void CMainApp::Render_MainApp()
{
// 	Rectangle(m_hDC, 0, 0, WINCX, WINCY); 
// 	Rectangle(m_hDC, 100, 100, WINCX - 100, WINCY - 100); 
	HDC hDubleBuffer = CBitmap_Manager::Get_Instance()->FindImage(L"DubleBuffer"); 

	HDC hMemDC = CBitmap_Manager::Get_Instance()->FindImage(L"BackBuffer"); 
	BitBlt(hDubleBuffer, 0, 0, WINCX, WINCY, hMemDC, 0, 0, SRCCOPY);

	CScene_Manager::Get_Instance()->Render_Scene_Manager(hDubleBuffer);

	++m_iFPS; 
	if (m_dwFPSTime + 1000 < GetTickCount())
	{
		swprintf_s(m_szFPS, L"FPS : %d", m_iFPS); 
		m_iFPS = 0; 
		m_dwFPSTime = GetTickCount(); 
	}
	TextOut(hDubleBuffer, 100, 100, m_szFPS, lstrlen(m_szFPS));

	BitBlt(m_hDC, 0, 0, WINCX, WINCY, hDubleBuffer, 0, 0, SRCCOPY); 
}

void CMainApp::Release_MainApp()
{
	ReleaseDC(g_hWnd, m_hDC); 
	CKey_Manager::Destroy_Instance(); 
	CBitmap_Manager::Destroy_Instance(); 
	CGameObject_Manager::Destroy_Instance(); 
	CLine_Manager::Destroy_Instance(); 
	CScene_Manager::Destroy_Instance();
}
メニュー
次に、ゲームメニューボタンを表示するメニューボタンを作成します.
まず、ロード中に右クリックを入力すると、メニューに移動するように構成されているため、すぐにメニュークラスを作成します.
ツールバーの
メニューに置くボタンをゲームオブジェクトに継承して実現
-MyButton.h-

#pragma once
#include "GameObject.h"
class CMyButton final:
	public CGameObject
{
private:
	explicit CMyButton();
public:
	virtual ~CMyButton();
public:
	void Set_FrameKey(const TCHAR* pFrameKey) { m_pFrameKey = pFrameKey;  }
public:
	// CGameObject을(를) 통해 상속됨
	virtual int Ready_GameObject() override;
	virtual int Update_GameObject() override;
	virtual void Late_Update_GameObject() override;
	virtual void Render_GameObject(HDC hDC) override;
	virtual void Release_GameObject() override;
public:
	static CGameObject * Create();

private:
	const TCHAR* m_pFrameKey; //프레임키를 통해 이미지를 불러옵니다
	int m_iDrawID; //ID를통해 그림을 어디서부터 읽어올지 결정합니다
};
-MyButton.cpp-

#include "stdafx.h"
#include "MyButton.h"


CMyButton::CMyButton()
	:m_iDrawID(0)
{
}


CMyButton::~CMyButton()
{
}

int CMyButton::Ready_GameObject()
{
	m_tInfo.iCX = 150; 
	m_tInfo.iCY = 150; 
    //버튼 이미지의 맞춰 크기를 설정해줍니다.

	return READY_OK;
}

int CMyButton::Update_GameObject()
{
	CGameObject::Update_Rect_GameObject();
	POINT pt{}; 
	//커서의 위치를 가져온뒤 좌표를 화면에 맞게 해주고
    //PtInRect를통해 만약 마우스와 충돌하면m_iDrawID = 1로
    //이미지를 바꿔줍니다.
	GetCursorPos(&pt); 
	ScreenToClient(g_hWnd, &pt); 
	if (PtInRect(&m_tRect, pt))
	{

		m_iDrawID = 1; 
	}
	else m_iDrawID = 0; 
	return 0;
}

void CMyButton::Late_Update_GameObject()
{
}

void CMyButton::Render_GameObject(HDC hDC)
{
	CGameObject::Update_Rect_GameObject();
	HDC hMemDC = CBitmap_Manager::Get_Instance()->FindImage(m_pFrameKey);
	if (nullptr == hMemDC)
		return; 

	GdiTransparentBlt(hDC,
		m_tRect.left,
		m_tRect.top,
		m_tInfo.iCX,
		m_tInfo.iCY, 
		hMemDC,
		m_tInfo.iCX * m_iDrawID, 0, //X축의 위치를 ID에따라 다르게 그려줍니다.
		m_tInfo.iCX, m_tInfo.iCY,
		RGB(255, 255, 255));
}

void CMyButton::Release_GameObject()
{
}
CGameObject * CMyButton::Create()
{
	CGameObject* pInstance = new CMyButton;
	if (0 > pInstance->Ready_GameObject())
		Safe_Delete(pInstance);

	return pInstance;
}


プライマリ・ロゴがこのように表示され、鍵が受信されると、次の画面に移動するように構成されます.