标签:
SPine数据组织
spAtlas:这个是从.atlas文件中解出来的结构,其中包含了纹理
struct spAtlas { spAtlasPage* pages; spAtlasRegion* regions; void* rendererObject; int ref; };
先不要管,看它的数据组织,spAtlasPage,spAtlasRegion,rendererObject都是什么东西?往下看
struct spAtlasPage { const spAtlas* atlas; const char* name; spAtlasFormat format; spAtlasFilter minFilter, magFilter; spAtlasWrap uWrap, vWrap; void* rendererObject; int width, height; spAtlasPage* next; };
spAtalsPage看它的成员,可以很简单看出,哇哦,这个就是纹理,给你看看真相,哈哈
void _spAtlasPage_createTexture (spAtlasPage* self, const char* path) { CCTexture2D* texture = CCTextureCache::sharedTextureCache()->addImage(path); texture->retain(); self->rendererObject = texture; self->width = texture->getPixelsWide(); self->height = texture->getPixelsHigh(); }
看见没有,真相在这里,里面有了纹理的宽,高。奇葩的是他竟然还有(spAtlasPage* next),很明显这是一个链表结构啊,如果你的一个动作文件,用到了多张纹理,那么这个指针就派上用场了。其他暂时忽略,看上面(_spAtlasPage_createTexture)发现没有,这里把纹理给持有了。所以纹理不会释放哦。
struct spAtlasRegion { const char* name; int x, y, width, height; float u, v, u2, v2; int offsetX, offsetY; int originalWidth, originalHeight; int index; int/*bool*/rotate; int/*bool*/flip; int* splits; int* pads; spAtlasPage* page; spAtlasRegion* next; };
这货一看,就是纹理当中包含的元素,一块,一块的描述信息。
看见这张纹理了吗,它的每一块都应该对应一个(spAtlasRegion)它。
这就是.atlas文件包含的信息啊!就是这样图片怎么怎么分割的,分隔成多少部分。每个部分的坐标是什么。
那个 renderobject是什么东西?我也不清楚,继续看。
spAtlas* spAtlas_create (const char* begin, int length, const char* dir, void* rendererObject) { spAtlas* self; int count; const char* end = begin + length; int dirLength = strlen(dir); int needsSlash = dirLength > 0 && dir[dirLength - 1] != ‘/‘ && dir[dirLength - 1] != ‘\\‘; spAtlasPage *page = 0; spAtlasPage *lastPage = 0; spAtlasRegion *lastRegion = 0; Str str; Str tuple[4]; self = NEW(spAtlas); self->rendererObject = rendererObject; ................
看见没有,亮点在最后一句。创建这个对象的时候,需要传进来一个东西void* rendererObject,然后,这个东西又赋予给了自己
spAtlas* self;
.......
self = NEW(spAtlas);
self->rendererObject = rendererObject;
然后在外面我的调用是
atlas = spAtlas_createFromFile(atlasFile, 0); 我竟然传了一个0,哈哈,没有用,暂时到这里。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
.JSON文件放的就是上面这些spAtlasRegion的树形结构的组织信息,也就是骨架信息,和每个动作信息,每个动作当中每个关键帧中各个Region的数据。哈哈。
先看看,创建的代码
SkeletonRenderer::SkeletonRenderer (const char* skeletonDataFile, const char* atlasFile, float scale) { initialize(); if(1) { CTimeMgr::GetInst()->time_begin("spAtlas_createFromFile"); atlas = spAtlas_createFromFile(atlasFile, 0); CCAssert(atlas, "Error reading atlas file."); CTimeMgr::GetInst()->time_end(); CTimeMgr::GetInst()->time_begin("spSkeletonJson_create"); spSkeletonJson* json = spSkeletonJson_create(atlas); CTimeMgr::GetInst()->time_end(); json->scale = scale; CTimeMgr::GetInst()->time_begin("spSkeletonJson_readSkeletonDataFile"); spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile); CTimeMgr::GetInst()->time_end(); CCAssert(skeletonData, json->error ? json->error : "Error reading skeleton data file."); spSkeletonJson_dispose(json); setSkeletonData(skeletonData, true); } else { atlas = spAtlas_createFromFile(atlasFile, 0); CCAssert(atlas, "Error reading atlas file."); spSkeletonJson* json = spSkeletonJson_create(atlas); json->scale = scale; spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile); CCAssert(skeletonData, json->error ? json->error : "Error reading skeleton data file."); spSkeletonJson_dispose(json); setSkeletonData(skeletonData, true); } }
if(1)中的内容,是我改的,else里面的内容是原有的。我改的目的,是为了1次加载多次使用,当然别的地方响应的有引用计数的析构了。还是老实的看else中的内容吧。
atlas = spAtlas_createFromFile(atlasFile, 0); 这个不用说了吧,我们暂且叫创建纹理图集吧
spSkeletonJson* json = spSkeletonJson_create(atlas); 根据纹理图集,创建一个JSON对象,它就像一个漏斗一样,纹理解析JSON文件准备的,用完就析构了。
json->scale = scale;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile);解析骨架文件
spSkeletonJson_dispose(json); 漏斗析构了吧
setSkeletonData(skeletonData, true); (以上代码在SkeletonRenderer类的构造函数中,所以,看清楚没有,解析出来的spSkeletonData被SkeletonRenderer持有了吧)
spSkeletonData* spSkeletonJson_readSkeletonDataFile (spSkeletonJson* self, const char* path) { int length; spSkeletonData* skeletonData; const char* json = _spUtil_readFile(path, &length); if (!json) { _spSkeletonJson_setError(self, 0, "Unable to read skeleton file: ", path); return 0; } skeletonData = spSkeletonJson_readSkeletonData(self, json); FREE(json); return skeletonData; }
这里干啥了,亮点在这句 skeletonData = spSkeletonJson_readSkeletonData(self, json);
反正大家知道这里面解析了JSON文件就可以了!
行了。我们只要知道JSON文件是要给包含骨架组织和动画运动的数据就可以了。而ATLAS文件才是与纹理相关就OK了。我们要做的是让它不持有纹理,想用的时候加载,不想用的时候,把纹理都卸掉就可以了!
假如加载纹理需要40ms,纹理占有内存512*512*4 = 1M,如果我们按照这个目标更改的话。其实是用了40ms换去了1M内存。
速度和内存是需要平衡的。哈哈,我们下面要开始做微创手术了。
Cocos2dx项目--动作类游戏内存优化--Spine结构分析1
标签:
原文地址:http://www.cnblogs.com/freeze86/p/4245060.html