• CCDirector导演类


    CCDirector类是Cocos2D-x游戏引擎的核心。它用来创建而且控制着屏幕的显示,同一时候控制场景的显示时间和显示方式。

    在整个游戏里一般仅仅有一个导演。游戏的開始、结束、暂停都会调用CCDirector类的方法。CCDirector类具有例如以下功能。

    • 初始化OpenGL会话。
    • 设置OpenGL的一些參数和方式。

    • 訪问和改变场景以及訪问Cocos2D-x的配置细节。
    • 訪问视图。

    • 设置投影和朝向。
    须要说明的是,CCDirector是单例模式,调用CCDirector方法的标准方式例如以下:
    • CCDirector::sharedDirector()->函数名

    CCDirector类的继承关系。如图3-8所看到的。


    CCDisplayLinkDirector继承了CCDirector,是一个能够自己主动刷新的导演类。它仅仅支持1/60 、1/30 和1/15三种动画间隔(帧间隔)。在Cocos2D-x里面。在游戏的不论什么时间,仅仅有一个场景对象实例处于执行状态。而导演就是流程的总指挥,它负责游戏全过程的场景切换。这也是典型的面向对象和分层的设计原则。以下分别介绍CCDirector类的成员数据和函数。

    先看返回单例对象的方法

    Director* Director::getInstance(){    
    if (!s_SharedDirector)    
    {       
    s_SharedDirector = new DisplayLinkDirector();       
    s_SharedDirector->init();    
    }    
    return s_SharedDirector;}

    注意,返回的是DisplayLinkDirector这个类。而且在创建完 DisplayLinkDirector对象之后调用了init方法,看一下init方法。

    从这种方法里面我们再一次了解一下,Director详细都能干什么,和一些内部初始化的工作是怎么完毕的

    bool Director::init(void){    
    setDefaultValues();    
    // scenes    
    _runningScene = nullptr;    
    _nextScene = nullptr;    
    _notificationNode = nullptr;    
    _scenesStack.reserve(15);    
    // FPS    
    _accumDt = 0.0f;    
    _frameRate = 0.0f;    
    _FPSLabel = _drawnBatchesLabel = _drawnVerticesLabel = nullptr;    
    _totalFrames = _frames = 0;    
    _lastUpdate = new struct timeval;    
    // paused ?    
    _paused = false;    
    // purge ?    
    _purgeDirectorInNextLoop = false;    
    _winSizeInPoints = Size::ZERO;    
    _openGLView = nullptr;    
    _contentScaleFactor = 1.0f;  
    // scheduler    
    _scheduler = new Scheduler();    
    
    // action manager    
    _actionManager = new ActionManager();    
    _scheduler->scheduleUpdate(_actionManager, Scheduler::PRIORITY_SYSTEM, false);    
    _eventDispatcher = new EventDispatcher();    
    _eventAfterDraw = new EventCustom(EVENT_AFTER_DRAW);    
    _eventAfterDraw->setUserData(this);    
    _eventAfterVisit = new EventCustom(EVENT_AFTER_VISIT);    
    _eventAfterVisit->setUserData(this);    
    _eventAfterUpdate = new EventCustom(EVENT_AFTER_UPDATE);    
    _eventAfterUpdate->setUserData(this);    
    _eventProjectionChanged = new EventCustom(EVENT_PROJECTION_CHANGED);    
    _eventProjectionChanged->setUserData(this);    
    
    //init TextureCache    
    initTextureCache();    
    
    _renderer = new Renderer;
    
    #if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) && (CC_TARGET_PLATFORM != CC_PLATFORM_WP8)    
    _console = new Console;
    #endif    
    return true;}

    能够看到。Director这个大管家初始化了 ActionManager 动作管理器,并将 _actionManager加到了定时器里。初始化了EventDispatcher EventCustom 等事件。初始化了纹理 和渲染器 Rendere。

    以下我们再看一下DisplayLinkDirector这个类。这是Director的实体类。

    class DisplayLinkDirector : public Director
    {
    public:    
     DisplayLinkDirector(): _invalid(false){}   
     
    //    
    // Overrides    
    //    
    virtual void mainLoop() override;    
    virtual void setAnimationInterval(double value) override;    
    virtual void startAnimation() override;    
    virtual void stopAnimation() override;
    
    protected:    
     bool _invalid;};
    这个类实现了Director的几个关键的虚函数。mainLoop这个是最基本的了,上面我们一再说逻辑循环,事实上都是指这个函数。全部的操作,动画,渲染。定时器都在这里驱动的。游戏主循环里重复的调度 mainLoop来一帧一帧的实现游戏的各种动作。动画……. mainLoop来决定当前帧该运行什么。是否到时间运行等等。

    void DisplayLinkDirector::mainLoop()
    {    
    if (_purgeDirectorInNextLoop){
         _purgeDirectorInNextLoop = false;
         purgeDirector();    
       }else if (!_invalid)    
           {drawScene();             
           // release the objects        
           PoolManager::getInstance()->getCurrentPool()->clear();    
           }
    }
    代码非常easy,依据对 purgeDirectorInNextLoop 推断来决定mainLoop是否应该清除。
    _invalid来决定 Director是否应该进行逻辑循环。

    这段代码非常easy,主要操作都封闭到了 drawScene里面后面我们跟进drawScene来看看每一个逻辑帧都干了些什么。

    后面另一句代码:PoolManager::getInstance()->getCurrentPool()->clear();

    从命名上来看是做清除操作,应该是内存操作,每帧回收不用的引用对象应该是在这里触发的,我们在内存应用的章节再回过头来讨论这块。
    以下看drawScene的代码

    void Director::drawScene(){    
    
    // 计算帧之间的时间间隔,以下依据这个时间间隔来推断是否应该进行某某操作    
    calculateDeltaTime();        
    
    // skip one flame when _deltaTime equal to zero.    
    if(_deltaTime < FLT_EPSILON) {return;}    
    if(_openGLView){_openGLView->pollInputEvents();}    
    
    //Director没有暂停的情况下,更新定时器。分发 update后的消息    
    if(!_paused){ 
    _scheduler->update(_deltaTime);
    _eventDispatcher->dispatchEvent(_eventAfterUpdate);}  
      
    // opengl清理
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    
    
    /*设置下个场景*/    
    if (_nextScene){
    setNextScene();}    
    
    kmGLPushMatrix();    
    
    // global identity matrix is needed... come on kazmath!    
    kmMat4 identity;    
    kmMat4Identity(&identity);  
      
    // 渲染场景    
    if (_runningScene)    
    {_runningScene->visit(_renderer, identity, false);
    
    // 分发场景渲染后的消息         
    _eventDispatcher->dispatchEvent(_eventAfterVisit);}    
    
    // 渲染notifications 结点,这个结点有什么用如今还看不太清楚,后面章节我们一定会摸清楚的    
    
    if (_notificationNode){_notificationNode->visit(_renderer, identity, false);    }    
    if (_displayStats){showStats();}    // 渲染 FPS等帧频显示
    _renderer->render();     // 调用了渲染器的render方法。详细我们在分析Render类的时候再回过来看都干了些什么   
     
    _eventDispatcher->dispatchEvent(_eventAfterDraw); 
       
    kmGLPopMatrix();    
    _totalFrames++;    
    
    // swap buffers    
    if (_openGLView){_openGLView->swapBuffers();}    
    if (_displayStats){calculateMPF();}
    
    }

    到如今,我们完整的分析了Director类,了解了这个大管家都管理了哪些对象。

    以下我们做个总结。Director主要管理了场景,四个事件的分发,渲染, Opengl对象等。它主要是以场景为单位来控制游戏的逻辑帧,通过场景的切换来实现游戏中不同界面的变化。mainloop这个函数调用了drawscene来实现每一帧的逻辑,主要是渲染逻辑。

  • 相关阅读:
    c# 方法重载
    c# propertyGrid下拉选项
    c# 枚举类型
    c# socket编程
    读书笔记之ado.net entity framework
    c# delegate的invoke和bejinInvoke的区别
    C# 读书笔记之类与结构体
    c#笔记之启动新线程
    c# listview的使用
    visual studio2013 改变匹配括号的颜色
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6905395.html
Copyright © 2020-2023  润新知