我先描写叙述一下这个问题:
拿之前做的卡牌游戏来说。假设一方场上有3张牌,那么肯定要以一种顺序来播放攻击动画。我是以从左到右的方式。
我的解决方案是向每张牌都传递一个延时參数,然后在runAction的时候使用DelyTime,可是这样的方法太麻烦。
如今说说更好的方法吧:
基本思路是vector与callfunc相结合。
一:
先在类里定义数据和函数
std::vector> v_action;//储存精灵TAG和动画TAG的容器
void push_action(int sprite_tag,int action_tag);//加入动作序列
void run_action(int sprite_tag,int action_tag);//播放动作
void next_action();//下一个动作
Sequence* run(int action_tag);//依据TAG返回动作
bool isRunAction;//是否正在播放动作
二:
在init初始化參数
//还没有播放动作
isRunAction=false;
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
//演员一
auto actor1 = Sprite::create("CloseNormal.png");
actor1->setTag(11);
actor1->setPosition(250,visibleSize.height/2);
this->addChild(actor1,2);
//演员二
auto actor2 = Sprite::create("CloseNormal.png");
actor2->setTag(22);
actor2->setPosition(300,visibleSize.height/2);
this->addChild(actor2,2);
//演员一跳跃
auto play1 = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCallback, this));
play1->setTag(1);
play1->setPosition(250,visibleSize.height/5);
//演员二跳跃
auto play2 = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCallback, this));
play2->setTag(2);
play2->setPosition(300,visibleSize.height/5);
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));
// create menu, it's an autorelease object
auto menu = Menu::create(play1,play2,closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);
void HelloWorld::menuCallback(Ref* pSender)
{
auto menuItem = (MenuItemImage*)pSender;
Sprite* actor;
switch (menuItem->getTag())
{
case 1:
push_action(11,1);
break;
case 2:
push_action(22,1);
break;
default:
break;
}
}
这里使用了push_action函数,作用是播放动作或者将操作存入容器:
void HelloWorld::push_action(int sprite_tag,int action_tag)
{
if(isRunAction==false)//假设没有在播放动作,那么直接播放此动作
{
isRunAction=true;
run_action(sprite_tag,action_tag);
}
else//假设正在播放,那么将此动作存入容器
{
std::vector v_sprite;
v_sprite.push_back(sprite_tag);
v_sprite.push_back(action_tag);
v_action.push_back(v_sprite);
}
}
凝视已经比較具体了~
我们先看看run_action函数里面有什么吧:void HelloWorld::run_action(int sprite_tag,int action_tag)
{
auto actor = (Sprite*)getChildByTag(sprite_tag);
auto squence = Sequence::create(run(action_tag),
CallFunc::create(this,callfunc_selector(HelloWorld::next_action)),
NULL);
actor->runAction(squence);
}
函数的作用是依据传入的两个tag播放动作,然后调用next_action:
void HelloWorld::next_action()
{
if(v_action.empty())
{
isRunAction=false;
}
else
{
std::vector a;
a=v_action.at(0);
int sprite_tag=a.at(0);
int action_tag=a.at(1);
std::vector>::iterator it = v_action.begin();
v_action.erase(it);
run_action(sprite_tag,action_tag);
}
}
假设容器里没有数据则说明接下来没有动作能够播放了,则把isRunAction赋为false,下次就能够直接播放动作。
假设容器里有数据。我们先把这项数据取出然后删除它。然后再调用run_action。
最后我们看看run里面有什么吧:
Sequence* HelloWorld::run(int action_tag)
{
switch (action_tag)
{
case 1:
return Sequence::create(MoveBy::create(0.2,Vec2(0,100)),
MoveBy::create(0.2,Vec2(0,-100)),
NULL);
default:
break;
}
}
非常easy,就是一个动作。当然我们能够依据须要添加。(注意返回參数是Sequence,所以想播放其它动画就改函数吧)
如今看看效果:
完毕!