游戏底层逻辑,MainLoop&&FSM&&MSG(二)

        • MSG消息机制
        • 准备写一个有关游戏底层算法物理算法以及AI重点是机器学习在游戏中的应用的长篇博客欢迎大家指正交流

MSG–消息机制

学过操作系统的同学们都知道,windows底层的数据传递有一个完善的消息机制(当时读书的时候也是烦透了PeekMsg这种东西,不过不得不说现在想起来其实操作系统是一门很有用的软件架构设计的书,操作系统基本包含了所有的基本软件体系架构),好了,闲谈无多,我们来看看代码。
首先是基本的消息结构体

Telegram.h

struct Telegram
{
    long int dispatchTime_;
    int sender_;
    int receiver_;
    MsgType msg_;
    void* extraInfo_;
    bool operator<(const Telegram& telegram)const
    {
        return (this->dispatchTime_ < telegram.dispatchTime_);
    }
    Telegram(long int dispatchTime, int sender, int receiver, MsgType msg, void* extraInfo):
        dispatchTime_(dispatchTime),
        sender_(sender),
        receiver_(receiver),
        msg_(msg),
        extraInfo_(extraInfo)
    {

    }
};

这个结构体包含了时序传输者接受者,消息以及额外信息。用int的类型定义的sender和receiver其实是用户的ID,我们可以通过ID找到实体的指针。

我们定义了“<”的运算符重载,这样在map结构中会根据此符号进行元素排序,我们就可以拥有带有时序的消息集合了。

然后是消息处理机,本质是一个任务队列,根据任务时序进行消息传递。
MsgDispatcher.h

class MsgDispatcher :public Singleton<MsgDispatcher>
{
private:
    ~MsgDispatcher(){}
    MsgDispatcher(const MsgDispatcher& msgDispatcher)
    {
        assert(this != &msgDispatcher&&"error:copy source is the same object");

        std::for_each(
            this->_msgQueue.cbegin(),
            msgDispatcher.getQueue().cbegin(),
            [this](Telegram tel)
        {
            this->_msgQueue.insert(tel);
        }
        );
    }
    inline MsgDispatcher& operator=(const MsgDispatcher& msgDispatcher)
    {
        assert(this != &msgDispatcher&&"error:copy source is the same object");

        std::for_each(
            this->_msgQueue.cbegin(),
            msgDispatcher.getQueue().cbegin(),
            [this](Telegram tel)
        {
            this->_msgQueue.insert(tel);
        }
        );
        return *this;
    }
private:
    std::set<Telegram> _msgQueue;//ordered by dispatchTime
protected:
    void discharge(BaseEntity*, const Telegram&);
public:
    MsgDispatcher(){}
public:
#define DEFAULT_DELAY 0.0f
#define NO_EXTRA_INFO NULL
public:
    void addMsg(long int, int, int, int, void*);
    void dispatchMsg();//executed in MainLoop
    std::set<Telegram> getQueue() const
    {
        return _msgQueue;
    }
    string Msg2Str(MsgType msg)
    {
        switch (msg)
        {
        case Bob_home:
            return "Bob is coming home now"; 
            break;
        case Stew_cooked:
            return "Stew is being cooked";
            break;
        default:
            return "";
            break;
        }
    }
};


#define MSGDISPATCHER MsgDispatcher::instance()

以及实现

MsgDipatcher.cpp

void MsgDispatcher::discharge(BaseEntity* receiver, const Telegram& tel)
{
    if (!receiver->handleMsg(tel))
    {
        cout << "\n" << "MSG Missing";
    }
}

void MsgDispatcher::addMsg(long int delay, int sender, int receiver, int msg, void* extraInfo)
{
    auto E_receiver = EMGR->getEntityByID(receiver);
    auto Msg = MsgType(msg);

    assert(E_receiver&&"recevier cannot be found");

    Telegram tel(clock(), sender, receiver, Msg, extraInfo);

    if (delay==0)
    { }
    else
    {
        long int currentTime = clock();
        tel.dispatchTime_ = delay + currentTime;
    }

    this->_msgQueue.insert(tel);
}

void MsgDispatcher::dispatchMsg()
{
    while (!_msgQueue.empty() &&
        (_msgQueue.begin()->dispatchTime_ < long(clock())) &&
        (_msgQueue.begin()->dispatchTime_ > 0))
    {
        //read the telegram from the front of the queue
        const Telegram& telegram = *_msgQueue.begin();

        //find the recipient
        BaseEntity* receiver = EMGR->getEntityByID(telegram.receiver_);

        cout << "\nQueued telegram ready for dispatch: Sent to "
            << EMGR->getNameOfEntity(receiver->ID()) << ". Msg is " << Msg2Str(telegram.msg_);

        //send the telegram to the recipient
        discharge(receiver, telegram);

        //remove it from the queue
        _msgQueue.erase(_msgQueue.begin());
    }
}

此处的消息为枚举的类(为了测试,只有两个消息),类似于SQL中的消息语句,你可以扩展一个消息解析程序,用字符串来传递消息,比如Time_Sender_Reciever_Msg_ExtraInfo这样的格式,无论是本地消息亦或服务器传输的网络消息,都可以解析处理,可扩展性也更强。

该类也是单例类,单例会广泛地使用在此架构中,然后用MainLoop的bindfunc函数绑定dispatchMsg函数,就形成了一个不断刷新的消息处理结构。

准备写一个有关游戏底层算法,物理算法,以及AI(重点是机器学习在游戏中的应用)的长篇博客,欢迎大家指正交流╰( ̄▽ ̄)╯

你可能感兴趣的:(游戏,架构设计)