cocos2d-x 3.2 中的重要类总结

来源:互联网 发布:erp软件推荐 编辑:程序博客网 时间:2024/06/06 13:56

~~~~我的生活,我的点点滴滴!!


基于cocos2dx 3.2版


cocos2d-x引擎中几个主要类做了简单的介绍:Director, Application, Node, Renderer, EventDispatcher, Scheduler等对于这些类简短的介绍,在心里有个大概。



1、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;}



2、Director


主要函数预览:

//openGL Matrix Operate在3.0里面没有,尼吗我用的是3.0蛋疼无比    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 Scenevoid 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();                             //把上面渲染的结果显示到屏幕    }    ...}





3、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);}


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函数主要实现了[添加一个QuadCommand到Render中去]的功能。

再看看Label的绘制函数:

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怎么构造和执行的。


4、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]);        ...    }    ...}

5、Schelduler


Schelduler是cocos2d-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的其它大部分方法, 要么

是它的衍生, 为了减少调用参数; 要么是对定时操作的控制, 比如暂停, 恢复, 移除等。



6、EventDispatcher


EventDispatcher,EventListener,Event之间的关系如下:


    1、EventDispatcher: 事件分发器, 相当于所有事件的中控中心. 管理着EventListener,当一个Event到来的时候决定CallBack的调用顺序。

    2、Event ( EventTouch, EventKeyboard 等), 具体的事件数据等。

    3、EventListener ( EventListenerTouch, EventListenerKeyboard 等 ): 建立了Event到CallBack的映射关系, EventDispatcher 根据这种映射关系调用对应的 CallBack。


6.1、Event


Event有以下几种类型:

    enum class Type    {        TOUCH,        KEYBOARD,        ACCELERATION,        MOUSE,        FOCUS,        CUSTOM    };

Event最重要的属性就是type, 标识了它是那种类型的事件, 也决定了由哪个EventListner来处理它。


6.2、EventListener


EventListner有以下几种类型:

    enum class Type    {        UNKNOWN,        TOUCH_ONE_BY_ONE,        TOUCH_ALL_AT_ONCE,        KEYBOARD,        MOUSE,        ACCELERATION,        FOCUS,        CUSTOM    };

除了UNKNOWN, 跟Event::Type相比,Event::Type::TOUCH会同时被两种类型的EventListener处理: TOUCH_ONE_BY_ONE和TOUCH_ALL_AT_ONCE。这两种EventListener分别

处理单点触摸事件和多点触摸事件。多说几句: 假如一个TouchEvent事件中有多个触摸点, 那么类型为EventListener::Type::TOUCH_ONE_BY_ONE的EventListener会把

这个事件分解成若干个单点触摸事件来处理。而类型为EventListener::Type::TOUCH_ALL_AT_ONCE 的 EventListener 就是来处理多点触摸的, 会一次处理它,其它几

种类型都是一一对应的, 即一种Event::Type的Event会被对应类型的EventListener接受。



6.3、存放 EventListener 的地方


在EventDispatcher中, 它把以上7种 EventListener::Type 类型的 EventListner 放到7个队列中. 也就是在这样一个字段中:

std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;

   1、EventListener::ListenerID : 每一种EventListener::Type有唯一的 EventListener::ListenerID. 其实通过这段代码typedef std::string ListenerID; 可

      知: EventListener::ListenerID 就是简单 string, 就是一个名称而已。

   2、EventListenerVector: 顾名思义, 就是一个 EventListener 的向量容器. 相对于普通的向量容器, 它增加了priority管理功能。


6.4、EventListener的fixedPriority


简单来说, 每个 EventListener 有自己的 fixedPriority 属性, 它是一个整数。


6.5、EventListener的遍历顺序


EventDispatcher 在抛发事件的时候, 会先处理 Event 的时候, 会优先遍历 fixedPriority 低的 EventListener, 调用它的 CallBack在某些条件下一个 Event 被一个 

EventListener 处理之后, 会停止遍历其它的 EventListener。反映到实战中就是: 你监听了某种事件, 这种事件也出发了, 但是对应的回调函数并没有被调用, 也就是

被优先级更高的 EventListener 截获了。

如果 fixedPriority 一样呢? 按照什么顺序?

    1、fixedPriority 为0, 这个值是专门为 Scene Object 预留的。即默认情况下, 绝大多数继承自 Node 的对象添加的普通事件监听器,其 fixedPriority 都为0。

       时, Node 的 globalZOrder 决定了优先级, 值越大, 越先被遍历到, 即在显示层中层级越高, 越先接受事件,这在ui响应逻辑中也是合理的。

    2、fixedPriority 不为0, 那就按添加顺序。


6.6、Event在什么条件下会被优先级更高的EventListener截获?


    1、对于 EventListenerTouchOneByOne, 它有一个字段: _needSwallow, 当它为 true 的时候, 如果它接受了某个 Event, 优先级更低的 EventListener 就接受不到了。

       可以用 EventListenerTouchOneByOne::setSwallowTouches(bool needSwallow) 来改变它。

    2、对于其它类型的 EventLIstener, 只有在显示调用了 Event::stopPropagation() 的时候, 才会中断遍历。


6.7、EventDispatcher::dispatchEvent()


下面我们看看EventDispatcher最核心的函数: 

   void EventDispatcher::dispatchEvent(Event* event);

当有响应的事件到来的时候, 都会调用这个函数来通知监听了此事件的对象。

其实上面的介绍, 已经把这个函数里绝大部分逻辑都描述了,这里做一个最后的总结。

事件抛发的简要流程如下:

    1、检查 _listenerMap 中所有的 EventListnerVector, 如果哪个容器的 EventListener 优先级顺序需要更新, 则重新排序。

    2、对于类型为 Event::Type::TOUCH 的事件, 则按照 EventListener 的遍历顺序遍历所有的 EventListener。只有接受了 EventTouch::EventCode::BEGAN 事件的 EventListener, 

       才会收到其他类型的 EventTouch 事件。

    3、对于其他类型的事件, 也按照EventListener的遍历顺序的顺序遍历对应的EventListener。


6.8、总结


Eventdispatcher 中的其它函数, 主要功能都是 添加EventListener, 删除EventListener等, 不做详细介绍。

总的来说, Eventdispatcher 是一个中转器:
    1、事件的产生模块儿, 只关心自己构造正确的 Event, 调用 EventDispatcher::dispatchEvent(Event* event) 交给 EventDispatcher。

    2、需要监听事件的模块儿, 只需调用 EventDispatcher::addEventListener(EventListener* listener) (或者它的其它变种)来注册自己作为监听者。

    3、EventDispatcher 的作用是: 

       3.1、把特定类型的 Event 送给对应类型的 EventListener。

       3.2、对于同一种 Event, 规定了事件送达的优先级。


0 0
原创粉丝点击