• 菜鸟也能学cocos2dx3.0 浅析刀塔传奇(下)


    首先我们讲点话外的东西,异步载入:众所周知,loading里面一般都是载入数据的,那么是怎么载入的呢?

    Director::getInstance()->getTextureCache()->addImageAsync(const std::string &path, const std::function<void(Texture2D*)>& callback)//參数1,文件路径。參数2。回调函数(一般都是进度条)

    那么假设我们要载入帧动画呢?

    auto frameache=SpriteFrameCache::getInstance();
    frameache->addSpriteFramesWithFile(" xxxxxx  ");//參数。plist文件路径
    

    但是这样并非异步载入,那么应该怎么办?事实上还是用上面这两个:

    Director::getInstance()->getTextureCache()->addImageAsync(const std::string &path, const std::function<void(Texture2D*)>& callback);//我们首先异步载入了纹理
    auto My_Texture2D=Director::getInstance()->getTextureCache()->addImage(" ");
    

    //假设我们成功异步载入图片之后,我们能够从纹理缓存里面。即std::unordered_map<std::string,Texture2D*> _textures  返回相应key的纹理。

    而key在引擎源码中则是文件的完整路径,由于在texture2d里面会做一步std::string fullpath =FileUtils::getInstance()->fullPathForFilename(path);而我们外部用的话。仅仅须要平时resources的路径就可以。

    或者直接auto cache=SpriteFrameCache::getInstance(); cache->addSpriteFramesWithFile("plist路径","png路径");

    auto frameache=SpriteFrameCache::getInstance();
    frameache->addSpriteFramesWithFile(" xxxxxx  ",My_Texture2D);//參数1,plist文件路径,參数2,纹理  这样我们就能完毕异步载入帧动画了~
    

    进入正题 刀塔传奇:

    首先我们解压dota的包,会发现有


    一张背景为黑色的jpg图和一张灰度图。对不是带alpha的png图,而是无alpha的jpg,那么刀塔传奇为什么要这么做呢?

    下面为我个人的理解:

    jpg图是将图像像素进行了压缩,而另外一张灰度图实际上则是附带了透明通道的8位的png,那么我们仅仅要将灰度图的alpha复制过去,就能实现jpg的背景镂空。

    这种话就能缩小图片的资源大小,毕竟你jpg是经过压缩的,同等镂空的png果断是要大非常多的。这里能够确定jpg+8位灰度<png。

    那么这样做的优势在哪里呢。没错。就是在图片资源非常多的情况下,我们能够清楚得感受到使用这种图片格式的优点:一、能够使你的应用程序更小,由于图片是压缩过了的。二、你的游戏能够启动地更快。

    原理上和pvr.ccz有点相似,但是pvr.ccz有着它独特的优势。就是pvr格式能够直接被ios的显卡所认可,比png更加安全。避免大量图片载入的内存问题。

    然后呢,我们应该怎么用jpg+灰度图实现纹理镂空的效果呢?

    看引擎代码!

    Texture2D * TextureCache::addImage(const std::string &path)
    {
        Texture2D * texture = nullptr;
        Image* image = nullptr;
        // Split up directory and filename
        // MUTEX:
        // Needed since addImageAsync calls this method from a different thread
    
        std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path);//获取完整路径
        if (fullpath.size() == 0)
        {
            return nullptr;
        }
        auto it = _textures.find(fullpath);//在缓存中查找是否是已经载入过的纹理图片
        if( it != _textures.end() )
            texture = it->second;
    
        if (! texture)//假设是未被加过的纹理
        {
            // all images are handled by UIImage except PVR extension that is handled by our own handler
            do 
            {
                image = new Image();//创建一个image对象,imgae对象中封装了libjpeg,即jpg的解压/压缩库。另外利用了FileUtils::getInstance()->getDataFromFile(_filePath)  FileUtils默认会以rb模式读取二进制的数据信息
                CC_BREAK_IF(nullptr == image);
    
                bool bRet = image->initWithImageFile(fullpath);//将FileUtiles读取的数据用jpeg进行解压。期间有个图片格式的推断
                CC_BREAK_IF(!bRet);
    		
                texture = new Texture2D();
    
                if( texture && texture->initWithImage(image) )//载入纹理将rgb888的jpg转为rgba8888
                {
    #if CC_ENABLE_CACHE_TEXTURE_DATA
                    // cache the texture file name
                    VolatileTextureMgr::addImageTexture(texture, fullpath);
    #endif
                    // texture already retained, no need to re-retain it
                    _textures.insert( std::make_pair(fullpath, texture) );
                }
                else
                {
                    CCLOG("cocos2d: Couldn't create texture for file:%s in TextureCache", path.c_str());
                }
            } while (0);
        }
    
        CC_SAFE_RELEASE(image);
    
        return texture;
    }
    /*..
    省略
    */
    
     *outDataLen = dataLen/3*4;//将rgb的length增长到rgba的长度
     *outData = new unsigned char[*outDataLen];//申请一块长度为rgba长度的内存
     auto TempData=outData;
    /*..
    省略
    */
     for (ssize_t i = 0, j=0,l = dataLen - 2; i < l; i += 3,++j)
        {
            * outData ++ = data[i];         //R
            * outData ++ = data[i + 1];     //G
            * outData ++ = data[i + 2];     //B
            * outData ++ =png_data[j];      //A 依据灰度图的像素信息0和255设置alpha
        }
    auto new_Texture2d=new Texture2D();
    new_Texture2d->initWithData(TempData,datalen。pixelFormat, imageWidth, imageHeight, imageSize);
    


    //这样我们就能实现刀塔传奇的主界面效果。 至于主界面中的比方泉水发光的效果,则是通过shader实现的

    至于dota的骨骼部分据说是他们自己的flash引擎做的,而我则用spine做了骨骼,由于cocostuio的骨骼功能不完好,spine则是专门针对骨骼的编辑器,而且全平台支持。u3d。libgdx,as3等等。最赞的应该就是spine的ffd,蒙皮了。

    眼下正在研究binary。即spine的二进制文件导出,直接读取binary创建骨骼的话,将会比json读取的更快,内存占用更小。

    ps:cocos2dx 3.1rc0出了,支持prite3dvideo。眼下感觉video应该是比較有用的,3d的话,个人感觉还是u3d吧。。。cocos3d支持还须要发展。

  • 相关阅读:
    Linux kill -9 和 kill -15 的区别
    redis 学习笔记之(五)redis-cli 命令
    专题(十四)awk
    Linux 学习笔记之(十一)SSH
    Linux 学习笔记之(十)查看文件
    rust 读写文件
    rust 显示本机ip
    rust error: linking with `link.exe` failed: exit code: 1181(未解决)
    Building a Concurrent Web Server with Async Rust
    Asynchronous Programming in Rust
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/9973608.html
Copyright © 2020-2023  润新知