我们进入一个游戏的时候, 通常会播放一段开场动画, 然后显示一个菜单界面. 动画(splash)稍微难一点, 我们先不做, 先看如何实现菜单.
资源
资源的加载还使交由TextureManager来完成即可.
状态机
为了便于管理资源和对象, 我们这里来使用有限状态机(Finite State Machine)来重写我们的程序. 首先我们创造一个抽象类, 然后以此为基础创建MenuState和PlayState. 如下
// GameState
#ifndef GAMESTATE_H_INCLUDED
#define GAMESTATE_H_INCLUDED
#include <string>
class GameState
{
public:
virtual void update() = 0;
virtual void render() = 0;
virtual bool onEnter() = 0;
virtual bool onExit() = 0;
virtual std::string getStateID() const = 0;
virtual ~GameState() {}
};
#endif // GAMESTATE_H_INCLUDED
// MenuState.h
#ifndef MENUSTATE_H_INCLUDED
#define MENUSTATE_H_INCLUDED
#include <iostream>
#include <vector>
#include "GameObject.h"
#include "GameState.h"
class MenuState : public GameState
{
public:
virtual void update();
virtual void render();
virtual bool onEnter();
virtual bool onExit();
virtual std::string getStateID() const { return s_menuID; }
virtual ~MenuState();
private:
static const std::string s_menuID;
std::vector<GameObject*> m_gameObjects;
};
#endif // MENUSTATE_H_INCLUDED
// GameStateMachine.h
#ifndef GAMESTATEMACHINE_H
#define GAMESTATEMACHINE_H
#include <vector>
#include "GameState.h"
class GameStateMachine
{
public:
void pushState(GameState* pState);
void changeState(GameState* pState);
void popState();
void update();
void render();
~GameStateMachine();
private:
std::vector<GameState*> m_gameStates;
};
#endif // GAMESTATEMACHINE_H
// GameStateMachine.cpp
#include <iostream>
#include "GameStateMachine.h"
GameStateMachine::~GameStateMachine()
{
if (!m_gameStates.empty()) {
delete m_gameStates.back();
m_gameStates.pop_back();
}
}
void GameStateMachine::pushState(GameState* pState)
{
m_gameStates.push_back(pState);
m_gameStates.back()->onEnter();
}
void GameStateMachine::changeState(GameState* pState)
{
if (!m_gameStates.empty()) {
if (m_gameStates.back()->getStateID() == pState->getStateID()) {
return;
}
if (m_gameStates.back()->onExit()) {
delete m_gameStates.back();
m_gameStates.pop_back();
}
}
m_gameStates.push_back(pState);
m_gameStates.back()->onEnter();
}
void GameStateMachine::popState()
{
if (!m_gameStates.empty()) {
if (m_gameStates.back()->onExit()) {
delete m_gameStates.back();
m_gameStates.pop_back();
}
}
}
void GameStateMachine::update()
{
if (!m_gameStates.empty()) {
m_gameStates.back()->update();
}
}
void GameStateMachine::render()
{
if (!m_gameStates.empty()) {
m_gameStates.back()->render();
}
}
然后我们用GameStateMachine来统一管理所有的状态类. 相应的我们需要将原来Game.cpp中的代码用GameStateMachine的替换.