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

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



    • GLView

      • openGL

        • 一段简单的例子
        • OpenGL Command Syntax
        • OpenGL as a State Machine
    • Application
      • 主要方法:
      • run()函数
    • Director
      • 主要函数预览
      • drawScene(): 主要绘制函数
    • Node::visit() 函数
      • 预览
      • Node::draw()
      • Label::draw
    • Renderer 渲染器
      • 主要函数预览
      • 渲染函数Renderer::render()
      • Renderer::visitRenderQueue
      • openGL VAO, VBO 介绍.
    • Schelduler介绍
    • EventDispatcher

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]深入--几个代表性的类

时间: 2024-10-18 10:02:23

[cocos2d-x]深入--几个代表性的类的相关文章

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

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

Cocos2d 3.0继承自Sprite的类在addChild后出现故障

当继承自Sprite的类被addChild到其它的Node里后出现例如以下图问题,说明没有调用父类Sprite::init()的方法,由于父类Sprite里的_textureAtlas须要初始化为null,在继承自Sprite的子类里的构造函数或init方法里加入Sprite::init()就能够了.

[cocos2dx笔记013]一个使用CCRenderTexture创建动态纹理显示数字的类

用CCLabelTTF显示的数字不好看.于是就想到用图片来代理.眼下网上的实现都是把每一个数字做一个CCSprite组合的方式. 可是我想.动态生成纹理的方式.没有就仅仅好自己手动写一个. 头文件 #ifndef _X_NUMBER_H_ #define _X_NUMBER_H_ #include <cocos2d.h> #include <xtype.h> namespace cocos2d { //基于图片显示的数字 /* 这个类不是用一个一个数字拼起来,而是渲染成一个独立的纹

实现单例类

单例类主要是为了防止重复的定义类实例,这样在整个程序中就只有一个类实例,cocos2d就是采用的单例模式 为了保证类实例只能产生一个,那么类构造函数就必须写成私有的,这样,在类外就不能调用构造函数构造新实例 第一种方式: //静态方法也是保证单例的条件之一 1 class Temp 2 { 3 private: 4 Temp(){} 5 private: 6 static Temp instance; 7 public: 8 static Temp getInstance() 9 { 10 re

darwin Stream Server源码分析

摘要 ?所谓的流式媒体简单的讲就是指人们通过网络实时的收看多媒体信息:如音频流.视频流等.与流式媒体对应的传统工作方式是下载+播放模式,即用户首先下载多媒体文件,然后再在本地播放,这种方法的一个主要缺点是启动延迟较大,例如一个30分钟长的MPEG-I文件(相当于VCD质量),即使使用1.5Mbps的速率下载,也需要半个小时才能完成,这样一个漫长的等待时间实在是无法忍受.在窄带网络环境中,几乎所有基于Internet的流式媒体产品都有着类似的工作原理:首先需要开发高效的压缩编码技术,并通过一套完整

【Cocos2D-X 学习笔记】为精灵添加单点触控

由于Cocos2d-x处于新学的阶段,因此最近也无法进行系统地更新,只会选择一些典型的Demo贴上来,一来是与大家分享,而来也可以作为以后回顾时的参考. 今天介绍一下Cocos2d-x的触摸事件处理,了解Android开发的朋友们知道,Android里会用一个OnClickListener()进行事件监听,而在J2SE中也会有Event类实现专门的监听处理.在Cocos2d-x中,因为是游戏引擎,用户在玩游戏时总是要通过屏幕与游戏进行交互,可想而知触摸事件是主要处理的事件.这里主要讲一下如何为精

Cocos2d-x之引擎框架简介

|   版权声明:本文为博主原创文章,未经博主允许不得转载. 1.cocos2d-x的设计思想 cocos2d-x分为导演,场景,图层,精灵,节点: (1).导演(Director):控制整个游戏的场景的切换 auto director = Director::getInstance(); auto glview = director->getOpenGLView(); 这行代码是在appdelegata中去获得一个导演对象,这个导演是一个全局对象,使用单例的模式使整个游戏使整个游戏只存在一个导

SpriteFrameCache和SpriteBatchNode

Cocos2d中SpriteFrameCache通常用来处理plist文件,并能与SpriteBatchNode结合使用来达到批处理渲染精灵的目的. 1)精灵帧缓存类SpriteFrameCache 2)精灵帧缓存类SpriteFrameCache 用来存储精灵帧,缓存精灵帧有助于提高程序的效率. SpriteFrameCache是一个单例模式,不属于某个精灵,是所有精灵共享使用的. 3)精灵批处理节点SpriteBatchNode 当你需要渲染显示两个或两个以上相同的精灵时,如果逐个渲染精灵,

场景的切换

/** * 以下代码实现的是切换场景的目的, * 点击文本框中的字体时,切换场景,有图片 */ //1.修改bool HelloWorld::init()方法 //2.创建ImageScene方法,c++ //3.将创建的场景添加到bool HelloWorld::init()中, //4.在最开始的位置上添加#include "ImageScene.h" //5.别忘了将自己创建的方法添加到xcode的编译环境中,不然运行时异常 //6.点击项目,点击Build Phases,找到C