CCDirector导演类

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

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

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

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

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

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


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

先看返回单例对象的方法post

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

注意,返回的是DisplayLinkDirector这个类。并且在建立完 DisplayLinkDirector对象以后调用了init方法,看一下init方法。动画

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

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的实体类。
spa

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的代码
code

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来实现每一帧的逻辑,主要是渲染逻辑。

相关文章
相关标签/搜索