cocos2dx 几个精灵按照顺序播放动画解决方法

前端之家收集整理的这篇文章主要介绍了cocos2dx 几个精灵按照顺序播放动画解决方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我先描述一下这个问题:

拿之前做的卡牌游戏来说,如果一方场上有3张牌,那么肯定要以一种顺序来播放攻击动画,我是以从左到右的方式。


我的解决方式是向每张牌都传递一个延时参数,然后在runAction的时候使用DelyTime,但是这种方法太麻烦!


现在说说更好的方法吧:

基本思路是vector与callfunc相结合。


一:

先在类里定义数据和函数

  1. std::vector<std::vector<int>> v_action;//储存精灵TAG和动画TAG的容器
  2.  
  3. void push_action(int sprite_tag,int action_tag);//添加动作序列
  4. void run_action(int sprite_tag,int action_tag);//播放动作
  5. void next_action();//下一个动作
  6.  
  7. Sequence* run(int action_tag);//根据TAG返回动作
  8.  
  9. bool isRunAction;//是否正在播放动作

二:

在init初始化参数

  1. //还没有播放动作
  2. isRunAction=false;
  3. Size visibleSize = Director::getInstance()->getVisibleSize();
  4. Vec2 origin = Director::getInstance()->getVisibleOrigin();
  5. //演员一
  6. auto actor1 = Sprite::create("CloseNormal.png");
  7. actor1->setTag(11);
  8. actor1->setPosition(250,visibleSize.height/2);
  9. this->addChild(actor1,2);
  10. //演员二
  11. auto actor2 = Sprite::create("CloseNormal.png");
  12. actor2->setTag(22);
  13. actor2->setPosition(300,visibleSize.height/2);
  14. this->addChild(actor2,2);
  15. //演员一跳跃
  16. auto play1 = MenuItemImage::create(
  17. "CloseNormal.png","CloseSelected.png",CC_CALLBACK_1(HelloWorld::menuCallback,this));
  18. play1->setTag(1);
  19. play1->setPosition(250,visibleSize.height/5);
  20. //演员二跳跃
  21. auto play2 = MenuItemImage::create(
  22. "CloseNormal.png",this));
  23. play2->setTag(2);
  24. play2->setPosition(300,visibleSize.height/5);
  25. auto closeItem = MenuItemImage::create(
  26. "CloseNormal.png",CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));
  27. closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2,origin.y + closeItem->getContentSize().height/2));
  28.  
  29. // create menu,it's an autorelease object
  30. auto menu = Menu::create(play1,play2,closeItem,NULL);
  31. menu->setPosition(Vec2::ZERO);
  32. this->addChild(menu,1);


以上创建了两个精灵和两个按钮(另一个忽略),点击play1那么演员1跳一下,点击play2演员2跳一下。为了实现两个演员不同时起跳和记录我们操作的顺序,我们需要在menuCallback里这样写:
  1. void HelloWorld::menuCallback(Ref* pSender)
  2. {
  3. auto menuItem = (MenuItemImage*)pSender;
  4. Sprite* actor;
  5. switch (menuItem->getTag())
  6. {
  7. case 1:
  8. push_action(11,1);
  9. break;
  10. case 2:
  11. push_action(22,1);
  12. break;
  13. default:
  14. break;
  15. }
  16. }

这里使用了push_action函数,作用是播放动作或者将操作存入容器:
  1. void HelloWorld::push_action(int sprite_tag,int action_tag)
  2. {
  3. if(isRunAction==false)//如果没有在播放动作,那么直接播放此动作
  4. {
  5. isRunAction=true;
  6. run_action(sprite_tag,action_tag);
  7. }
  8. else//如果正在播放,那么将此动作存入容器
  9. {
  10. std::vector<int> v_sprite;
  11. v_sprite.push_back(sprite_tag);
  12. v_sprite.push_back(action_tag);
  13. v_action.push_back(v_sprite);
  14.  
  15. }
  16. }

注释已经比较详细了~

我们先看看run_action函数里面有什么吧:
  1. void HelloWorld::run_action(int sprite_tag,int action_tag)
  2. {
  3. auto actor = (Sprite*)getChildByTag(sprite_tag);
  4. auto squence = Sequence::create(run(action_tag),CallFunc::create(this,callfunc_selector(HelloWorld::next_action)),NULL);
  5. actor->runAction(squence);
  6. }

函数的作用是根据传入的两个tag播放动作,然后调用next_action:
  1. void HelloWorld::next_action()
  2. {
  3. if(v_action.empty())
  4. {
  5. isRunAction=false;
  6. }
  7. else
  8. {
  9. std::vector<int > a;
  10. a=v_action.at(0);
  11. int sprite_tag=a.at(0);
  12. int action_tag=a.at(1);
  13. std::vector<std::vector<int>>::iterator it = v_action.begin();
  14. v_action.erase(it);
  15. run_action(sprite_tag,action_tag);
  16. }
  17. }

如果容器里没有数据则说明接下来没有动作可以播放了,则把isRunAction赋为false,下次就可以直接播放动作。

如果容器里有数据,我们先把这项数据取出然后删除它,然后再调用run_action。

最后我们看看run里面有什么吧:

  1. Sequence* HelloWorld::run(int action_tag)
  2. {
  3. switch (action_tag)
  4. {
  5. case 1:
  6. return Sequence::create(MoveBy::create(0.2,Vec2(0,100)),MoveBy::create(0.2,-100)),NULL);
  7. default:
  8. break;
  9. }
  10. }

很简单,就是一个动作,当然我们可以根据需要增加。(注意返回参数是Sequence,所以想播放其他动画就改函数吧)


现在看看效果


完成!

猜你在找的Cocos2d-x相关文章