cocos2d-x 仿真树叶飘落效果的实现
转自:http://blog.csdn.net/ufolr/article/details/7624851
最近项目中需要一个落叶的效果,本来想用粒子特效来实现,但是几经调试,虽然调出了落叶的效果,但是并不是十分理想,最大的不足就是落叶是平面的,没有立体感,虽然把落叶做小之后却是立体感的感觉会有所缓解,但总不能把树叶无限的缩小吧,而且立体感的缺失在粒子特效中确实是一个始终存在的问题。作为一个最求品质的程序猿,最终还是决定自己设精灵动作来实现。
在分析了粒子特效实现的原理并在国内外论坛上爬了半天,最后边实验边修改,终于完成了一个可行的仿真感较强的立体的落叶效果,现在就拿出来跟大家分享一下。
原理->树叶飘落动作分析:
树叶下落过程分解为:下落+摆动+叶片自传。
也就是只要将这三个动作实现,并同时执行就可以实现树叶飘落的效果。
下面就拿出代码具体解析实现过程:
老规矩,先上.h的内容,.h就不多解释了:
#ifndef __LEAF_H__
#define __LEAF_H__ #include "cocos2d.h"
USING_NS_CC; class Leaf : public cocos2d::CCLayer
{
public:
virtual bool init(); void resetLeafPos(CCNode* sender);//叶片位置重置函数
void playLeafAnim(CCSprite *spriteLeaf);//下落过程实现函数 LAYER_NODE_FUNC(Leaf);
}; #endif // __LEAF_H__
接下来是具体的实现,为了我们能不断的产生自然、随和的落叶,我们分三步来完成:
1:第一次初始化;2:落叶动作的实现;3:下落动作完成重新设定落叶开始。
上代码,先看看用到的头文件:
#include <iostream>
#include <ctime>
#include <cstdlib> #include"Leaf.h" using namespace std; enum {TAG_LEAF1 = , TAG_LEAF2};
初始化树叶精灵的设定:
<span style="font-size:12px;">bool Leaf::init()
{
CCSprite *spriteLeaf1 = CCSprite::spriteWithFile("img_yezi_1.png");
spriteLeaf1->setRotation();//旋转角度
spriteLeaf1->setAnchorPoint(ccp(0.5, ));//设置精灵锚点
spriteLeaf1->setPosition(ccp(, ));//叶子1第一次初始位置
spriteLeaf1->setScale(0.5);//设置叶片大小 this->addChild(spriteLeaf1,,TAG_LEAF1);
this->playLeafAnim(spriteLeaf1);//调用play函数播实现叶动作 CCSprite *spriteLeaf2 = CCSprite::spriteWithFile("img_yezi_2.png");
spriteLeaf2->setRotation();
spriteLeaf2->setAnchorPoint(ccp(0.5, ));
spriteLeaf2->setPosition(ccp(, ));
spriteLeaf2->setScale(0.5); this->addChild(spriteLeaf2,,TAG_LEAF2);
this->playLeafAnim(spriteLeaf2); return true;
}</span>
将精灵的锚点设定在其高度的3倍的位置,加上旋转动作后,叶片会产生单摆的动作效果。再加上下落的动作,就会有树叶飘落的感觉了。
<span style="font-size:12px;">//叶子飘落动作
void Leaf::playLeafAnim(CCSprite *spriteLeaf)
{
int iTag = spriteLeaf->getTag(); CCLog("playtag%d", iTag);
ccTime time, roTime;
float fAngle1, fAngle2;
if (iTag == TAG_LEAF1)
{
CCLog("tag1");
time = ;//叶子下落的时间
roTime = 2.5;//叶子单向摆动一次时间
fAngle1 = -;//叶子逆时针摆动角度
fAngle2 = ;//顺时针摆动角度
}
else
{
CCLog("tag2");
time = ;
roTime = 3.2;
fAngle1 = -;
fAngle2 = ;
}
CCLog("rotime%ffAngle1%ffAngle2%f",roTime, fAngle1,fAngle1);
//随机生成叶子横向偏移值
srand((UINT)GetCurrentTime());
int iRandPos = rand() % ;
CCLog("Pianyi%d", iRandPos);
//叶子所运动到的位置
CCMoveTo *moveTo = CCMoveTo::actionWithDuration(time, ccp(CCDirector::sharedDirector()->getWinSize().width - iRandPos, ));
CCCallFuncN *actDone = CCCallFuncN::actionWithTarget(this, callfuncN_selector(Leaf::resetLeafPos));
CCFiniteTimeAction *putdown = CCSequence::actions(moveTo, actDone, NULL);
//叶子旋转动作
CCRotateBy *rotaBy1 = CCRotateBy::actionWithDuration(roTime, fAngle1);
CCRotateBy *rotaBy2 = CCRotateBy::actionWithDuration(roTime, fAngle2); //叶子翻转动作
spriteLeaf->setVertexZ();//设置深度抬高60,避免出现使用CCOrbitCamera实现空间翻转时产生错位和遮挡等问题
//CCDirector::sharedDirector()->setDepthTest(false);
//关闭深度测试同样可以避免上述问题,不过,推荐使用深度设置setVertexZ来正确解决,因为有时你可能需要遮挡的效果,关闭深度测试后将造成遮挡效果的缺失
CCOrbitCamera * orbit = CCOrbitCamera::actionWithDuration(, , , , , , );
//让树叶精灵始终执行三维翻转的动作
CCRepeat *fz3d = CCRepeat::actionWithAction(orbit, -);//无限循环执行叶片翻转的动作
//CCRepeatForever *fz3d = CCRepeatForever::actionWithAction(orbit);
//由于下面使用CCSpawn同时执行动作,所以不可以使用无限次数类型的动作,而因使用有线次数循环CCRepeat将循环次数设置为-1 //用CCEaseInOut包装落叶摆动的动作,让树叶的进入、出现更自然(淡入淡出效果)
CCEaseInOut *ease1 = CCEaseInOut::actionWithAction(rotaBy1, );
CCEaseInOut *ease2 = CCEaseInOut::actionWithAction(rotaBy2, );
//摆动动作合成
CCFiniteTimeAction *seq2 = CCSequence::actions(ease1, ease2, NULL);//依次执行顺时针、逆时针摆动
CCRepeat *baidong = CCRepeat::actionWithAction(seq2, -);//摆动合成 //动作执行->同时执行所有动作
spriteLeaf->runAction(CCSpawn::actions(putdown, baidong, fz3d, NULL)); }</span>
现在叶子飘落的主干就设定完毕了,其实看上去并不复杂,就是三个动作:下落+摆动+翻转,未来使落叶更自然,我们尽可能的在数据可变的范围内使用随机参数,我这里用了系统时间做种子来产生随机数,但是我感觉产生的随机数还是不够理想,如果你有更好的种子,可以告诉我。其实还有很多参数可以在限定范围内使用随机数,由于时间关系我没有逐个去调试,而是直接设定了一个固定值。有时间你可以逐个设定实验,找到最佳的数据范围。
现在为了使我们的落叶能够源源不断的产生,我们还需要让落叶的产生和消亡循环起来:
//重置叶子的位置
void Leaf::resetLeafPos(CCNode* sender)
{
int iTag = int(sender->getTag());//获得被重置叶片的标签
int iZoder = int(sender->getZOrder());//获取被重置叶片的z轴值
sender->removeFromParentAndCleanup(true);//清除已经落到底点的叶子 char sImg[] = "img_yezi_1.png";
_snprintf(sImg, sizeof(sImg), "img_yezi_%d.png", iTag % ); CCPoint pos;
float fAngle;
//随机生成叶子的起始位置
srand((UINT)GetCurrentTime());
int iRand = (rand() % );
if (iTag == TAG_LEAF1)
{
pos = ccp(iRand, );
fAngle = ;
}
else
{
pos = ccp(iRand, );
fAngle = ;
}
//重新生成新的叶片,在起点处释放
CCSprite *spriteLeaf = CCSprite::spriteWithFile(sImg);
spriteLeaf->setScale(0.5);
spriteLeaf->setAnchorPoint(ccp(0.5, ));
spriteLeaf->setRotation(fAngle);
spriteLeaf->setPosition(pos); this->addChild(spriteLeaf, iZoder,iTag);
this->playLeafAnim(spriteLeaf);//重置后的树叶再次执行飘落动作
}
这样3d仿真的落叶的效果就基本实现了,为了节约时间,这里只写了2片叶子的情况,多片叶子的情况可以举一反三,多加几片叶子就行。这里需要注意的是在使用CCOrbitCamera来实现三维空间的翻转时,由于openGL绘图的关系,我们得将精灵的深度设置上浮,以避免openGL绘图时精灵的部分被后面的色彩遮挡。
解决遮挡问题可以直接关闭深度测试CCDirector::sharedDirector()->setDepthTest(false);
也可以设置精灵VertexZ上浮spriteLeaf->setVertexZ(60);
如果你的程序不需要深度测试,你大可以直接关了它,但是你不能确定是的程序是否每个地方都没有用到深度测试,所以,推荐设置VertexZ值来避免你的精灵被遮挡。VertexZ值的大小为你的精灵被挡住部分的像素值。
cocos2d-x 仿真树叶飘落效果的实现的更多相关文章
- <转>cocos2d-x学习笔记(五)仿真树叶飘落效果的实现(精灵旋转、翻转、钟摆运动等综合运用)
转载自ufolr的博客 原文连接:http://blog.csdn.net/ufolr/article/details/7624851 最近项目中需要一个落叶的效果,本来想用粒子特效来实现,但是几经调 ...
- HTML5效果:实现树叶飘落
实现如图所示的东西效果(落叶下落): html代码: <!DOCTYPE html> <html> <head> <title>HTML5树叶飘落动画& ...
- HTML5树叶飘落动画
查看效果:http://keleyi.com/keleyi/phtml/css3/15.htm 请使用Chrome浏览器查看本效果. html源代码: <!DOCTYPE HTML> &l ...
- js实现雪花飘落效果的代码
使用js实现雪花飘落的效果,用html5绘布加js写的雪花飘效果 . 代码: <html> <head> <script> /** * js与html5实现的雪花飘 ...
- 【OpenGL】Shader实例分析(七)- 雪花飘落效果
转发请保持地址:http://blog.csdn.net/stalendp/article/details/40624603 研究了一个雪花飘落效果.感觉挺不错的.分享给大家,效果例如以下: 代码例如 ...
- 简单说 JavaScript实现雪花飘落效果
说明 这次实现的雪花飘落的效果很简单,主要是为了练习练习JavaScript中的定时器,setTimeout 和 setInterval. 效果图 解释setTimeout() setTimeout函 ...
- AJ学IOS(33)UI之Quartz2D雪花飘落效果刷帧
AJ分享,必须精品 效果: 可以加入随机数实现真的飘落效果哦. 代码: -(id)initWithCoder:(NSCoder *)aDecoder { //请注意这里一定要先初始化父类的构造方法 i ...
- Cocos2D v3.4.9粒子效果不能显示的原因分析及解决办法
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 在游戏App中为了衬托气氛我们往往使用一些特殊的图形效果,粒子 ...
- 原生js实现雪花飘落效果
雪花飘落的效果实现步骤:1.使用setInterval定时器每800毫秒创建一个雪花:2.把每一个雪花作为参数传进动态下落的方法中即可. <style> *{padding: 0;marg ...
随机推荐
- 浏览器HTML5支持程度测试
/********************************************************************* * 浏览器HTML5支持程度测试 * 说明: * 想知道对 ...
- django - 替换admin的textarea为 富文本
1. 安装这个:https://github.com/pydanny/django-wysiwyg 2. 下载你希望的 编辑器,到你的指定路径STATIC_ROOT [详细后面补充]
- ORACLE RAC 监听配置 (listener.ora tnsnames.ora)
Oracle RAC 监听器的配置与单实例稍有不同,但原理和实现方法基本上是相同的.在Oracle中 tns进程用于为指定网络地址上的一个或多个Oracle 实例提供服务注册,并响应来自客户端对该服务 ...
- shell 删除日志
一般线上服务的日志都是采用回滚的防止,写一定数量的日志 或是有管理工具定期去转移老旧日志 前几天删除一个测试环境的日志,只保留两天的日志,结果把正在写的日志都给删掉了,不得不重启了服务,经过这一次的错 ...
- [转] TreeList 当前节点图标和背景色设置
高原之上原文TreeList 选中节点时图标状态和背景色 // 给TreeList加SelectImage this.treelArea.SelectImageList = imglCustom; / ...
- [LeetCode] Remove Element 分析
Remove Element算是LeetCode的一道水题,不过这题也有多种做法,现就我所知的几种做一点讨论. 题目链接:https://leetcode.com/problems/remove-el ...
- Canvas入门(1):绘制矩形、圆、直线、曲线等基本图形
来源:http://www.ido321.com/968.html 一.Canvas的基础知识 Canvas是HTML 5中新增的元素,专门用于绘制图形.canvas元素就相当于一块“画布”,一块无色 ...
- JSON 省市数据包括港澳
data: [{ name: "北京", cities: ["西城", "东城", "崇文", "宣武&quo ...
- Spark系列(六)Master注册机制和状态改变机制
各组件的注册流程如下图: 注册机制源码说明: 入口:org.apache.spark.deploy.master文件下的receiveWithLogging方法中的case RegisterAppli ...
- gratitute
韩信帮刘邦夺得天下,最终又得到了什么?姑且不问当初刘邦拜将是何心态?虽然他的所拜之相并不是的那边从芒砀山带下来的哥们或是在沛县时候一起打混的兄弟? 韩信在汉军营得以重用,在项羽处屈其才,此真正的原因在 ...