码迷,mamicode.com
首页 > 其他好文 > 详细

Cocos2dx项目--动作类游戏内存优化--Spine结构分析1

时间:2015-01-23 21:31:56      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!