• Cocos2d-x 3.2 学习笔记(十六)保卫萝卜 游戏主循环与定时器


         保卫萝卜~想法一直存在于想法,实战才是硬道理!有想法就去实现,眼高手低都是空谈。

     
    一、游戏主循环GameSchedule
         主循环是游戏处理逻辑,控制游戏进度的地方,处理好主循环是很重要的。写一个简单的游戏主循环是很有必要的~
    游戏主循环有开始、有结束、有暂停、有恢复把握好进度,控制好游戏,处理好逻辑。我在Cocos2dx进入主场景时开启游戏主循环,在永远不再使用时删除主循环,在游戏暂停时pause主循环,在游戏恢复时resume主循环。
     
    #ifndef __GameSchedule__
    #define __GameSchedule__
    #include "cocos2d.h"
    
    USING_NS_CC;
    class GameSchedule : public Ref
    {
    public:
        static GameSchedule* getInstance();
        void start();
        void end();
        static void pause();
        static void resume();
    private:
        virtual void onExit();
        ~GameSchedule();
        void globalUpdate(float time);
        void init();
    };
    
    #endif
    #include "GameSchedule.h"
    #include "GameDelayTime.h"
    #include "SceneMgr.h"
    static GameSchedule* _instance = nullptr;
    static bool _pause = true;
    
    GameSchedule* GameSchedule::getInstance()
    {
        if( !_instance )
        {
            _instance = new GameSchedule();
            _instance->init();
        }
        return _instance;
    }
    
    void GameSchedule::init()
    {
        _pause = true;
    }
    
    void GameSchedule::start()
    {
        log("GameSchedule -----> start ");
        _pause = false;
        Director::getInstance()->getScheduler()->schedule(schedule_selector(GameSchedule::globalUpdate),this,0,false);
    }
    
    void GameSchedule::end()
    {
        log("GameSchedule -----> end ");
        Director::getInstance()->getScheduler()->unschedule(schedule_selector(GameSchedule::globalUpdate),this);
        CC_SAFE_DELETE(_instance);
    }
    
    void GameSchedule::pause()
    {
        log("GameSchedule -----> pause ");
        _pause = true;
    }
    
    void GameSchedule::resume()
    {
        log("GameSchedule -----> resume ");
        _pause = false;
    }
    
    void GameSchedule::globalUpdate(float time)
    {
          if( _pause ) return;
          GameDelayTime::getInstance()->UpdateTime(time);
         SceneMgr::getInstance()->UpdateScene(time);
    }
    
    
    void GameSchedule::onExit()
    {
        log("GameSchedule dispose!!!!1111");
    }
    
    GameSchedule::~GameSchedule()
    {
        log("GameSchedule dispose!!!!222");
    }
    GameSchedule.cpp
     
    使用静态单例创建主循环对象,并使用Schedule 注册函数接口,作为引擎的主循环回调。
     
    Director::getInstance()->getScheduler()->schedule(schedule_selector(GameSchedule::globalUpdate),this,0,false);
     
    这里的GameSchedule::globalUpdate函数将是逻辑处理的开始,定时器刷新,场景处理等。
     
    在进入主场景时开启入主循环,实现游戏的逻辑处理。
     
    二、定时器GameDelayTime
     
         定时器也就是定时回调,在有限时间内调用指定目标函数。这在一些游戏逻辑处理中很有用,包括一些动作处理(Cocos2dx中有延时动作和回调动作)。当然,有一个自己写的处理函数,我想是非常棒的~自己动手才能理解。
     
         定时器的处理类GameDelayTime将会集中处理所有的定时器、更新定时器、删除定时器。当然GameDelayTime类将会出现在游戏主循环GameSchedule::globalUpdate函数中,使用游戏主循环控制整个游戏的所有动作表现,当游戏暂停时停止所有逻辑处理,等待再次恢复。定时器数据类DelayTimeDate是定时器的数据中心,记录定时器的延迟时间、延迟目标等。如果达到延迟时间将会调用目标函数,并退出自更新,等待处理类GameDelayTime删除。
         游戏中的定时器是危险的,如果在场景中使用了定时器或在结点对象中使用定时器时,必须在退出场景或移除结点时删除所使用的定时器!
    如:Node::onExit()时 删除定时器对象。这是至关重要的!如果结点已移除而没有删除定时器对象,那么定时器指针会一直存在于内存,指针成为野指针,到达延迟时间时被调用将会产生不可预料的麻烦。(我很想知道该怎样去判断一个函数指针指向的目标是否被释放……这样就可以避免野指针调用后崩溃,自己c++太菜……希望有人能告诉我)。
     
    #ifndef __GameDelayTime__
    #define __GameDelayTime__
    
    #include "cocos2d.h"
    using namespace std;
    USING_NS_CC;
    
    class DelayTimeDate
    {
    public:
        static DelayTimeDate* create( float delayTime,std::function<void()> callback );
        CC_SYNTHESIZE( float, delayTime, DelayTime );
        CC_SYNTHESIZE( std::function<void()>, callback, Callback );
        CC_SYNTHESIZE_READONLY( float, time, TotalTime );
        bool update(float time);
    private:
        float _time;
        void init( float delayTime,std::function<void()> callback ){
            _time = 0;
            setDelayTime(delayTime);
            setCallback(callback);
        }
    };
    
    
    class GameDelayTime
    {
    public:
        static GameDelayTime* getInstance();
        DelayTimeDate* addDelayTimeCallBack( float delayTime,std::function<void()> callback );
        void removeDelayTimeCallBack( DelayTimeDate* delayTimeDate );
        void UpdateTime(float time);
    private:
        vector<DelayTimeDate*> _keyMap;
    
        void init();
    
    };
    
    #endif
    #include "GameDelayTime.h"
    
    static GameDelayTime* _instance = nullptr;
    
    GameDelayTime* GameDelayTime::getInstance()
    {
        if(!_instance)
        {
            _instance = new GameDelayTime();
            _instance->init();
        }
        return _instance;
    }
    
    void GameDelayTime::init()
    {
    }
    
    DelayTimeDate* GameDelayTime::addDelayTimeCallBack( float delayTime,std::function<void()> callback )
    {
        auto delayTimeDate = DelayTimeDate::create(delayTime,callback);
        _keyMap.push_back(delayTimeDate);
        return delayTimeDate;
    }
    
    void GameDelayTime::removeDelayTimeCallBack( DelayTimeDate* delayTimeDate )
    {
        int size = _keyMap.size();
        while (size-->0)
        {
            if(delayTimeDate == _keyMap.at(size) )
            {
                _keyMap.erase(_keyMap.begin()+size);
                CC_SAFE_DELETE(delayTimeDate);
                break;
            }
        }
    }
    
    void GameDelayTime::UpdateTime(float time)
    {
        int size = _keyMap.size();
        while (size-->0)
        {
            auto delayTimeDate = _keyMap.at(size);
            if( delayTimeDate != nullptr )
            {
                bool isCallBack = delayTimeDate->update(time);
                if( isCallBack )
                {
                    removeDelayTimeCallBack(delayTimeDate);
                }
            }
    
        }
    }
    
    DelayTimeDate* DelayTimeDate::create( float delayTime,std::function<void()> callback )
    {
        DelayTimeDate* delayTimeDate = new DelayTimeDate();
        delayTimeDate->init(delayTime,callback);
        return delayTimeDate;
    }
    
    bool DelayTimeDate::update(float time)
    {
        _time+=time;
        if( _time >= getDelayTime() )
        {
            if( callback )
            {
                callback();
                return true;
            }
        }
        return false;
    }
    GameDelayTime.cpp
     
    三、结合
         游戏主循环与定时器基本就这样了,我的实现比较简单。
     
    简单出兵应用:
     
     
      简单的控制主循环实现游戏的暂停逻辑处理。目前是比较简单的实现,希望后续能想到更好的idea。
  • 相关阅读:
    Ubuntu 16.04 samba详细配置及使用(将linux中的共享目录设置成windows中的一个映射磁盘)
    在python上获得随机字符
    Internet Information Services (IIS)管理器 部署网站报错
    SQL Server 2019 安装过程中如何设置二进制
    W: http://archive.ubuntukylin.com:10006/ubuntukylin/dists/xenial/InRelease: Signature by key 6CE35A4EBAB676094476BE7CD259B7555E1D3C58 uses weak digest algorithm (SHA1)
    Django命令行相关命令 以及创建一个空白网页的步骤
    网络爬虫之定向爬虫:爬取当当网2015年图书销售排行榜信息(Crawler)
    Ubuntu 16.04 Django安装和配置
    问题记录2:TypeError: write() argument must be str, not bytes
    问题记录1:The VMware Authorization Service is not running.
  • 原文地址:https://www.cnblogs.com/Richard-Core/p/4234152.html
Copyright © 2020-2023  润新知