cocos2d-x - 资源加载

资源加载

简而言之,cocos2d-x使用快速缓存机制(Cache)来缓存加载的资源,避免重复读取磁盘的开销。

(一)CSLoader

CSLoader模块用于从CocosStudio导出的csb, json或ExportJson文件中加载相应的节点(Node)、动画(ActionTimeline)等。

1. 加载节点
  • 直接调用CSLoader::createNode方法。e.g.
    auto node = CSLoader::createNode("MainScene.csb");
    if (node) 
    {
        addChild(node);
    }
    
  • CSLoader::createNode:根据后缀选择对应的创建方法——二进制(csb)或 json(json/ExportJson)
    Node* CSLoader::createNode(const std::string& filename)
    {
        std::string path = filename;
        size_t pos = path.find_last_of('.');
        std::string suffix = path.substr(pos + 1, path.length());
        
        CSLoader* load = CSLoader::getInstance();
    
        if (suffix == "csb")
        {
            return load->createNodeWithFlatBuffersFile(filename, nullptr);
        }
        else if (suffix == "json" || suffix == "ExportJson")
        {
            return load->createNodeFromJson(filename);
        }
    
        return nullptr;
    }
    
    Node* CSLoader::createNodeWithFlatBuffersFile(const std::string &filename, const ccNodeLoadCallback &callback)
    {
        Node* node = nodeWithFlatBuffersFile(filename, callback);
        reconstructNestNode(node);
        return node;
    }
    
  • CSLoader::nodeWithFlatBuffersFile:使用FlatBuffer文件(二进制)创建节点。
    Node* CSLoader::nodeWithFlatBuffersFile(const std::string &fileName, const ccNodeLoadCallback &callback)
    {
        std::string fullPath = FileUtils::getInstance()->fullPathForFilename(fileName);	// 绝对路径
        Data buf = FileUtils::getInstance()->getDataFromFile(fullPath);	
    
        auto csparsebinary = GetCSParseBinary(buf.getBytes());
        
        // decode plist
        auto textures = csparsebinary->textures();
        int textureSize = textures->size();
        for (int i = 0; i < textureSize; ++i)
        {
            SpriteFrameCache::getInstance()->addSpriteFramesWithFile(textures->Get(i)->c_str());	// 将精灵帧添加到快速缓存中(如果有帧动画的话)
        }
        
        Node* node = nodeWithFlatBuffers(csparsebinary->nodeTree(), callback);	// 递归创建节点树
        
        return node;
    }
    
    • 目前有个问题就是暂时不清楚什么时候会触发addSpriteFramesWithFile,即使在CocosStudio生成了帧动画,也不会在加载时触发精灵帧的快速缓存。但在方法CSLoader::loadSprite会应用到(SpriteFrame* spriteFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName(path);)。
    • 关于精灵快速缓存和纹理快速缓存可以参考博客:我的Cocos2d-x學習筆記(七)紋理快取、幀快取、精靈的建立、zOrder
2. 加载动画
  • 直接调用CSLoader::createTimeline方法。
    ActionTimeline* action = CSLoader::createTimeline("MainScene.csb");
    if (action) 
    {
        node->runAction(action);
        action->gotoFrameAndPlay(0, false);
    }
    
  • CSLoader::createTimeline:根据后缀选择对应的创建方法——二进制(csb)或 json(json/ExportJson)。
    ActionTimeline* CSLoader::createTimeline(const std::string &filename)
    {
        std::string suffix = getExtentionName(filename);
        
        ActionTimelineCache* cache = ActionTimelineCache::getInstance();
        
        if (suffix == "csb")
        {
            return cache->createActionWithFlatBuffersFile(filename);
        }
        else if (suffix == "json" || suffix == "ExportJson")
        {
            return cache->createActionFromJson(filename);
        }
        
        return nullptr;
    }
    
  • ActionTimelineCache::createActionWithFlatBuffersFile:判断一下动作是否已经存在,不存在就加载,否则直接返回clone。
    ActionTimeline* ActionTimelineCache::createActionWithFlatBuffersFile(const std::string &fileName)
    {
        ActionTimeline* action = _animationActions.at(fileName);
        if (action == NULL)
        {
            action = loadAnimationActionWithFlatBuffersFile(fileName);
        }
        return action->clone();
    }
    
  • ActionTimelineCache::loadAnimationActionWithFlatBuffersFile:从csb文件中加载数据,进一步调用createActionWithDataBuffer函数。
    ActionTimeline* ActionTimelineCache::loadAnimationActionWithFlatBuffersFile(const std::string &fileName)
    {
        // if already exists an action with filename, then return this action
        ActionTimeline* action = _animationActions.at(fileName);
        if (action)
            return action;	// 不是才判断过吗?为什么这里还要再判断一次?
        
        std::string path = fileName;
        
        std::string fullPath = FileUtils::getInstance()->fullPathForFilename(fileName);
        
        CC_ASSERT(FileUtils::getInstance()->isFileExist(fullPath));
        
        Data buf = FileUtils::getInstance()->getDataFromFile(fullPath);
        action = createActionWithDataBuffer(buf);
        _animationActions.insert(fileName, action);
    
        return action;
    }
    
  • ActionTimelineCache::createActionWithDataBuffer:获取动作,调用loadTimelineWithFlatBuffers加载时间线。
    ActionTimeline* ActionTimelineCache::createActionWithDataBuffer(const cocos2d::Data& data)
    {
        auto csparsebinary = GetCSParseBinary(data.getBytes());	// 解析csb二进制文件
    
        auto nodeAction = csparsebinary->action();	// 获取动作
        auto action = ActionTimeline::create();
    
        int duration = nodeAction->duration();
        action->setDuration(duration);
        float speed = nodeAction->speed();
        action->setTimeSpeed(speed);
        
        auto animationlist = csparsebinary->animationList();
        int animationcount = animationlist->size();
        for (int i = 0; i < animationcount; i++)
        {
            auto animationdata = animationlist->Get(i);
            AnimationInfo info;
            info.name = animationdata->name()->c_str();
            info.startIndex = animationdata->startIndex();
            info.endIndex = animationdata->endIndex();
            action->addAnimationInfo(info);
        }
    
        auto timeLines = nodeAction->timeLines();
        int timelineLength = timeLines->size();
        std::multimap<std::string,timeline::Timeline*> properTimelineMap;// order the timelines depends property name
        for (int i = 0; i < timelineLength; i++)
        {
            auto timelineFlatBuf = timeLines->Get(i);
            Timeline* timeline = loadTimelineWithFlatBuffers(timelineFlatBuf);	// 加载Timeline
            if (timeline)
            {
                properTimelineMap.emplace(timelineFlatBuf->property()->c_str(), timeline);
            }
        }
    
        for (const auto& properTimelinePair : properTimelineMap)
        {
            action->addTimeline(properTimelinePair.second);
        }
        return action;
    }
    
  • ActionTimelineCache::loadTimelineWithFlatBuffers:根据不同的属性加载不同的帧。
    Timeline* ActionTimelineCache::loadTimelineWithFlatBuffers(const flatbuffers::TimeLine *flatbuffers)
    {
        Timeline* timeline = nullptr;
        
        // property
        std::string property = flatbuffers->property()->c_str();
        if(property == "")
            return nullptr;
      	
        if(property != "")
        {
            timeline = Timeline::create();
            
            int actionTag = flatbuffers->actionTag();
            timeline->setActionTag(actionTag);
            
            auto framesFlatbuf = flatbuffers->frames();
            int length = framesFlatbuf->size();
            for (int i = 0; i < length; i++)
            {
                auto frameFlatbuf = framesFlatbuf->Get(i);
                Frame* frame = nullptr;
                
                if (property == Property_VisibleForFrame)
                {
                    auto boolFrame = frameFlatbuf->boolFrame();
                    frame = loadVisibleFrameWithFlatBuffers(boolFrame);
                }
                else if (property == Property_Position)
                {
                    auto potisionFrame = frameFlatbuf->pointFrame();
                    frame = loadPositionFrameWithFlatBuffers(potisionFrame);
                }
                else if (property == Property_Scale)
                {
                    auto scaleFrame = frameFlatbuf->scaleFrame();
                    frame = loadScaleFrameWithFlatBuffers(scaleFrame);
                }
                else if (property == Property_RotationSkew)
                {
                    auto scaleFrame = frameFlatbuf->scaleFrame();
                    frame = loadRotationSkewFrameWithFlatBuffers(scaleFrame);
                }
                else if (property == Property_CColor)
                {
                    auto colorFrame = frameFlatbuf->colorFrame();
                    frame = loadColorFrameWithFlatBuffers(colorFrame);
                }
                else if (property == Property_FrameEvent)
                {
                    auto eventFrame = frameFlatbuf->eventFrame();
                    frame = loadEventFrameWithFlatBuffers(eventFrame);
                }
                else if (property == Property_FileData)
                {
                    auto textureFrame = frameFlatbuf->textureFrame();
                    frame = loadTextureFrameWithFlatBuffers(textureFrame);
                }
                else if (property == Property_Alpha)
                {
                    auto intFrame = frameFlatbuf->intFrame();
                    frame = loadAlphaFrameWithFlatBuffers(intFrame);
                }
                else if (property == Property_AnchorPoint)
                {
                    auto scaleFrame = frameFlatbuf->scaleFrame();
                    frame = loadAnchorPointFrameWithFlatBuffers(scaleFrame);
                }
                else if (property == Property_ZOrder)
                {
                    auto intFrame = frameFlatbuf->intFrame();
                    frame = loadZOrderFrameWithFlatBuffers(intFrame);
                }
                else if (property == Property_ActionValue)
                {
                    auto innerActionFrame = frameFlatbuf->innerActionFrame();
                    frame = loadInnerActionFrameWithFlatBuffers(innerActionFrame);
                }
                else if (property == Property_BlendValue)
                {
                    auto blendFrame = frameFlatbuf->blendFrame();
                    frame = loadBlendFrameWithFlatBuffers(blendFrame);
                }
    
                if (!frame)
                {
                    CCLOG("frame is invalid.");
                    continue;
                }
                timeline->addFrame(frame);
            }
        }
        
        return timeline;
    }
    

【参考资料】
[1] 我的Cocos2d-x學習筆記(七)紋理快取、幀快取、精靈的建立、zOrder
[2] Cocos2d-x 之精灵帧 SpriteFrame

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值