码迷,mamicode.com
首页 > 其他好文 > 详细

[cocos2d-x]深入--几个代表性的类

时间:2014-07-22 22:44:53      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   使用   

[cocos2d-x]深入--几个代表性的类

摘要: 此文对cocos2d-x引擎中最具代表性,最能体现框架结构的几个类做了简单的介绍, 包括Director,Application, Renderer, EventDispatcher, Scheduler. 对于这些类, 也只对关系主要流程的方法做了介绍, 略过了容错代码和其它细节. 主要目的是让大家快速的对cocos2d-x引擎有一个全面笼统的认识, 也方便快速定位问题.



GLView

cocos2d-xopenGL的封装. 不同平台下, openGL有一些差别.

openGL

一段简单的例子

以下内容引用自Introduction to OpenGL. 需要更具体的介绍也可参考这个链接.

#include <whateverYouNeed.h>
main() {
   InitializeAWindowPlease();

   glClearColor (0.0, 0.0, 0.0, 0.0);
   glClear (GL_COLOR_BUFFER_BIT);

   glColor3f (1.0, 1.0, 1.0);
   glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
   glBegin(GL_POLYGON);
      glVertex3f (0.25, 0.25, 0.0);
      glVertex3f (0.75, 0.25, 0.0);
      glVertex3f (0.75, 0.75, 0.0);
      glVertex3f (0.25, 0.75, 0.0);
   glEnd();
   glFlush();

   UpdateTheWindowAndCheckForEvents();
}

OpenGL Command Syntax

  • OpenGL commands use the prefix gl and initial capital letters for each word making up the command name
  • some seemingly extraneous letters appended to some command names (for example, the 3f in glColor3f() and glVertex3f())

OpenGL as a State Machine

OpenGL is a state machine. You put it into various states (or modes) that then remain in effect until you change them.

Application

主要方法:

virtual const char * getCurrentLanguage();
virtual Platform getTargetPlatform();
virtual void setAnimationInterval(double interval);
int run();//启动主循环

run()函数

int Application::run()
{

    ...

    while(!glview->windowShouldClose())
    {
        QueryPerformanceCounter(&nNow);
        if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)
        {
            nLast.QuadPart = nNow.QuadPart;

            director->mainLoop();       //Director进行这一帧的渲染
            glview->pollEvents();       // This function processes only those events that have already been received and then returns immediately.
        }
        else
        {
            Sleep(0);
        }
    }

    ...

    return true;
}

Director

主要函数预览

//openGL Matrix Operate
    void pushMatrix(MATRIX_STACK_TYPE type);
    void popMatrix(MATRIX_STACK_TYPE type);
    void loadIdentityMatrix(MATRIX_STACK_TYPE type);
    void loadMatrix(MATRIX_STACK_TYPE type, const Mat4& mat);
    void multiplyMatrix(MATRIX_STACK_TYPE type, const Mat4& mat);
    Mat4 getMatrix(MATRIX_STACK_TYPE type);
    void resetMatrixStack();

//View Data
    inline double getAnimationInterval();
    inline bool isDisplayStats();
    inline GLView* getOpenGLView();
    inline Projection getProjection();
    Size getVisibleSize() const;

    Vec2 getVisibleOrigin() const;
    Vec2 convertToGL(const Vec2& point);
    Vec2 convertToUI(const Vec2& point);
    float getZEye() const;

// Scene 场景管理
    inline Scene* getRunningScene();
    void runWithScene(Scene *scene);
    void pushScene(Scene *scene);


// 控制绘制的暂停和恢复
    void end();
    void pause();
    void resume();

//绘制图形(界面展示最重要的函数)
    void drawScene();

//Getter and Setter
    Scheduler* getScheduler() const { return _scheduler; }
    void setScheduler(Scheduler* scheduler);

    ActionManager* getActionManager() const { return _actionManager; }
    void setActionManager(ActionManager* actionManager);

    EventDispatcher* getEventDispatcher() const { return _eventDispatcher; }
    void setEventDispatcher(EventDispatcher* dispatcher);

    Renderer* getRenderer() const { return _renderer; }

drawScene(): 主要绘制函数

// Draw the Scene
void Director::drawScene()
{
    ...

    if (! _paused)
    {
        _scheduler->update(_deltaTime);                         //Scheduler 定时器 更新
        _eventDispatcher->dispatchEvent(_eventAfterUpdate);     //Dispatcher 抛发事件.
    }

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         //glClear

    if (_nextScene)                                             //取得下一个将要显示的Scene.
    {
        setNextScene();
    }

    pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);      //将上一次绘制的Context放到堆栈

    // draw the scene
    if (_runningScene)
    {
        _runningScene->visit(_renderer, Mat4::IDENTITY, false);
        _eventDispatcher->dispatchEvent(_eventAfterVisit);
    }

    _renderer->render();                                        //渲染
    _eventDispatcher->dispatchEvent(_eventAfterDraw);

    popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);       //返回到上一次绘制时的状态.


    // swap buffers
    if (_openGLView)
    {
        _openGLView->swapBuffers();                             //把上面渲染的结果显示到屏幕
    }

    ...
}

Node::visit() 函数

预览

Node::visit() 的主要功能就是

  1. 调用所有孩子的visit函数
  2. 调用self->draw()函数
void Node::visit(Renderer* renderer, const Mat4 &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* director = Director::getInstance();
    director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);

    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
        this->draw(renderer, _modelViewTransform, flags);

        for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
            (*it)->visit(renderer, _modelViewTransform, flags);
    }
    else
    {
        this->draw(renderer, _modelViewTransform, flags);
    }

    director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}

Node::draw()

因为Node是所有可显示对象的父类, 没有任何显示内容, 所以draw函数为空.
这里我们以Sprite::draw函数为例简单介绍下draw的作用.

void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
    // Don‘t do calculate the culling if the transform was not updated
    _insideBounds = (flags & FLAGS_TRANSFORM_DIRTY) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds;

    if(_insideBounds)
    {
        _quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform);
        renderer->addCommand(&_quadCommand);
    }
}

我们看到, Sprite::draw函数主要实现了[添加一个QuadCommandRender中去]的功能.
再看看Label的绘制函数.

Label::draw

void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
    // Don‘t do calculate the culling if the transform was not updated
    _insideBounds = (flags & FLAGS_TRANSFORM_DIRTY) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds;

    if(_insideBounds) {
        _customCommand.init(_globalZOrder);
        _customCommand.func = CC_CALLBACK_0(Label::onDraw, this, transform, flags);
        renderer->addCommand(&_customCommand);
    }
}

其实, 跟Sprite::draw也差不多. 关键在于这个RenderCommand怎么构造和执行的.

Renderer 渲染器

主要函数预览

    void initGLView();

    /** Adds a `RenderComamnd` into the renderer */
    void addCommand(RenderCommand* command);

    /** Adds a `RenderComamnd` into the renderer specifying a particular render queue ID */
    void addCommand(RenderCommand* command, int renderQueue);

    /** Pushes a group into the render queue */
    void pushGroup(int renderQueueID);

    /** Pops a group from the render queue */
    void popGroup();

    /** Creates a render queue and returns its Id */
    int createRenderQueue();

    /** Renders into the GLView all the queued `RenderCommand` objects */
    void render();

可见它主要由两个功能:

  1. ReanderCommand进行排序和分类管理
  2. 进行渲染:render()

渲染函数Renderer::render()

void Renderer::render()
{
   ...

    if (_glViewAssigned)
    {
       ...
        //排列渲染队列
        for (auto &renderqueue : _renderGroups)
        {
            renderqueue.sort();
        } 
        //进行渲染
        visitRenderQueue(_renderGroups[0]);
        ...
    }
    ...
}

Renderer::visitRenderQueue

按照顺序执行所有的 RenderCommand

void Renderer::visitRenderQueue(const RenderQueue& queue)
{
    ssize_t size = queue.size();

    for (ssize_t index = 0; index < size; ++index)
    {
        auto command = queue[index];
        auto commandType = command->getType();
        if(RenderCommand::Type::QUAD_COMMAND == commandType)
        {
            auto cmd = static_cast<QuadCommand*>(command);
            //Batch quads
            if(_numQuads + cmd->getQuadCount() > VBO_SIZE)
            {
                drawBatchedQuads();
            }

            _batchedQuadCommands.push_back(cmd);

            memcpy(_quads + _numQuads, cmd->getQuads(), sizeof(V3F_C4B_T2F_Quad) * cmd->getQuadCount());
            convertToWorldCoordinates(_quads + _numQuads, cmd->getQuadCount(), cmd->getModelView());

            _numQuads += cmd->getQuadCount();

        }
        else if(RenderCommand::Type::GROUP_COMMAND == commandType)
        {
            flush();
            int renderQueueID = ((GroupCommand*) command)->getRenderQueueID();
            visitRenderQueue(_renderGroups[renderQueueID]);
        }
        else if(RenderCommand::Type::CUSTOM_COMMAND == commandType)
        {
            ...
        }
        ...
    }
}

openGL VAO, VBO 介绍.

GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形
OpenGL 4.0 VAO VBO 理解

Schelduler介绍

Scheldulercocos2d-x中实现延迟调用,定时调用时最重要的功能. 类似于其他语言中的Timer
他最核心的函数就是:

void schedule(const ccSchedulerFunc& callback, void *target, float interval, unsigned int repeat, float delay, bool paused, const std::string& key);

用来启动一个定时操作: 在延迟delay时间后, 每隔repeat时间, 调用一次callback. target用来标记这个操作属于谁, 方便管理, 比如在析构的时候调用void unschedule(void *target)即可移除当前对象的所有定时操作.

Schelduler的其它大部分方法, 要么是它的衍生, 为了减少调用参数; 要么是对定时操作的控制, 比如暂停, 恢复, 移除等. 如果只对想对框架的各个模块有大概的了解, 可以不做深入.

EventDispatcher

(后续添加)

Written with StackEdit.

[cocos2d-x]深入--几个代表性的类,布布扣,bubuko.com

[cocos2d-x]深入--几个代表性的类

标签:des   style   blog   http   color   使用   

原文地址:http://www.cnblogs.com/jhzhu/p/3859964.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!