cocos2dx v3.0 主循环

<pre name="code" class="cpp">int Application::run()
{
    // Initialize instance and cocos2d.
    if (! applicationDidFinishLaunching())
    {
        return 0;
    }

    long lastTime = 0L;
    long curTime = 0L;

    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();

    // Retain glview to avoid glview being released in the while loop
    glview->retain();

    while (!glview->windowShouldClose())
    {
        lastTime = getCurrentMillSecond();

        //1? director循环</span>
        director->mainLoop();
        //2?  这里的glview就是AppDelegate.cpp中GLView::create得到、并使用Director::setOpenGLView设置的。</span>
        //在许多平台下没这函数。。</span>
        glview->pollEvents();

        //sleep, 使得达到指定帧率。 帧率是由cpu及所需的运算量决定。</span>
        curTime = getCurrentMillSecond();
        if (curTime - lastTime < _animationInterval)
        {
            usleep((_animationInterval - curTime + lastTime)*1000);
        }
    }
    /* Only work on Desktop
    *  Director::mainLoop is really one frame logic
    *  when we want to close the window, we should call Director::end();
    *  then call Director::mainLoop to do release of internal resources
    */
    if (glview->isOpenGLReady())
    {
        director->end();
        director->mainLoop();
        director = nullptr;
    }
    glview->release();
    return -1;
}


void DisplayLinkDirector::mainLoop()
{
    //调用Director::end时才为true。</span>
    if (_purgeDirectorInNextLoop)
    {
        _purgeDirectorInNextLoop = false;
        purgeDirector();
    }
    else if (! _invalid)
    {//_invalid. 初始值为false。 当StartAnimation时为false, StopAnimation时为true。</span>
        //3 ....</span>
        drawScene();
     
        // release the objects</span>
        //对当前AutoReleasePool中所有object调用一次release</span>
        PoolManager::getInstance()->getCurrentPool()->clear();
    }
}


void Director::drawScene()
{
    // calculate "global" dt</span>
    //计算_deltaTime。 也就是本次drawScene与上次调用drawScene的时间差。</span>
    calculateDeltaTime();
    
    // skip one flame when _deltaTime equal to zero.
    if(_deltaTime < FLT_EPSILON)
    {
        return;
    }

    if (_openGLView)
    {   //在许多平台下, 该函数没有或者为空。
        _openGLView->pollInputEvents();
    }

    //tick before glClear: issue #533
    if (! _paused)//Dierctor::pause时设置该值为true; Director::resume时设置该值为false
    {
        //update的逻辑:</span>
        //对_updateNegList, _update0List, _updatePosList 三种priority的调用回调。 这三种都是使用Schedule::scheduleUpdate加入的定时器</span>
        //对_hashForTimers调用回调。 这种是使用Schedule::schedule加入的定时器。</span>
        //然后依次从<span style="font-family: Arial, Helvetica, sans-serif;">_updateNegList, _update0List, _updatePosList中删除需要删除的定时器</span></span>
        _scheduler->update(_deltaTime);
        //dispatch逻辑</span>
        //如果Event::Type::TOUCH, 找到单点触摸的listener和多点触摸的listener; 先执行单点触摸的回调, 然后执行多点触摸的回调</span>
        //否则可能为ACCELERATION/CUSTOM/KEYBOARD/MOUSE,找到对应的listener的associateNode, 执行_onEvent,如果返回_onEvent返回true、且调用了Event::stopPropagation(), 则不再向后传递事件。游戏开发之旅上说的是调用EventListener::setSwallowTouches(false)。</span>
        _eventDispatcher->dispatchEvent(_eventAfterUpdate);
    }

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /* to avoid flickr, nextScene MUST be here: after tick and before draw.
     XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
    //如果调用了replaceScene/push/pop/popToSceneStackLevel之后, _nextScene就有效。</span>
    if (_nextScene)
    {
        setNextScene();
    }

    kmGLPushMatrix();

    // global identity matrix is needed... come on kazmath!
    kmMat4 identity;
    kmMat4Identity(&identity);

    // draw the scene
    //_runingScene始终有效。 只有当刚Director::init时以及Director::purgeDirector时才会被设为NULL</span>
    if (_runningScene)
    {
        _runningScene->visit(_renderer, identity, false);
        _eventDispatcher->dispatchEvent(_eventAfterVisit);
    }

    // draw the notifications node
    //是被Director::setNotificationNode设置的Node</span>
    if (_notificationNode)
    {
        //!!!!这里是绘制。将children按zOrder排序递归绘制: 先绘制_localZOrder<0的childrenNode;然后绘制自己;再绘制剩下的childrenNode</span>
        //这里的绘制, 只是将Node的{_globalZOrder, _texture->getName(), _shaderProgram, _blendFunc,...>构造成一个QuadCommand,放入 Rendererde 的容器中</span>
        _notificationNode->visit(_renderer, identity, false);
    }

    if (_displayStats)
    {//显示统计信息。 Director::setDisplayStats(true);
        showStats();
    }

     //!!!!这里是真正的绘制。。 这里有BatchCommand之类的处理。</span>
    _renderer->render();
    _eventDispatcher->dispatchEvent(_eventAfterDraw);

    kmGLPopMatrix();

    _totalFrames++;

    // swap buffers
    if (_openGLView)
    {
        _openGLView->swapBuffers();
    }

    if (_displayStats)
    {
        calculateMPF();
    }
}



 

你可能感兴趣的:(cocos2dx v3.0 主循环)