您的位置:首页 > 移动开发 > Cocos引擎

分析cocos2dx 3.3运行流程

2016-07-17 20:45 387 查看
<1>不管在哪个平台xode也好,windows下也好,都先进入:

cocos2d::Application *app =cocos2d::Application::getInstance();

app->run();

intApplication::run()

{

    if (applicationDidFinishLaunching()) 

    {

        [[CCDirectorCallersharedDirectorCaller]startMainLoop];

    }

    return0;

}

<2>在开始游戏循环之前,先进入,进行分辨率设置

boolAppDelegate::applicationDidFinishLaunching() {

    // initialize director

    auto director =Director::getInstance();

    auto glview = director->getOpenGLView();

    if(!glview) {

        glview = GLViewImpl::create("Cpp Empty Test");

        director->setOpenGLView(glview);

    }

    director->setOpenGLView(glview);

    // Set the design resolution

    glview->setDesignResolutionSize(designResolutionSize.width,designResolutionSize.height,ResolutionPolicy::NO_BORDER);

Size frameSize = glview->getFrameSize();

    

    vector<string> searchPath;

    // In this demo, we select resource according to the frame's height.

    // If the resource size is different from design resolution size, you need to set contentScaleFactor.

    // We use the ratio of resource's height to the height of design resolution,

    // this can make sure that the resource's height could fit for the height of design resolution.

    // if the frame's height is larger than the height of medium resource size, select large resource.

if (frameSize.height >mediumResource.size.height)

{

        searchPath.push_back(largeResource.directory);

        director->setContentScaleFactor(MIN(largeResource.size.height/designResolutionSize.height,largeResource.size.width/designResolutionSize.width));

}

    // if the frame's height is larger than the height of small resource size, select medium resource.

    elseif (frameSize.height
>smallResource.size.height)

    {

        searchPath.push_back(mediumResource.directory);

        

        director->setContentScaleFactor(MIN(mediumResource.size.height/designResolutionSize.height,mediumResource.size.width/designResolutionSize.width));

    }

    // if the frame's height is smaller than the height of medium resource size, select small resource.

else

    {

        searchPath.push_back(smallResource.directory);

        director->setContentScaleFactor(MIN(smallResource.size.height/designResolutionSize.height,smallResource.size.width/designResolutionSize.width));

    }

    

    // set searching path

    FileUtils::getInstance()->setSearchPaths(searchPath);

    // turn on display FPS

    director->setDisplayStats(true);

    // set FPS. the default value is 1.0/60 if you don't call this

    director->setAnimationInterval(1.0 /60);

    // create a scene. it's an autorelease object

    auto scene =HelloWorld::scene();

    // run

    director->runWithScene(scene);

    return true;

}

<3>资源分辨率设置过之后,每一帧调用一次函数doCaller

-(void) startMainLoop

{

        // Director::setAnimationInterval() is called, we should invalidate it first

    [selfstopMainLoop];

    

    displayLink = [NSClassFromString(@"CADisplayLink")displayLinkWithTarget:selfselector:@selector(doCaller:)];

    [displayLinksetFrameInterval:self.interval];

    [displayLinkaddToRunLoop:[NSRunLoopcurrentRunLoop]forMode:NSDefaultRunLoopMode];

}

<4>每一帧都进行mainLoop函数

-(void) doCaller: (id) sender

{

    cocos2d::Director* director =cocos2d::Director::getInstance();

    [EAGLContextsetCurrentContext: [(CCEAGLView*)director->getOpenGLView()->getEAGLView()context]];

    director->mainLoop();

}

<5>

voidDisplayLinkDirector::mainLoop()

{

    if (_purgeDirectorInNextLoop)

    {

        _purgeDirectorInNextLoop =false;

        purgeDirector();

    }

    elseif (_restartDirectorInNextLoop)

    {

        _restartDirectorInNextLoop =false;

        restartDirector();

    }

    elseif (!
_invalid)

    {

        drawScene();

     

        // release the objects

        PoolManager::getInstance()->getCurrentPool()->clear();

    }

}

<6>绘制玩每一帧都,都会被刚添加到自动管理池AutoReleasePool中的对象进行一次遍历。

void
AutoreleasePool::clear()

{

#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG >
0)

    _isClearing =
true;

#endif

    std::vector<Ref*> releasings;

    releasings.swap(_managedObjectArray);

    for (const
auto &obj : releasings)

    {

        obj->release();

    }

#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG >
0)

    _isClearing =
false;

#endif

}

总结:

std::vector<Ref*> releasings;

releasings.swap(_managedObjectArray);
这行代码很有意思,将releasings和_managedObjectArray内容进行交换,交换后,_managedObjectArray就为空了,然后将releasings遍历一遍,将引用计数减去1,为0的就回收内存了。

<7>

// Draw the Scene

voidDirector::drawScene()

{

    // calculate "global" dt

    calculateDeltaTime();

    

    if (_openGLView)

    {

        _openGLView->pollEvents();

    }

    //tick before glClear: issue #533

    if (!_paused)

    {

        _scheduler->update(_deltaTime);

        _eventDispatcher->dispatchEvent(_eventAfterUpdate);

    }

    _renderer->clear();

    experimental::FrameBuffer::clearAllFBOs();

    /* to avoid flickr, nextScene MUST be here: after tick and before draw.

     * FIXME: Which bug is this one. It seems that it can't be reproduced with v0.9

     */

    if (_nextScene)

    {

        setNextScene();

    }

    pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);

    

    if (_runningScene)

    {

#if (CC_USE_PHYSICS || (CC_USE_3D_PHYSICS && CC_ENABLE_BULLET_INTEGRATION) || CC_USE_NAVMESH)

        _runningScene->stepPhysicsAndNavigation(_deltaTime);

#endif

        //clear draw stats

        _renderer->clearDrawStats();

        

        //render the scene

        _runningScene->render(_renderer);

        

        _eventDispatcher->dispatchEvent(_eventAfterVisit);

    }

    // draw the notifications node

    if (_notificationNode)

    {

        _notificationNode->visit(_renderer,Mat4::IDENTITY,0);

    }

    if (_displayStats)

    {

        showStats();

    }

    _renderer->render();

    _eventDispatcher->dispatchEvent(_eventAfterDraw);

    popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);

    _totalFrames++;

    // swap buffers

    if (_openGLView)

    {

        _openGLView->swapBuffers();

    }

    if (_displayStats)

    {

        calculateMPF();

    }

}

<8>在Scene中调用其render方法回执场景。

voidScene::render(Renderer* renderer)

{

    auto director =Director::getInstance();

    Camera* defaultCamera =nullptr;

    constauto& transform =getNodeToParentTransform();

    for (constauto& camera :getCameras())

    {

        if (!camera->isVisible())

            continue;

        

        Camera::_visitingCamera = camera;

        if (Camera::_visitingCamera->getCameraFlag()
== CameraFlag::DEFAULT)

        {

            defaultCamera = Camera::_visitingCamera;

        }

        

        director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);

        director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,Camera::_visitingCamera->getViewProjectionMatrix());

        camera->apply();

        //clear background with max depth

        camera->clearBackground();

        //visit the scene

        visit(renderer, transform,0);

#if CC_USE_NAVMESH

        if (_navMesh &&_navMeshDebugCamera
== camera)

        {

            _navMesh->debugDraw(renderer);

        }

#endif

        

        renderer->render();

        

        director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);

    }

    

#if CC_USE_3D_PHYSICS && CC_ENABLE_BULLET_INTEGRATION

    if (_physics3DWorld &&_physics3DWorld->isDebugDrawEnabled())

    {

        director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);

        director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,_physics3dDebugCamera
!=nullptr ?_physics3dDebugCamera->getViewProjectionMatrix()
: defaultCamera->getViewProjectionMatrix());

        _physics3DWorld->debugDraw(renderer);

        renderer->render();

        director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);

    }

#endif

    Camera::_visitingCamera =nullptr;

    experimental::FrameBuffer::applyDefaultFBO();

}

<9>Scene其实也是一个Node,递归绘制自身及其子节点

voidNode::visit(Renderer* renderer,constMat4
&parentTransform,uint32_t parentFlags)

{

    // quick return if not visible. children won't be drawn.

    if (!_visible)

    {

        return;

    }

    uint32_t flags =processParentFlags(parentTransform, parentFlags);

    // IMPORTANT:

    // To ease the migration to v3.0, we still support the Mat4 stack,

    // but it is deprecated and your code should not rely on it

    _director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);

    _director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW,_modelViewTransform);

    

    bool visibleByCamera =isVisitableByVisitingCamera();

    int i =0;

    if(!_children.empty())

    {

        sortAllChildren();

        // draw children zOrder < 0

        for( ; i <_children.size(); i++ )

        {

            auto node =_children.at(i);

            if (node && node->_localZOrder <0)

                node->visit(renderer,_modelViewTransform, flags);

            else

                break;

        }

        // self draw

        if (visibleByCamera)

            this->draw(renderer,_modelViewTransform,
flags);

        for(auto it=_children.cbegin()+i;
it != _children.cend(); ++it)

            (*it)->visit(renderer,_modelViewTransform, flags);

    }

    elseif (visibleByCamera)

    {

        this->draw(renderer,_modelViewTransform,
flags);

    }

    _director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);

    

    // FIX ME: Why need to set _orderOfArrival to 0??

    // Please refer tohttps://github.com/cocos2d/cocos2d-x/pull/6920

    // reset for next frame

    // _orderOfArrival = 0;

}
首先绘制_localZOrder < 0的,其次在for(auto it=_children.cbegin()+i;
it != _children.cend(); ++it)绘制 >=0 的

<10>

voidNode::sortAllChildren()

{

    if (_reorderChildDirty)

    {

        std::sort(std::begin(_children),std::end(_children),nodeComparisonLess);

        _reorderChildDirty =false;

    }

}

bool nodeComparisonLess(Node* n1,Node* n2)

{

    return( n1->getLocalZOrder() < n2->getLocalZOrder()
||

           ( n1->getLocalZOrder() == n2->getLocalZOrder() && n1->getOrderOfArrival()
< n2->getOrderOfArrival() )

           );

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: