Cocos2d-x学习笔记(九)纹理CCTexture2D和精灵CCSprite

来源:互联网 发布:如何评价新东方 知乎 编辑:程序博客网 时间:2024/05/01 21:03


原创文章,转载请注明出处:http://blog.csdn.net/sfh366958228/article/details/38850499


前言

在Cocos2d-x中对图片得封装是通过CCImage来完成,该类实现了对于不同类型图片得读取、解析、像素信息保存。由于在引擎内部封装,一般情况下不需要修改此类,由于Cocos2d-x使用了Open GL的图形库,因此在图片显示在屏幕的过程中是通过在3D空间的某个平面通过纹理贴图的方式完成的图片显示,在Cocos2d-x中通过CCTexture2D来实现。

在纹理处理中有如下一些常用类:

CCImage // 调用libpng libjpg来读取图片的像素信息

CCTexture2D // 封装纹理对象

CCTextureCache // 一组纹理对象,通过CCDictionary管理,通过字符key获取

CCRenderTexture // 创建动态纹理

CCSprite // 实现纹理显示

CCSpriteFrame // 用来定义动画层的每一帧,定义好厚以CCAction的形式作用到一个CCSprite上来呈现动画效果

CCSpriteBatchNode //

CCSpriteFrameCache // 一组纹理对象,通过CCDictionary管理,通过字符key获取

CCAnimation // 实现一组Sprite播放的Action


根据图片文件创建CCSprite

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. CCSprite * sprite = CCSprite::create("HelloWorld.png");  
利用create方法完成了对图片纹理的加载,我们来看看创建过程的源码
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. CCSprite* CCSprite::create(const char *pszFileName, const CCRect& rect)  
  2. {  
  3.     CCSprite *pobSprite = new CCSprite(); //创建一个CCSprite对象  
  4.     if (pobSprite && pobSprite->initWithFile(pszFileName, rect)) // 如果成功创建,且初始化成功  
  5.     {  
  6.         pobSprite->autorelease(); // 添加到自动释放管理CCPoolManager中  
  7.         return pobSprite;  
  8.     }  
  9.     CC_SAFE_DELETE(pobSprite); // 创建失败,安全删除  
  10.     return NULL;  
  11. }  
  12.   
  13. bool CCSprite::initWithFile(const char *pszFilename, const CCRect& rect)  
  14. {  
  15.     CCAssert(pszFilename != NULL, ""); // 文件名不能为空  
  16.   
  17.     CCTexture2D *pTexture = CCTextureCache::sharedTextureCache()->addImage(pszFilename); // 将图片添加至纹理缓存中,并获取对应的CCTexture对象  
  18.     if (pTexture) // 如果对象不为空,返回initWithTexture  
  19.     {  
  20.         return initWithTexture(pTexture, rect);  
  21.     }  
  22.     return false;  
  23. }  
  24.   
  25. bool CCSpriteFrame::initWithTexture(CCTexture2D* pobTexture, const CCRect& rect)  
  26. {  
  27.     CCRect rectInPixels = CC_RECT_POINTS_TO_PIXELS(rect); // 点矩形转像素矩形  
  28.     return initWithTexture(pobTexture, rectInPixels, false, CCPointZero, rectInPixels.size);  
  29. }  
  30.   
  31. bool CCSpriteFrame::initWithTexture(CCTexture2D* pobTexture, const CCRect& rect, bool rotated, const CCPoint& offset, const CCSize& originalSize)  
  32. {  
  33.     m_pobTexture = pobTexture;  
  34.     if (pobTexture)  
  35.     {  
  36.         pobTexture->retain();  
  37.     }  
  38.   
  39.     m_obRectInPixels = rect;  
  40.     m_obRect = CC_RECT_PIXELS_TO_POINTS(rect);  
  41.     m_obOffsetInPixels = offset;  
  42.     m_obOffset = CC_POINT_PIXELS_TO_POINTS( m_obOffsetInPixels );  
  43.     m_obOriginalSizeInPixels = originalSize;  
  44.     m_obOriginalSize = CC_SIZE_PIXELS_TO_POINTS( m_obOriginalSizeInPixels );  
  45.     m_bRotated = rotated;  
  46.   
  47.     return true;  
  48. }  

根据CCTexture2D纹理对象创建CCSprite

有时候,为了让图片资源更小,会根据一张图片来创建不同的CCSprite,这样需要首先通过CCTextureCache加载图片到图片纹理的缓存,然后从缓存获取这张图片的CCTexture2D对象,根据这个对象来创建CCSprite,代码如下:
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. CCTexture2D *texture = CCTextureCache()::sharedTextureCache()->addImage("Player.png");  
  2. CCSprite *sprite = CCSprite::createWithTexture(texture, CCRectMake(0, 0, 85, 121));  
CCRectMake是指定一个裁剪区域,该方法实现了将纹理对象texture的一部分区域创建一个CCSprite图层。
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. CCSprite* CCSprite::createWithTexture(CCTexture2D *pTexture, const CCRect& rect)  
  2. {  
  3.     CCSprite *pobSprite = new CCSprite();  
  4.     if (pobSprite && pobSprite->initWithTexture(pTexture, rect))  
  5.     {  
  6.         pobSprite->autorelease();  
  7.         return pobSprite;  
  8.     }  
  9.     CC_SAFE_DELETE(pobSprite);  
  10.     return NULL;  
  11. }  
createWithTexture和create方法几乎类似。

使用CCSpriteFrame创建CCSprite

CCSpriteFrame是用来定义动画层的每一帧,定义好以后以CCAction的形式作用到一个CCSprite上来呈现动画效果,一般情况下会用这个动画的第一帧来创建CCSprite:
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. CCTexture2D *texture = CCTextureCache()::sharedTextureCache()->addImage("Player.png");  
  2. CCSpriteFrame spriteFrame01 = CCSpriteFrame::createWithTexture(texture, CCRectMake(132 * 0, 132 * 0, 132, 132));  
  3. CCSprite *sprite = CCSprite::createWithSpriteFrame(spriteFrame01);  
而CCSpriteFrame的创建除了直接通过CCTexture2D对象之外,还可以通过读取纹理工具(Cocos Studio)导出的plist文件来创建。
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. CCSpriteFrameCache *cache = CCSpriteFrameCache::sharedSpriteFrameCache();  
  2. cache->addSpriteFramesWithFile("grossini.plist");  
  3. CCArray *aniFrames = CCArray::createWithCapacity(14);  
  4. char str[100] = {0};  
  5. for (int k = 0; k < 14; ;++)  
  6. {  
  7. sprintf(str, "grossini_dance_%02d.png", (k+1));  
  8. CCSpriteFrame *frame = cache->spriteFrameByName(str);  
  9. animFrames->addObject(frame);  
  10. }  
通过grossini.plist将图片剪裁程多帧,在使用的时候通过spriteFrameByName方法从CCSpriteFrameCache获取每一帧,通过工具软件生成plist,通过上述方法解析plist,能大大加快程序开发的效率。

使用CCAnimate和CCAnimation创建动画
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. // 序列帧加载方法1 - 逐图加载  
  2. CCAnimation *animation = CCAnimation::create();  
  3. char str[100] = {0};  
  4. for(int i = 1; i <= 14; i++){  
  5.     sprintf(str, "grossini_dance_%02d.png", i);  
  6.     animation->addSpriteFrameWithFileName(str);  
  7. }  
  8. animation->setDelayPerUnit(0.2);  
  9. animation->setRestoreOriginalFrame(false);  
  10. sprite->runAction(CCAnimate::create(animate));  
  11.   
  12. // 序列帧加载方法2 - 切图法  
  13. CCArray* animFrames = CCArray::createWithCapacity(14);  
  14. CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage("grossini_dance_atlas_nomipmap.png");  
  15. for (int i = 0; i < 14; i++) {  
  16.     CCSpriteFrame* spriteFrame = CCSpriteFrame::createWithTexture(texture, CCRectMake(40 * i % 5, 57 * i / 5, 40, 57));  
  17.     animFrames->addObject(spriteFrame);  
  18. }  
  19. CCAnimation *animation = CCAnimation::createWithSpriteFrames(animFrames, 0.2f);  
  20. sprite->runAction(CCAnimate::create(animation));  

用CCSpriteBatchNode进行文理贴图的优化

在场景中随机生成100个相同的精灵,看看使用CCSpriteBatchNode优化前和优化后两种不同的效果。

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. // 优化前  
  2. for (int i = 0; i < 100; i++)  
  3. {  
  4.     CCSprite *sp = CCSprite::create("Icon.png");  
  5.     int x = arc4random()%480;  
  6.     int y = arc4random()%320;  
  7.     sp->setPosition(CCPointMake(x, y));  
  8.     this->addChild(sp);  
  9. }  
  10.   
  11. // 优化后  
  12. CCSpriteBatchNode* batchNode = CCSpriteBatchNode::create("Icon.png", 10);  
  13. batchNode->setPosition(CCPointZero);  
  14. this->addChild(batchNode);  
  15. for (int i=0; i<100; i++)  
  16. {  
  17.     CCSprite *sp = CCSprite::create("Icon.png");  
  18.     int x = arc4random()%480;  
  19.     int y = arc4random()%320;  
  20.     sp->setPosition(CCPointMake(x, y));  
  21.     batchNode->addChild(sp);  
  22. }  


效果(优化前):



效果(优化后):



优化了之后,明显的看的出第一幅图第一个参数是100,也就是说精灵渲染了100次,这是比较消耗资源的。第二幅图,第一个参数只渲染一次。还有就是由于模拟器调用的是PC的内存所以内存比较大,对第三个参数是不会有多大的影响的,但如果是真机调试的话效果会很明显,第一种情况会明显的比较卡。


0 0
原创粉丝点击