zoukankan      html  css  js  c++  java
  • boost statechart 模板化的state类

    备忘:

        项目中大量使用了boost的statecahrt状态机.这玩意麻烦,但有时确实挺好用的.排查时让人头痛.尤其是项目整个状态机庞大且混乱,穿插了大量不规则的不属于statechart框架的全局状态变量(bool变量啥的).但工作需要,我需要实现除去人物逻辑动作等状态之外,各个状态都能有一个子状态,这样状态切换时都能进行全屏特效或别的工作.目前的办法是给state加上模板参数.事实上,项目中的确实缺乏通用子状态概念,导致实现不同职业的状态机时,类似一些特效开关,加载配置等,全部都需要在每个职业实现一个状态机,状态机里全部重写这些步骤一遍.一旦这些通用的设置有修改,就要全部去找到各个职业的状态机,然后再找到各个状态,一个一个改之.

    #ifndef __fsm_h__
    #define __fsm_h__
    
    #include <boost/statechart/event.hpp>
    #include <boost/statechart/state_machine.hpp>
    #include <boost/statechart/simple_state.hpp>
    #include <boost/statechart/state.hpp>
    #include <boost/statechart/custom_reaction.hpp>
    #include <boost/statechart/transition.hpp>
    #include <boost/statechart/result.hpp>
    
    #include <boost/config.hpp>
    
    #ifdef BOOST_INTEL
    #  pragma warning( disable: 304 ) // access control not specified
    #endif
    
    namespace Alpha
    {
        namespace fsm
        {
            namespace sc = boost::statechart;
            namespace mpl = boost::mpl;
    
            template< class MostDerived,
            class InitialState,
            class Allocator = std::allocator< void >,
            class ExceptionTranslator = sc::null_exception_translator >
            struct fsm_machine : public sc::state_machine<MostDerived, InitialState, Allocator, ExceptionTranslator>
            {
    
            };
    
            struct nulltype {};
    
            template<class Host> 
            struct fsm_state_init_converter
            {
                typedef mpl::list<Host>     type;
                typedef Host                origin_type;
            };
    
            template<> 
            struct fsm_state_init_converter< mpl::list<> >
            {
                typedef mpl::list<>  type;
                typedef nulltype     origin_type;
            };
    
            template<
                class MostDerived, 
                class Context, 
                class InnerInitial = boost::mpl::list<>, 
                    sc::history_mode historyMode = sc::has_no_history
            >
            struct fsm_state : public sc::state<MostDerived, Context, typename fsm_state_init_converter<InnerInitial>::type, historyMode>
            {
                typedef sc::state<MostDerived, Context, typename fsm_state_init_converter<InnerInitial>::type, historyMode> my_state_base;
                typedef typename fsm_state_init_converter<InnerInitial>::origin_type initial_type;
    
                fsm_state(my_state_base::my_context ctx):my_state_base(ctx) {}
            };
    
            template<class Context> 
            struct fsm_common_init_state : public fsm::fsm_state<fsm_common_init_state<Context>, Context>
            {
                typedef fsm::fsm_state<fsm_common_init_state<Context>, Context> my_state_base;
    
                fsm_common_init_state(my_state_base::my_context ctx):my_state_base(ctx) 
                { std::cout << "enter fsm_common_init_state\n"; }
                ~fsm_common_init_state() { std::cout << "exit fsm_common_init_state\n"; }
            };
    
            template<class Context, 
                template<class _Context> class common_init_state_type = fsm_common_init_state>
            struct fsm_common_state : public fsm::fsm_state<fsm_common_state<Context, common_init_state_type>, 
                Context, 
                common_init_state_type<fsm_common_state<Context, common_init_state_type>> >
            {
                typedef fsm_common_state<Context, common_init_state_type> this_type;
                typedef fsm::fsm_state<this_type, Context, common_init_state_type<this_type> > my_state_base;
    
                fsm_common_state(my_state_base::my_context ctx):my_state_base(ctx) 
                { std::cout << "enter fsm_common_state\n"; }
                ~fsm_common_state() { std::cout << "exit fsm_common_state\n"; }
            };
    
        }
    }
    
    #endif

     下一步搭配正交区域.目前遇到的问题是当前状态跳转时,实现fading时需要进入一个中间状态,而不能直接跳转(例如下一个场景),将需要某种回调机制.当然这些实际上可以通过statechart的event和reaction模拟,但之前都是通过全局变量来控制,而且场景建立删除牢牢的变为当前状态的一部分了.如果level能够做成继承多态的,而不是绑定到状态上,靠状态区分level,应是更合适的方法.目前已经定死了,解决办法就是再添加2个全局的事件,通知通用子状态,因为退出时需要进行一个延迟几秒左右的处理,来进行类似淡出的效果.当然,如果渲染和逻辑能够支持多线程,就容易处理多了.也就不纠结这几秒的延迟事件了.暂告一段落.

     可能需要搭配的event带模板的.如下:

        template<class Host> struct EffectEvent_Fading : public sc::event<EffectEvent_Fading<Host>> {};
        template<class Host> struct EffectEvent_Blooming : public sc::event<EffectEvent_Blooming<Host>> {};
  • 相关阅读:
    个人总结
    第三次个人作业
    第二次结对作业
    第一次结对作业
    第二次个人编程作业
    第一次博客编程作业
    第一次随笔作业
    BUAA_2020_软件工程_提问回顾与总结
    BUAA_2020_软件工程_软件案例分析作业
    BUAA_2020_软件工程_结对项目作业
  • 原文地址:https://www.cnblogs.com/flytrace/p/2888375.html
Copyright © 2011-2022 走看看