Cocos2d-x 精灵CCSprite

精灵就是将图形资源加载到内存中,并根据游戏需要将其显示到屏幕中的工具,继承自CCNode,CCSprite除了节点的功能外,还封装了一张图片,在游戏中一个2D图形就是一个精灵类的对象。还有一点我们需要注意,就是cocos2d是用3d的方式绘制2d图形的,精灵绘制图像用的是openGL ES(移动平台用的3d引擎,android用的也是它),因此图片在内存中实际上是以Texture贴图)的形式存在的
精灵相关类的关系图

精灵相关类的关系图.jpg

方法

static CCSprite* spriteWithTexture(CCTexture2D *pTexture);
根据一个CCTexture2D创建并返回一个精灵对象,就是封装了alloc、init和autorelease的静态初始化方法。前面说过,精灵是用Texture绘制的,CCTexture2D就是封装了Texture的类,精灵必须被赋予一个CCTexture2D的对象才能工作。

static Sprite* createWithTexture(CCTexture2D *texture, const Rect& rect, bool rotated=false);
增加了读取范围的创建方法,该方法只会将范围内的图像加载到精灵中,以及范围矩形是否旋转

static Sprite* create(const std::string& filename);
根据图片资源创建并返回精灵对象,filename是文件(通常是png)的相对路径,即前面省略了bundle的路径。

static Sprite* create(const std::string& filename, const Rect& rect);
也是根据图片资源创建并返回精灵对象,只是增加了读取范围,只会加载范围内的图像。

static Sprite* createWithSpriteFrame(SpriteFrame *spriteFrame);
根据一个CCSPriteFrame对象创建并返回一个精灵对象,CCSPriteFrame是帧,它是组成动画的一部分,CCSPriteFrame的成员变量中有一个Texture,用帧创建精灵,其实就是用帧的Texture创建精灵,当精灵切换帧时,Texture也会随之更换,精灵就会呈现不同的形态,以次达到动画的效果。这里大家可以理解为,Texture和Frame都可以构成一个精灵对象。

static Sprite* createWithSpriteFrameName(const std::string& spriteFrameName);
根据帧的名字创建并返回一个精灵对象。这里要引入一个概念,就是cocos2d中的帧是由一个单例对象统一管理的,这个单例的作用就是充当一个内存池,它将需要使用的CCSpriteFrame对象保存到自己内部的一个字典中,当有精灵需要用到它时,就从池中取出来传递过去,如果有多个精灵需要一个Frame的话,可以共用一个,而不必拷贝N份,这样可以节约内存和创建对象的时间。这里的参数spriteFrameName其实就是字典的Key,内存池先通过它找到Frame对象,再用它去创建精灵。

virtual bool initWithTexture(CCTexture2D *texture);
virtual bool initWithTexture(CCTexture2D *texture, const Rect& rect);
virtual bool initWithFile(const std::string& filename);
virtual bool initWithSpriteFrame(SpriteFrame *spriteFrame);
virtual bool initWithSpriteFrameName(const std::string& spriteFrameName);
以上都是静态方法调用的初始化

virtual SpriteBatchNode* getBatchNode() const;
virtual void setBatchNode(SpriteBatchNode *spriteBatchNode);
CCSpriteBatchNode,是一个批量处理精灵绘制的类。
精灵是用openGL的方法绘制图形的,这点大家都清楚了,当场景中有100个精灵的时候,程序的执行是这样的:

for(int i= 0;i<100;i++){
    open-draw-close;
}

就是说执行了100次的open-draw-close;而用CCSpriteBatchNode绘制的话则是这样执行的:
open-

for(int i= 0;i<100;i++){
    draw;
}

-close,即省略了99次的open和close,从而优化了精灵的绘制效率。这里就是用CCSpriteBatchNode中的Texture创建精灵,并把精灵添加到batchNode中。

SpriteBatchNode *batch = SpriteBatchNode::create("Images/grossini_dance_atlas.png", 15);
Sprite *sprite = Sprite::createWithTexture(batch->getTexture(), Rect(0, 0, 57, 57));
batch->addChild(sprite);
layer->addChild(batch);

- (void) draw
绘制

- (void) setDisplayFrame:(CCSpriteFrame*)frame
切换精灵当前显示的图象,之前说过精灵是可以播放动画的,播放动画的实质就是切换Frame,都是靠该接口实现的。

- (void) setDisplayFrameWithAnimationName: (NSString*) animationName index:(int) frameIndex
将动画序列中的某一帧设置为精灵当前的显示帧。CCAnimation是封装动画功能的类,它可以看作是由若干个_CCSpriteFrame对象组成的序列,精灵按照顺序切换它们,就形成了动画。CCAnimation也有内存池,此处的animationName就是key,内存池通过它找到CCAnimation对象,再通过索引frameIndex找到动画序列中的某一帧,将该帧设为精灵的当前显示帧。

- (BOOL) isFrameDisplayed:(CCSpriteFrame*)frame
判断精灵当前显示的帧是否为参数frame,判断的依据是它们的成员texture的名字和rect是否相同。

- (CCSpriteFrame*) displayedFrame
获取精灵当前显示的帧。

- (void) setTexture:(CCTexture2D*)texture
设置精灵当前显示的贴图,作用其实和setDisplayFrame,都是改变精灵的形态,只不过这个方法是直接改Texture(setDisplayFrame内部也调用了该方法)。

- (CCTexture2D*) texture
获取精灵当前显示的贴图。

CCSpriteBatchNode

CCSpriteBatchNode作用是优化精灵,提高精灵的绘制效率,精灵数量越多,效果越明显。它的工作原理是:将所有该对象的子节点(只能是精灵)用openGL的渲染方法一次性绘制,这样可以省去多次open-close的时间,作为CCSpriteBatchNode对象子节点的精灵不能用自己的Texture绘制,而是用CCSpriteBatchNode对象的Texture统一绘制,精灵只是提供坐标、旋转角度等信息,这就是它只需要open-close一次的原因,但也正因为如此,导致批处理节点的所有子节点都必须和它用同一套Texture,即CCSpriteBatchNode对象绘制出的图形都是一样的,这点需要格外注意。CCSpriteBatchNode的用法和普通精灵没什么两样,都可以设置Texture,也都是用Texture来绘制,只要通过addChild方法成为其子节点的精灵,都会得到它的优化,但是CCSpriteBatchNode只能添加精灵为子节点。

static SpriteBatchNode* createWithTexture(Texture2D* tex, ssize_t capacity = DEFAULT_CAPACITY);
和精灵的方法类似,根据一个CCTexture2D对象构建一个精灵批处理节点,封装了alloc、init和autorelease方法。

static SpriteBatchNode* create(const std::string& fileImage, ssize_t capacity = DEFAULT_CAPACITY);
根据文件名初始化

CCTexture2D

可以把它看成一个纹理(即图片加载入内存后供CPUGPU操作的贴图对象。),它是cocos2d-x渲染图形的重要参数,用来贴图,因为cocos2d-x使用opengl es绘制2d图形的,它的尺寸是2n次方。一般通过以下方式获得:

CCTexture2D* cache = CCTextureCache::sharedTextureCache()->addImage("hero.png");

– (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size
初始化CCTexture2D对象,方法中的那一长串参数都是引擎帮我们运算出来的,它通常被下面的方法调用,因此先别急着去钻研这些参数,即使你看到头大它也不过是生成一张贴图而已……

– (id) initWithImage:(UIImage *)uiImage resolutionType:(ccResolutionType)resolution
总的来说它就是将一个UIImage转化为一个CCTexture2D,这个方法被N多种方法封装过(比如我们前面说的精灵的initWithFile方法),基本上我们也不会主动去用它。

– (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size
根据一个字符串生成一个Texture,这个方法不需要图片资源。

CCTextureCache

该类的本质是一个内存池,用来缓存游戏中用到的CCTexture2D对象,是个单例。一旦纹理加载完成,下次使用时可使用它返回之前加载的纹理,从而减少对GPUCPU内存的占用。

它内部有一个字典CCMutableDictionary m_pTextureskey为图片的名称,值是CCTexture2D。当调用它的addImage函数添加图片时,会先根据图片名称去内存中查找是否已存在,如果存在,则将对象返回,如果不存在,则会生成一个,将其存入池中并返回,这样同样的Texture在池中最多只会有一份,达到节约空间的目的。

+ (CCTextureCache *)sharedTextureCache
获取单例,单例类的惯用模式。

+ (void)purgeSharedTextureCache
释放内存池,当游戏结束时由导演调用。

CCSpriteFrame

这个类的最大作用就是作为Texture的载体,将图形数据传递给精灵,同时它还有offsetrotated等一系列参数,用来存储Plist的数据。(plist是一种数据存储格式,有专门的API可以将其读取并保存到内存中,但这里说的是一种动画编辑器生成的、基于plist格式保存的数据,就是说cocos2d支持这种动画编辑器,可以解析它的数据)使用Frame机制构建精灵,还可以支持精灵的动画效果,因为精灵除了做位移或旋转等操作,还可能实时地改变自身显示的图形。cocos2dCCAnimation保存一个Frame序列,然后用CCAnimate这个行为类根据序列定时切换精灵的当前帧。

CCSpriteFrameCache

SpriteFrameCache 管理帧的内存池,主要服务于多张碎图合并出来的纹理图片。这种纹理在一张大图中包含了多张小图,直接通过TextureCache引用会有诸多不便,因而衍生出来精灵框帧的处理方式,即把截取好的纹理信息保存在一个精灵框帧内,精灵通过切换不同的框帧来显示出不同的图案。
SpriteFrameCache的常用接口和TextureCache类似,唯一需要注意的是添加精灵帧的配套文件一个plist文件和一张大的纹理图

- (void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary textureFilename:(NSString*)textureFilename
根据一个字典和Texture的文件名构建CCSpriteFrame对象并添加到内存池中。一般来说这个字典都是从plist中读取出来的,通过这种方法来支持动画编辑器,当然我们也可以根据这个格式自己构建字典。

- (void) addSpriteFramesWithFile:(NSString*)plist textureFilename:(NSString*)textureFilename
根据一个plist文件名和Texture的文件名构建CCSpriteFrame对象并添加到内存池中。先通过文件名找到plist文件的路径,然后用字典的API把它加载到内存中,最后调用addSpriteFramesWithDictionary:textureFilename:方法。

- (void) addSpriteFramesWithFile:(NSString*)plist
缺省了Texture文件名的构建方法,缺省的文件名先在_plist中查找,如果没有则查找和plist同名的文件。

- (void) addSpriteFrame:(CCSpriteFrame*)frame name:(NSString*)frameName
将CCSpriteFrame对象添加到内存池中。

- (void) removeSpriteFrameByName:(NSString*)name
根据key从内存池中删除Frame。

– (void) removeSpriteFramesFromFile:(NSString*) plist
从内存池删除plist中列出的Frame,相当于addSpriteFramesWithFile的逆向操作。

– (void) removeSpriteFramesFromDictionary:(NSDictionary*) dictionary
从内存池删除字典中列出的Frame,相当于addSpriteFramesWithDictionary的逆向操作。

- (CCSpriteFrame*) spriteFrameByName:(NSString*)name
根据key在内存池中查找Frame并返回。

– (void) removeSpriteFramesFromTexture:(CCTexture2D*) texture
从内存池中删除和所给texture相同的Frame。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容