对CCImage的绘制是通过CCTexture2D来实现的(OPENGL es)通过纹理绘制到某个面。

(本文中所提到的方法在cocos2d2.0中部分有调整,请应用时候具体察看源码)
1. 首先来了解一下跟精灵相关的几个类:
(1) CCTexture2D
可以把它看成一个纹理,它是cocos2d-x渲染图形的重要参数,用来贴图,因为cocos2d-x使用opengl es绘制2d图形的,它的尺寸是2的n次方。一般通过以下方式获得:
CCTexture2D* cache = CCTextureCache::sharedTextureCache()->addImage("hero.png"); 
(2) CCSprite
这个就是精灵类,是CCNode的子类,可以直接添加到CCLayer或CCScene,它的内部封装了CCTexture2D(纹理),可以通过下面几种方式初始化精灵对象。
static CCSprite* spriteWithTexture(CCTexture2D pTexture); //CCTexture2D表示精灵包含的图片,范围是整张图片 
static CCSprite
 spriteWithTexture(CCTexture2D pTexture, const CCRect& rect); //CCRect表示图片的指定范围,即从图片的指定矩形区域
static CCSprite
 spriteWithSpriteFrame(CCSpriteFrame pSpriteFrame); ////CCSpriteFrame表示精灵的某一帧,内部封装了CCTexture2D和CCRect,CCRect表示图片的指定范围,即从图片的指定矩形区域裁剪 
static CCSprite
 spriteWithSpriteFrameName(const char pszSpriteFrameName);

static CCSprite spriteWithFile(const char pszFileName); 
static CCSprite
 spriteWithFile(const char pszFileName, const CCRect& rect); 
static CCSprite
 spriteWithBatchNode(CCSpriteBatchNode batchNode, const CCRect& rect); 
下面是两种比较常用的初始化精灵的方式:
CCSprite
 sprite = CCSprite::spriteWithFile("hero.png"); 
/** 或者 **/ 
CCTexture2D* cache = CCTextureCache::sharedTextureCache()->addImage("hero.png"); 
CCSprite* sprite = CCSprite::spriteWithTexture(cache); 
(3) CCTextureCache
它相当于CCTexture2D的容器,是内存池,用来缓存CCTexture2D对象的,它内部有一个字典CCMutableDictionary m_pTextures,key为图片的名称,值是CCTexture2D。当调用它的addImage函数添加图片时,会先根据图片名称去内存中查找是否已存在,是则直接取出返回。下面是addImage部分源码:
[cpp] 
CCTexture2D * CCTextureCache::addImage(const char * path) 

CCTexture2D * texture = NULL; 
std::string pathKey = path; 
CCFileUtils::ccRemoveHDSuffixFromFile(pathKey);

pathKey = CCFileUtils::fullPathFromRelativePath(pathKey.c_str()); 
texture = m_pTextures->objectForKey(pathKey);

std::string fullpath = pathKey; // (CCFileUtils::fullPathFromRelativePath(path)); 
if( ! texture ) 

/** .... */ 
}

return texture;


如果需要一次加载多张图片的时候,可以先把图片加载到CCTextureCache中,这样使用图片的时候速度就会很快了。

(4) CCSpriteBatchNode

它是批处理绘制精灵,主要是用来提高精灵的绘制效率的,需要绘制的精灵数量越多,效果越明显。因为cocos2d-x采用opengl es绘制图片的,opengl es绘制每个精灵都会执行:open-draw-close流程。而CCSpriteBatchNode是把多个精灵放到一个纹理上,绘制的时候直接统一绘制该texture,不需要单独绘制子节点,这样opengl es绘制的时候变成了:open-draw()-draw()…-draw()-close(),节省了多次open-close的时间。CCSpriteBatchNode内部封装了一个CCTextureAtlas(纹理图集,它内部封装了一个CCTexture2D)和一个CCArray(用来存储CCSpriteBatchNode的子节点:单个精灵)。注意:因为绘制的时候只open-close一次,所以CCSpriteBatchNode对象的所有子节点都必须和它是用同一个texture(同一张图片):

在addChild的时候会检查子节点纹理的名称跟CCSpriteBatchNode的是不是一样,如果不一样就会出错,源码:

[cpp] Child(CCNode *child, int zOrder, int tag) 

/** ... */ 
// check CCSprite is using the same texture id 
CCAssert(pSprite->getTexture()->getName() == m_pobTextureAtlas->getTexture()->getName(), "");

/** ... */ 
}

下面是使用CCSpriteBatchNode的使用代码示例:
[cpp] 
CCSpriteBatchNode* BatchNode1 = CCSpriteBatchNode::batchNodeWithFile("Images/grossinidanceatlas.png", 50); 
addChild(BatchNode1, 0, kTagSpriteBatchNode);

CCSpriteBatchNode* BatchNode = (CCSpriteBatchNode*) getChildByTag( kTagSpriteBatchNode ); 
int idx = CCRANDOM_0_1() * 1400 / 100; 
int x = (idx%5) * 85; 
int y = (idx/5) * 121;

CCSprite* sprite = CCSprite::spriteWithTexture(BatchNode->getTexture(), CCRectMake(x,y,85,121)); 
BatchNode->addChild(sprite);

sprite->setPosition( ccp( p.x, p.y) ); 
(5) CCSpriteFrameCache
它是管理CCSpriteFrame的内存池,跟CCTextureCache功能一样,不过跟CCTextureCache不同的是,如果内存池中不存在要查找的帧,它会提示找不到,而不会去本地加载图片。它的内部封装了一个字典:CCDictionary *m_pSpriteFrames,key为帧的名称。CCSpriteFrameCache一般用来处理plist文件(这个文件指定了每个独立的精灵在这张“大图”里面的位置和大小),该文件对应一张包含多个精灵的大图,plist文件可以使用TexturePacker制作。

下面是使用CCSpriteFrameCache的使用代码示例:

[cpp] 
CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache(); 
cache->addSpriteFramesWithFile("animations/grossini.plist", "animations/grossini.png");
mpSprite1 = CCSprite::spriteWithSpriteFrameName("grossinidance01.png"); 
m
pSprite1->setPosition( ccp( s.width/2-80, s.height/2) ); 
只要plist文件跟对应的png图片在同一目录下,且名字相同,则addSpriteFramesWithFile(“animations/grossini.plist”, “animations/grossini.png”)可以改成addSpriteFramesWithFile(“animations/grossini.plist”);

    1. CCSpriteBatchNode和CCSpriteFrameCache结合使用
      必须保证CCSpriteFrameCache和CCSpriteBatchNode加载的是同一纹理贴图。

[cpp] 
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("animations/ghosts.plist", "animations/ghosts.png"); 
CCSpriteBatchNode *aParent = CCSpriteBatchNode::batchNodeWithFile("animations/ghosts.png"); 
addChild(aParent, 0, kTagSprite1);

CCSprite *pFather = CCSprite::spriteWithSpriteFrameName("father.gif"); 
pFather->setPosition(ccp( s.width/2, s.height/2)); 
aParent->addChild(pFather, 0, kTagSprite2);

//////////////////////////////////////////////////////////////////////

voidCCTextureCache的异步加载

voidCCTextureCache::addImageAsync(constchar *path, CCObject *target, SEL_CallFuncO selector)

{

CCAssert(path != NULL, "TextureCache: fileimage MUST not be NULL");

CCTexture2D *texture = NULL;

std::string pathKey = path;

CCFileUtils::ccRemoveHDSuffixFromFile(pathKey);

pathKey = CCFileUtils::fullPathFromRelativePath(pathKey.c_str());

texture = m_pTextures->objectForKey(pathKey); //根据pathkey查看是否纹理已经加载过,如果已经有了,则不重复加载

std::string fullpath = pathKey;

if (texture != NULL)

{

if (target && selector)

{

(target->*selector)(texture);

}

return;

}

if (target)

{

target->retain();

}

// lazy init

static bool firstRun = true;

if (firstRun)

{

s_pAsyncStructQueue = new queue<AsyncStruct*>();

s_pImageQueue = new queue<ImageInfo*>();

pthread_mutex_init(&s_asyncStructQueueMutex, NULL);

seminit(&ssem, 0, 0);

pthreadmutexinit(&s_ImageInfoMutex, NULL);

pthreadcreate(&sloadingThread, NULL, loadImage, NULL); //创建新的线程,用于后台加载图片

//创建调度队列,用来根据已加载的图片进行纹理转换

CCScheduler::sharedScheduler()->scheduleSelector(schedule_selector(CCTextureCache::addImageAsyncCallBack), this, 0, false);

need_quit = false;

firstRun = false;

}

// generate async struct

AsyncStruct *data = new AsyncStruct();

data->filename = fullpath.c_str();

data->target = target;

data->selector = selector;

// add async struct into queue

pthreadmutexlock(&s_asyncStructQueueMutex);

s_pAsyncStructQueue->push(data); //将需要加载的图片放入队列中

pthreadmutexunlock(&s_asyncStructQueueMutex);

sempost(&ssem);

}

从上述代码分析可以看出其过程:

1.创建线程,用于后台加载

    1. 将对于需要加载的图片放入队列中

    1. callback函数设定,用于将加载完成的图片转为纹理,等待使用其调用是由CCTimer::update调用的。

    1. addImageAsyncCallBack函数在处理完纹理转换,还会调用addImageAsync传入的SEL_CallFuncO selector,实现用户加载图片纹理之后的具体处理。

使用例子:

CCTextureCache::sharedTextureCache()->addImageAsync("Images/blocks.png", this,callfuncO_selector(TextureCacheTest::loadingCallBack));

loadingCallBack函数就是使用异步加载完之后的用户可以自处理结果,比如初始化一个sprite,用这个纹理贴出来。

或创建动画。

//////////////////////////////////////////////////////////////////////

红孩儿

深入分析Cocos2d-x 2.0中的“纹理”一文对CCTexture2D和CCTexturePVR,CCTextureCache的Api做了说明,推荐大家阅读
http://blog.csdn.net/honghaier/article/details/8068895

深入分析Cocos2d-x 2.0中的“纹理”的更多相关文章

  1. 如何在Cocos2D 1.0 中掩饰一个精灵(六)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 掩饰一个精灵:实现代码 打开HelloWorldLayer.m并 ...

  2. 如何在Cocos2D 1.0 中掩饰一个精灵(五)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 掩饰和CCRenderTexture CCRenderTextu ...

  3. Cocos2D中的纹理(textures)的解释

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

  4. Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(一)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 首先说一下为什么要转换,这是为了后面的A*寻路算法做准备.由于在 ...

  5. 如何在Cocos2D 1.0 中掩饰一个精灵(一)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 原帖来自Ray Wunderlich写的精彩的文章 How To ...

  6. 基于Cocos2d-x学习OpenGL ES 2.0之多纹理

    没想到原文出了那么多错别字,实在对不起观众了.介绍opengl es 2.0的不多.相信介绍基于Cocos2d-x学习OpenGL ES 2.0之多纹理的,我是独此一家吧.~~ 子龙山人出了一个系列: ...

  7. 【cocos2d-js官方文档】二十五、Cocos2d-JS v3.0中的单例对象

    为何将单例模式移除 在Cocos2d-JS v3.0之前.全部API差点儿都是从Cocos2d-x中移植过来的,这是Cocos2d生态圈统一性的重要一环.可惜的是,这样的统一性也在非常大程度上限制了C ...

  8. OpenGL ES 3.0之Texturing纹理详解(二)

    Texture Filtering and Mipmapping 纹理过滤与多级纹理 前面我们已经讲了单个2D图像的2D纹理的介绍,这篇文章主要讲解多级纹理.纹理坐标是用于生成一个2D索引,当放大和缩 ...

  9. [译] C# 5.0 中的 Async 和 Await (整理中...)

    C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...

随机推荐

  1. ecshop的数据库getRow、getAll、getOne区别

    ECShop没有使用一些开源的数据库操作类,比如adodb或者PEAR,而是封装了自己的实现.这样做的好处是实现非常轻量,大大减小了分发包的文件大小.另外,当网站需要做memcached缓存时,也可以 ...

  2. laravel 数据库查询的一些函数意义(未完)

    ->all() 查询数据库中的全部信息,一对象形式返回 $rows=UserModel::all(); ->get() 查询的执行函数,->toArray()将查询的是数据集转换成数 ...

  3. C语言 · 约数个数

    算法提高 约数个数   时间限制:1.0s   内存限制:512.0MB      输入一个正整数N,输出其约数的个数. 样例输入 12 样例输出 6 样例说明 12的约数包括:1,2,3,4,6,1 ...

  4. 决Ubuntu使用`make menuconfig`配置Linux 内核时,出现缺少'ncurses-devel'库支持。

    *** Unable to find the ncurses libraries or the *** required header files. *** 'make menuconfig' req ...

  5. DDR2基础

    一. DDR2介绍 DDR2由JEDEC(电子设备工程联合委员会)开发的新生代内存技术标准.该标准定义了DDR2封装.寻址及操作.电气等所有特性. DDR相关技术对比 DDR DDR2 DDR3 电压 ...

  6. How to activate maven profile inside eclipse

    How to activate maven profile inside eclipse Normally maven is use for project dependency management ...

  7. 树莓派安装centos 7系统

    1,格式化 https://www.sdcard.org/downloads/formatter_4/eula_windows/ 2,烧录,Win32DiskImager https://source ...

  8. 常用gitignore模板

    作用是让临时文件和中间文件都不提交到代码库中 工程相关的.gitignore 放在根目录 常用 的有: Android.gitignore C++.gitignore C.gitignore CMak ...

  9. NPOI导入Excel日期格式的处理 - 附类型格式匹配表

    传统操作Excel方法在部署的时候遇到很多问题,如目标主机需要安装Excel.64位电脑不支持.需要安装相关驱动程序等.所以我们一般会使用开源的NPOI来替代传统的Excel操作方法,NPOI的优点是 ...

  10. STL的map容器将第3个模板参数设为less_equal或greater_equal会怎样?

    最近都在学Linux系统编程,用C就足矣,有段时间没碰C++了,于是实现些算法练手. 实现多项式乘法的时候发现有几项没有合并同类项,最终调试到这一步时发现了问题. res是map类型,用find查找k ...