• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

chchpd

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

cocos2dx --- Action综合应用一:落叶效果

转载:http://blog.csdn.net/ufolr/article/details/7624851  ufolr

仿真感较强的立体的落叶效果

思路:

  落叶动作分解:下落+摆动+自转。最后同时执行。

实现:

 1 class Leaf : public cocos2d::CCLayer
 2 {
 3 public:
 4     virtual bool init();
 5 
 6     void resetLeafPos(CCNode* sender);//叶片位置重置函数
 7     void playLeafAnim(CCSprite *spriteLeaf);//下落过程实现函数
 8 
 9     LAYER_NODE_FUNC(Leaf);
10 };
 1 bool Leaf::init()
 2 {
 3     CCSprite *spriteLeaf1 = CCSprite::spriteWithFile("img_yezi_1.png");
 4     spriteLeaf1->setRotation(30);//旋转角度
 5     spriteLeaf1->setAnchorPoint(ccp(0.5, 3));//设置精灵锚点
 6     spriteLeaf1->setPosition(ccp(450, 500));//叶子1第一次初始位置
 7     spriteLeaf1->setScale(0.5);//设置叶片大小
 8 
 9     this->addChild(spriteLeaf1,100,TAG_LEAF1);
10     this->playLeafAnim(spriteLeaf1);//调用play函数播实现叶动作
11      
12     CCSprite *spriteLeaf2 = CCSprite::spriteWithFile("img_yezi_2.png");
13     spriteLeaf2->setRotation(50);
14     spriteLeaf2->setAnchorPoint(ccp(0.5, 3));
15     spriteLeaf2->setPosition(ccp(200, 540));
16     spriteLeaf2->setScale(0.5);
17 
18     this->addChild(spriteLeaf2,101,TAG_LEAF2);
19     this->playLeafAnim(spriteLeaf2);
20 
21     return true;
22 }

将精灵的锚点设定在其高度的3倍的位置,加上旋转动作后,叶片会产生单摆的动作效果。再加上下落的动作,就会有树叶飘落的感觉。

 1 //叶子飘落动作
 2 void Leaf::playLeafAnim(CCSprite *spriteLeaf)
 3 {
 4     int iTag = spriteLeaf->getTag();
 5      
 6     CCLog("playtag%d", iTag);
 7     float fromtime, roTime;
 8     float fAngle1, fAngle2;
 9     if (iTag == TAG_LEAF1)
10     {
11         CCLog("tag1");
12         fromtime= 10;//叶子下落的时间
13         roTime = 2.5;//叶子单向摆动一次时间
14         fAngle1 = -80;//叶子逆时针摆动角度
15         fAngle2 = 80;//顺时针摆动角度
16     }
17     else
18     {
19         CCLog("tag2");
20         fromtime= 14;
21         roTime = 3.2;
22         fAngle1 = -100;
23         fAngle2 = 100;
24     }
25     CCLog("rotime%ffAngle1%ffAngle2%f",roTime, fAngle1,fAngle1);
26     //随机生成叶子横向偏移值
27     srand((unsigned)time());
28     int iRandPos = rand() % 250;
29     CCLog("Pianyi%d", iRandPos);
30     //叶子所运动到的位置
31     CCMoveTo *moveTo = CCMoveTo::actionWithDuration(time, ccp(CCDirector::sharedDirector()->getWinSize().width - iRandPos, 30));
32     CCCallFuncN *actDone = CCCallFuncN::actionWithTarget(this, callfuncN_selector(Leaf::resetLeafPos));
33     CCFiniteTimeAction *putdown = CCSequence::actions(moveTo, actDone, NULL);
34     //叶子旋转动作
35     CCRotateBy *rotaBy1 = CCRotateBy::actionWithDuration(roTime, fAngle1);
36     CCRotateBy *rotaBy2 = CCRotateBy::actionWithDuration(roTime, fAngle2);
37 
38     //叶子翻转动作
39     spriteLeaf->setVertexZ(60);//设置深度抬高60,避免出现使用CCOrbitCamera实现空间翻转时产生错位和遮挡等问题
40     //CCDirector::sharedDirector()->setDepthTest(false);
41     //关闭深度测试同样可以避免上述问题,不过,推荐使用深度设置setVertexZ来正确解决,因为有时你可能需要遮挡的效果,关闭深度测试后将造成遮挡效果的缺失
42     CCOrbitCamera * orbit = CCOrbitCamera::actionWithDuration(8, 1, 0, 0, 360, 45, 0);
43     //让树叶精灵始终执行三维翻转的动作
44     CCRepeat *fz3d = CCRepeat::actionWithAction(orbit, -1);//无限循环执行叶片翻转的动作
45     //CCRepeatForever *fz3d = CCRepeatForever::actionWithAction(orbit);
46     //由于下面使用CCSpawn同时执行动作,所以不可以使用无限次数类型的动作,而因使用有线次数循环CCRepeat将循环次数设置为-1
47     
48     //用CCEaseInOut包装落叶摆动的动作,让树叶的进入、出现更自然(淡入淡出效果)
49     CCEaseInOut *ease1 = CCEaseInOut::actionWithAction(rotaBy1, 3);
50     CCEaseInOut *ease2 = CCEaseInOut::actionWithAction(rotaBy2, 3);
51     //摆动动作合成
52     CCFiniteTimeAction *seq2 = CCSequence::actions(ease1, ease2, NULL);//依次执行顺时针、逆时针摆动
53     CCRepeat *baidong = CCRepeat::actionWithAction(seq2, -1);//摆动合成
54 
55     //动作执行->同时执行所有动作
56     spriteLeaf->runAction(CCSpawn::actions(putdown, baidong, fz3d, NULL));
57     
58 }

 现在叶子飘落的主干就设定完毕了,其实看上去并不复杂,就是三个动作:下落+摆动+翻转,为了使落叶更自然,我们尽可能的在数据可变的范围内使用随机参数,这里用了系统时间做种子来产生随机数,但是我感觉产生的随机数还是不够理想,如果你有更好的种子,可以告诉我。其实还有很多参数可以在限定范围内使用随机数,由于时间关系我没有逐个去调试,而是直接设定了一个固定值。有时间你可以逐个设定实验,找到最佳的数据范围。现在为了使我们的落叶能够源源不断的产生,我们还需要让落叶的产生和消亡循环起来:

 1 //重置叶子的位置
 2 void Leaf::resetLeafPos(CCNode* sender)
 3 {
 4     int iTag = int(sender->getTag());//获得被重置叶片的标签
 5     int iZoder = int(sender->getZOrder());//获取被重置叶片的z轴值
 6     sender->removeFromParentAndCleanup(true);//清除已经落到底点的叶子
 7      
 8     char sImg[15] = "img_yezi_1.png";
 9     snprintf(sImg, sizeof(sImg), "img_yezi_%d.png", iTag % 100);
10 
11     CCPoint pos;
12     float fAngle;
13     //随机生成叶子的起始位置
14     srand((unsigned)time());
15     int iRand = (rand() % 200);
16     if (iTag == TAG_LEAF1)
17     {
18         pos = ccp(iRand, 600);
19         fAngle = 30;
20     }
21     else
22     {
23         pos = ccp(iRand, 570);
24         fAngle = 50;
25     }
26     //重新生成新的叶片,在起点处释放
27     CCSprite *spriteLeaf = CCSprite::spriteWithFile(sImg);
28     spriteLeaf->setScale(0.5);
29     spriteLeaf->setAnchorPoint(ccp(0.5, 3));
30     spriteLeaf->setRotation(fAngle);
31     spriteLeaf->setPosition(pos);
32 
33     this->addChild(spriteLeaf, iZoder,iTag);
34     this->playLeafAnim(spriteLeaf);//重置后的树叶再次执行飘落动作
35 }

这样3d仿真的落叶的效果就基本实现了,为了节约时间,这里只写了2片叶子的情况,多片叶子的情况可以举一反三,多加几片叶子就行。这里需要注意的是在使用CCOrbitCamera来实现三维空间的翻转时,由于openGL绘图的关系,我们得将精灵的深度设置上浮,以避免openGL绘图时精灵的部分被后面的色彩遮挡。解决遮挡问题可以直接关闭深度测试CCDirector::sharedDirector()->setDepthTest(false);也可以设置精灵VertexZ上浮spriteLeaf->setVertexZ(60);如果你的程序不需要深度测试,你大可以直接关了它,但是你不能确定是的程序是否每个地方都没有用到深度测试,所以,推荐设置VertexZ值来避免你的精灵被遮挡。VertexZ值的大小为你的精灵被挡住部分的像素值。

posted on 2013-05-07 17:03  chchpd  阅读(1399)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3