【玩转cocos2d-x之三十七】粒子系统的加载优化
Cocos2d-x的粒子系统是通过加载plist生成的。plist包含两部分内容:粒子系统属性和粒子纹理。然而每次调用create都会对plist进行读取解析,如果重复地使用同一个粒子效果,这样的调用明显是低效冗余的。所以我们要做的是,将粒子系统属性和粒子纹理分别抽出。
(1)将粒子系统属性预加载并全局保存,避免每次进行读取。
(2)粒子纹理可视且可以进行纹理打包,加载粒子纹理就和加载普通的图片一样。
本文通过增加ParticleSystemQuad的接口实现对粒子系统属性和纹理帧的直接载入,来提高粒子系统的加载效率和实现内存纹理的优化。
1.ParticleSystemQuad
首先先看下ParticleSystemQuad,ParticleSystemQuad继承于ParticleSystem,拥有后者的所有特性,并且增加了一些新的特性:
(1)粒子大小支持浮点数
(2)支持缩放
(3)支持选择
(4)支持subrect
(5)支持批渲染
ParticleSystemQuad同时也是其他特效的父类,创建一个粒子系统的函数调用顺序为:
- Create→initWithFile→initWithDictionary
在initWithDictionary中对粒子数据和纹理进行了读取和解析(这部分有兴趣的可以直接看源码)。
2.如何优化?
参考initWithDictionary的函参
- static bool initWithDictionary(ValueMap& dictionary, const std::string& dirname);
设计如下接口,当然你要传入文件名也可以:
- static ParticleSystemQuad * create(ValueMap& valueMap, SpriteFrame *frame);
- bool initWithValueMap(ValueMap &valueMap, SpriteFrame* frame);
源码如下:
- ParticleSystemQuad * ParticleSystemQuad::create( ValueMap& map, SpriteFrame *frame)
- {
- ParticleSystemQuad *ret = new ParticleSystemQuad();
- if (ret && ret->initWithValueMap(map, frame))
- {
- ret->autorelease();
- return ret;
- }
- CC_SAFE_DELETE(ret);
- return ret;
- }
- bool ParticleSystemQuad::initWithValueMap(ValueMap &valueMap, SpriteFrame* frame)
- {
- std::string dirname = "";
- bool ret = false;
- unsigned char *buffer = nullptr;
- unsigned char *deflated = nullptr;
- do
- {
- int maxParticles = valueMap["maxParticles"].asInt();
- // self, not super
- if(this->initWithTotalParticles(maxParticles))
- {
- // Emitter name in particle designer 2.0
- _configName = valueMap["configName"].asString();
- // angle
- _angle = valueMap["angle"].asFloat();
- _angleVar = valueMap["angleVariance"].asFloat();
- // duration
- _duration = valueMap["duration"].asFloat();
- // blend function
- if (_configName.length()>0)
- {
- _blendFunc.src = valueMap["blendFuncSource"].asFloat();
- }
- else
- {
- _blendFunc.src = valueMap["blendFuncSource"].asInt();
- }
- _blendFunc.dst = valueMap["blendFuncDestination"].asInt();
- // color
- _startColor.r = valueMap["startColorRed"].asFloat();
- _startColor.g = valueMap["startColorGreen"].asFloat();
- _startColor.b = valueMap["startColorBlue"].asFloat();
- _startColor.a = valueMap["startColorAlpha"].asFloat();
- _startColorVar.r = valueMap["startColorVarianceRed"].asFloat();
- _startColorVar.g = valueMap["startColorVarianceGreen"].asFloat();
- _startColorVar.b = valueMap["startColorVarianceBlue"].asFloat();
- _startColorVar.a = valueMap["startColorVarianceAlpha"].asFloat();
- _endColor.r = valueMap["finishColorRed"].asFloat();
- _endColor.g = valueMap["finishColorGreen"].asFloat();
- _endColor.b = valueMap["finishColorBlue"].asFloat();
- _endColor.a = valueMap["finishColorAlpha"].asFloat();
- _endColorVar.r = valueMap["finishColorVarianceRed"].asFloat();
- _endColorVar.g = valueMap["finishColorVarianceGreen"].asFloat();
- _endColorVar.b = valueMap["finishColorVarianceBlue"].asFloat();
- _endColorVar.a = valueMap["finishColorVarianceAlpha"].asFloat();
- // particle size
- _startSize = valueMap["startParticleSize"].asFloat();
- _startSizeVar = valueMap["startParticleSizeVariance"].asFloat();
- _endSize = valueMap["finishParticleSize"].asFloat();
- _endSizeVar = valueMap["finishParticleSizeVariance"].asFloat();
- // position
- float x = valueMap["sourcePositionx"].asFloat();
- float y = valueMap["sourcePositiony"].asFloat();
- this->setPosition( Point(x,y) );
- _posVar.x = valueMap["sourcePositionVariancex"].asFloat();
- _posVar.y = valueMap["sourcePositionVariancey"].asFloat();
- // Spinning
- _startSpin = valueMap["rotationStart"].asFloat();
- _startSpinVar = valueMap["rotationStartVariance"].asFloat();
- _endSpin= valueMap["rotationEnd"].asFloat();
- _endSpinVar= valueMap["rotationEndVariance"].asFloat();
- _emitterMode = (Mode) valueMap["emitterType"].asInt();
- // Mode A: Gravity + tangential accel + radial accel
- if (_emitterMode == Mode::GRAVITY)
- {
- // gravity
- modeA.gravity.x = valueMap["gravityx"].asFloat();
- modeA.gravity.y = valueMap["gravityy"].asFloat();
- // speed
- modeA.speed = valueMap["speed"].asFloat();
- modeA.speedVar = valueMap["speedVariance"].asFloat();
- // radial acceleration
- modeA.radialAccel = valueMap["radialAcceleration"].asFloat();
- modeA.radialAccelVar = valueMap["radialAccelVariance"].asFloat();
- // tangential acceleration
- modeA.tangentialAccel = valueMap["tangentialAcceleration"].asFloat();
- modeA.tangentialAccelVar = valueMap["tangentialAccelVariance"].asFloat();
- // rotation is dir
- modeA.rotationIsDir = valueMap["rotationIsDir"].asBool();
- }
- // or Mode B: radius movement
- else if (_emitterMode == Mode::RADIUS)
- {
- if (_configName.length()>0)
- {
- modeB.startRadius = valueMap["maxRadius"].asInt();
- }
- else
- {
- modeB.startRadius = valueMap["maxRadius"].asFloat();
- }
- modeB.startRadiusVar = valueMap["maxRadiusVariance"].asFloat();
- if (_configName.length()>0)
- {
- modeB.endRadius = valueMap["minRadius"].asInt();
- }
- else
- {
- modeB.endRadius = valueMap["minRadius"].asFloat();
- }
- modeB.endRadiusVar = 0.0f;
- if (_configName.length()>0)
- {
- modeB.rotatePerSecond = valueMap["rotatePerSecond"].asInt();
- }
- else
- {
- modeB.rotatePerSecond = valueMap["rotatePerSecond"].asFloat();
- }
- modeB.rotatePerSecondVar = valueMap["rotatePerSecondVariance"].asFloat();
- } else {
- CCASSERT( false, "Invalid emitterType in config file");
- CC_BREAK_IF(true);
- }
- // life span
- _life = valueMap["particleLifespan"].asFloat();
- _lifeVar = valueMap["particleLifespanVariance"].asFloat();
- // emission Rate
- _emissionRate = _totalParticles / _life;
- //don't get the internal texture if a batchNode is used
- if (!_batchNode)
- {
- // Set a compatible default for the alpha transfer
- _opacityModifyRGB = false;
- if (!_configName.empty())
- {
- _yCoordFlipped = valueMap["yCoordFlipped"].asInt();
- }
- }
- setDisplayFrame(frame);
- ret = true;
- }
- } while (0);
- free(buffer);
- free(deflated);
- return ret;
- }
注意,这里只是提供了通过粒子系统属性和纹理创建粒子系统的接口,并没有实现对粒子属性的全局保存(可以参考 Earth Warriors 3D中ParticleManager的实现 )和图片帧的预加载。
粒子属性的获取:
- ValueMap FileUtilsApple::getValueMapFromFile(const std::string& filename);
图片帧的获取(这个获取方式就比较多了。。。):
- SpriteFrame* create(const std::string& filename, const Rect& rect);
3.如何使用?
- auto plistData = FileUtils::getInstance()->getValueMapFromFile("Particles/emissionPart.plist");
- auto emission_frame = SpriteFrame::create("Images/engine.jpg", Rect(0,0,25,32));
- auto emitter = ParticleSystemQuad::create(plistData, emission_frame);
- _background->addChild(_emitter, 10);
4.源码下载
我也不知道3.0release会不会集成这个功能,这里先发出pull request的链接:https://github.com/cocos2d/cocos2d-x/pull/5979/files
【玩转cocos2d-x之三十七】粒子系统的加载优化相关推荐
- QQ 玩一玩获取用户图像昵称以及CocosCreator动态加载网络图片
文章目录 1.CocosCreator 加载图片的几种方式 2.QQ 玩一玩通过openId获取用户图像.昵称 3. 源码 QQ 玩一玩获取用户图像.昵称以及CocosCreator加载图片的几种方式 ...
- 重温CLR(十七)程序集加载和反射
本章主要讨论在编译时对一个类型一无所知的情况下,如何在运行时发现类型的信息.创建类型的实例以及访问类型的成员.可利用本章讲述的内容创建动态可扩展应用程序. 反射使用的典型场景一般是由一家公司创建宿主应 ...
- SAP UI5 应用开发教程之三十七 - 使用 Chrome 开发者工具 Console 面板进行元素审查试读版
一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...
- 轻松玩转树莓派Pico之三、Windows+Ubuntu虚拟机模式下VSCode C语言开发环境搭建
目录 1.VSCode下载与安装 2.VSCode基础插件安装 3.SSH连接与配置 4.SSH免密登录 5.Pico编译 工欲善其事,必先利其器.之前的介绍的Pico流程都是通过命令行编译,没有进行 ...
- MFC学习笔记之三(粒子系统+怪物简单AI+碰撞检测)
到上海找到住的地方之后,干的第一件事,就是抓紧时间学习,为了找到工作努力ing... 备注:以下请参考http://blog.csdn.net/hust_xy/article/details/9374 ...
- Cocos2d之Texture2D类详解之将文件加载成Texture2D对象
一.声明 笔者以cocos2d框架cocos2d-x-3.3rc0版本的源码做分析.本文为笔者原创,允许转载和分享,只要注明文章出处即可. 二.简介 Texture2D类简介 Texture2D类允许 ...
- 【Cocos2d-X(2.x) 游戏开发系列之三】最新版本cocos2d-2.0-x-2.0.2使用资源加载策略
前段时间cocos2dx更新了最新版本cocos2d2.0x2.0.2,也从这个版本开始对于资源加载与管理都改变了策略. 在之前的加载方式都是通过沿用与cocos2d-iphone一样的加载资源 ...
- 征途2无法显示服务器列表,解决win10系统玩征途2提示“DriverCommlnit驱动加载失败”的方法...
征途2是一款众所周知的角色扮演类游戏,它在玩法上延续了征途1的总体风格,但是在画面和音效上比征途1的要提高了很多,其独特的玩法吸引了众多的玩家.但是又部分用户反映,在win10系统上运行征途2的游戏时 ...
- JavaScript玩转机器学习:保存并加载 tf.Model
JavaScript玩转机器学习:保存并加载 tf.Model 保存并加载 tf.Model TensorFlow.js提供了保存和加载模型的功能,这些模型可以是使用LayersAPI创建的或从现有T ...
最新文章
- mybatis源码分析之事务管理器
- druid+spring配置
- 科普篇:贝叶斯网络中的置信度传播
- c++类的应用和权限
- iframe放大显示,如何让iFrame在点击按钮时全屏显示?
- CF#1288A Deadline (函数求最值问题)
- rxjs of操作符里subscribeToArray的实现原理示意图及分析
- SpringMVC配置视图的直接映射view-controller命名空间
- 美国夫妇用数学算法买彩票赢1.74亿元——网友:现在学数学还来得及吗?
- Tensorflow快餐教程(9) - 卷积
- 【Java】选择结构排坑指南
- Java常用接口与类——String类、StringBuffer类、StringBuilder类
- vmclone 问题
- 零基础学python还是c语言-学习汇编还是学习python,自己刚学完C语言,学习那个好呢?...
- 一条语句引发的思考:装箱和拆箱,空指针的类型转换
- servlet到底是什么
- Python程序员的发展前景
- 安徽省二级计算机证书,在哪个网站打印安徽省二级计算机证书?
- JAVA7-6 约分最简分式 (15 分)
- AI应用第一课:支付宝刷脸登录