深入分析Cocos2d-x 2.0中的“纹理”
对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");
mpSprite1->setPosition( ccp( s.width/2-80, s.height/2) );
只要plist文件跟对应的png图片在同一目录下,且名字相同,则addSpriteFramesWithFile(“animations/grossini.plist”, “animations/grossini.png”)可以改成addSpriteFramesWithFile(“animations/grossini.plist”);
- 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.创建线程,用于后台加载
将对于需要加载的图片放入队列中
callback函数设定,用于将加载完成的图片转为纹理,等待使用其调用是由CCTimer::update调用的。
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中的“纹理”的更多相关文章
- 如何在Cocos2D 1.0 中掩饰一个精灵(六)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 掩饰一个精灵:实现代码 打开HelloWorldLayer.m并 ...
- 如何在Cocos2D 1.0 中掩饰一个精灵(五)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 掩饰和CCRenderTexture CCRenderTextu ...
- Cocos2D中的纹理(textures)的解释
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(一)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 首先说一下为什么要转换,这是为了后面的A*寻路算法做准备.由于在 ...
- 如何在Cocos2D 1.0 中掩饰一个精灵(一)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 原帖来自Ray Wunderlich写的精彩的文章 How To ...
- 基于Cocos2d-x学习OpenGL ES 2.0之多纹理
没想到原文出了那么多错别字,实在对不起观众了.介绍opengl es 2.0的不多.相信介绍基于Cocos2d-x学习OpenGL ES 2.0之多纹理的,我是独此一家吧.~~ 子龙山人出了一个系列: ...
- 【cocos2d-js官方文档】二十五、Cocos2d-JS v3.0中的单例对象
为何将单例模式移除 在Cocos2d-JS v3.0之前.全部API差点儿都是从Cocos2d-x中移植过来的,这是Cocos2d生态圈统一性的重要一环.可惜的是,这样的统一性也在非常大程度上限制了C ...
- OpenGL ES 3.0之Texturing纹理详解(二)
Texture Filtering and Mipmapping 纹理过滤与多级纹理 前面我们已经讲了单个2D图像的2D纹理的介绍,这篇文章主要讲解多级纹理.纹理坐标是用于生成一个2D索引,当放大和缩 ...
- [译] C# 5.0 中的 Async 和 Await (整理中...)
C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...
随机推荐
- linux下apache服务器的安装、启动、查看
一.apache的启动 apahce启动命令:/你的安装目录/apachectl start apaceh启动 apache停止命令/你的安装目录/apachectl stop 停止 apache ...
- Ribbon 和 wowza 的集成开发
前言 Ribbon 是提供 REST 服务的区域感知负载均衡器,它在 wowza 的前端,应该部署在专业的 REST 容器下,而不是流媒体服务器 wowza 下. 本文介 ...
- SQL业务审核与优化
审核 什么是业务审核 类似与code review 评审业务Schema和SQL设计 偏重关注性能 是业务优化的主要入口之一 审核提前发现问题,进行优化 上 ...
- IE6支持兼容min-width、max-width CSS样式属性
IE6支持兼容min-width.max-width CSS样式属性 让IE6支持max-width.IE6支持min-width样式 我们在写CSS的时候,常常会遇到让一个图片或一个布局不能超出设定 ...
- 02、Quick Start for Windows phone
在使用这个 SDK 提供的功能前,必须先添加类库的引用到你的工程里.参考: Download and add the libraries to the project. 定义你的 XAML 的 UI ...
- doc转docx以及type对应的类型
https://blog.csdn.net/flagang/article/details/51454665 // 作为type格式保存到临时文件 // *Variant(0):doc // *Var ...
- 彻底征服 Spring AOP 之 理论篇
基本知识 其实, 接触了这么久的 AOP, 我感觉, AOP 给人难以理解的一个关键点是它的概念比较多, 而且坑爹的是, 这些概念经过了中文翻译后, 变得面目全非, 相同的一个术语, 在不同的翻译下, ...
- ibatis中in语句参数传入方法
第一种:传入参数仅有数组,iterate中不能有数组的属性名 <select id="GetEmailList_Test" resultClass=" ...
- OSX监听全局键盘按下事件并捕获事件源的硬件接口位置
在OSX系统全局监听键盘的按下事件,并可以捕获事件源的硬件的接口位置,用于区分是哪个键盘产生的事件.下面的代码只是以键盘为例子,其实是可以适用于其他输入外设的.如有需要可搜索相关外设的匹配字典的创建代 ...
- ci 框架插入时返回插入的id号
$this->db->insert('goods',$data); $gid=$this->db->insert_id('goods'); return $gid;