C++RPG控制台游戏,用窗口基类管理各个窗口

GameMgr中定义窗口基类指针。通过更该窗口基类的指针指向(更改为:菜单、地图、商店等窗口)实现窗口之间的转换

问题:

GameMgr是否不再直接管理菜单、地图、商店。是否还要定义其成员变量。倘或不再直接管理,如何在一个窗口中,拿到另一个窗口数据?

窗口管理为何不好:

一、GameMgr不再对map等场景进行直接管理,而是在管理其父类CWndBase:

GameMgr不再对map等场景进行直接管理,而是在管理其父类CWndBase,并将各个场景对象压入vecter<CWndBase*>容器中,这样gameMgr要调用map等场景的其他方法时,都要进行一次向下的强制转换。(向下的强制转换是不安全的)等到游戏规模变大时,我们很难预测到容器中存放的究竟是CWndBase的哪一个子类,直接的强制转换是不明智的,而遍历容器去寻找符合的子类,确保强制转换的正确性会导致每一次向gameMgr取数据都会遍历一遍容器,个人觉得会影响运行速度。且,多出了很多可能意想不到的异常

二、进入新场景时,是新建子类对象的指针,并将其压入vector<CWndBase>中。这样会导致每次进入新的场景时,都是一个全新的场景(这一点已经得到了验证)。

三、如何使用窗口管理:

窗口基类应当怎么使用:A类要对B类进行管理就应当让A类的成员变量

里面具有B类,并设置相关的get、set等函数。例如:GameMgr要对map、以及shop进行管理,就应当让GameMgr里面具有:m_gameMap和m_Shop两个成员变量并且对其进行new的操作,不需要其压入vector<wndBase>的容器中。倘若要进行渲染,则直接使用GameMgr里面的getShop的方法,获取CShop的对象。如下(GameMgr对shop进行管理):

GameMgr:

//#pragma once//避免类被重复定义
#ifndef __GAMEMGR_H__
#define __GAMEMGR_H__
#include "GameMenu.h"
#include "GameMap.h"
#include "Shop.h"
#include "WndBase.h"
class CGameMgr
{
public:
	CGameMgr();//构造函数:对象创建的时候调用,并且只调用一次。  初始化
	~CGameMgr();
	//成员函数
	void update();
	void onRender();
	void restoreScene();
	void changeScene(CWndBase* pWnd);
	CShop* getShop()
	{
		return m_pShop;
	};
	static CGameMgr* getInstance();
private:
	static CGameMgr* m_spInstance;
private:
	CWndBase* m_pCurWnd;
	vector<CWndBase*> m_vecScene;
	CShop* m_pShop;
};
#endif


#include "stdafx.h"
#include "GameMgr.h"

CGameMgr* CGameMgr::m_spInstance = nullptr;
CGameMgr::CGameMgr()
{
	//CGameMenu* m_pGameMenu重新定义了一个对象
// 	m_pGameMenu = new CGameMenu();//初始化的时候必须去想操作系统申请内存
// 	m_pGameMap = new CGameMap();
// 	m_pShop = new CShop();
	m_pCurWnd = new CWndBase();
	m_pShop = new CShop;
	//m_nGameState = E_GAME_MENU;
}


CGameMgr::~CGameMgr()
{
}

void CGameMgr::update()
{
	// 	if (E_GAME_MENU == m_nGameState)
	// 	{
	// 		m_pGameMenu->update();
	// 	}
	// 	else if (E_GAME_MAP == m_nGameState)
	// 	{
	// 		m_pGameMap->update();
	// 	}
	// 	else if (E_GAME_SHOP == m_nGameState)
	// 	{
	// 		m_pShop->update();
	// 	}
	m_pCurWnd->update();
}

void CGameMgr::onRender()
{
// 	if (E_GAME_MENU == m_nGameState)
// 	{
// 		m_pGameMenu->onRender();
// 	}
// 	else if (E_GAME_MAP == m_nGameState)
// 	{
// 		m_pGameMap->onRender();
// 	}
// 	else if (E_GAME_SHOP == m_nGameState)
// 	{
// 		m_pShop->onRender();
// 	}
	m_pCurWnd->onRender();
}

CGameMgr* CGameMgr::getInstance()
{
	//当前单例没有被创建出来(他为空),就要去new出来
	if (nullptr == m_spInstance)
	{
		m_spInstance = new CGameMgr();
	}
	return m_spInstance;
}

void CGameMgr::changeScene(CWndBase* pWnd)
{
	m_vecScene.push_back(m_pCurWnd);//把当前窗口存储起来
	m_pCurWnd = pWnd;//当前窗口改成要切换过去的窗口
}

void CGameMgr::restoreScene()
{
	if (m_vecScene.size() > 1)
	{
		//delete m_pCurWnd;
		m_pCurWnd = m_vecScene.back();
		m_vecScene.pop_back();
	}
}

 当要改变场景为shop的时候:

	if (nullptr != pNpc)//不为空,pNpc存在
	{
		//碰到NPC的时候把玩家坐标还原
		m_pPlayer->resotore();
		//切换到商店。
		//CGameMgr::getInstance()->setGameState(E_GAME_SHOP);
		//通过当前碰到这个npc去找数据管理者拷贝相应的物品数据:需要数据找数据管理者拿:商店。
		//能否取到商店:商店的接口传一个npcID进去,在商店里面通过npcID去找数据管理者取到相应的数据
		//CGameMgr::getInstance()->getShop()->setItems(pNpc->getID());
		//CShop* pShop = new CShop();
		CGameMgr::getInstance()->getShop()->setItems(pNpc->getID());
		//pShop->setItems(pNpc->getID());
		CGameMgr::getInstance()->changeScene(CGameMgr::getInstance()->getShop());
	}

总结:

因为之前代码设置了窗口基类之后,GameMgr内不再对gameMap等进行管理(不再具有成员变量m_gameMap等,只有其父类容器),所以进行操作十分复杂。更该过后的代码,GameMgr具有gameMap*类型的成员变量,对其进行了管理。

在游戏管理模式里面,A类要对B类进行管理,就应当让A类直接具有B类的成员变量。

猜你喜欢

转载自blog.csdn.net/qq_41791653/article/details/81939257