zoukankan      html  css  js  c++  java
  • cocos2dx 几个精灵依照顺序播放动画解决方法

    我先描写叙述一下这个问题:

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


    我的解决方案是向每张牌都传递一个延时參数,然后在runAction的时候使用DelyTime,可是这样的方法太麻烦。


    如今说说更好的方法吧:

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


    一:

    先在类里定义数据和函数

    std::vector<std::vector<int>> 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);


    以上创建了两个精灵和两个button(还有一个忽略),点击play1那么演员1跳一下,点击play2演员2跳一下。为了实现两个演员不同一时候起跳和记录我们操作的顺序,我们须要在menuCallback里这样写:
    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<int> 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<int > a;
    		a=v_action.at(0);
    		int sprite_tag=a.at(0);
    		int action_tag=a.at(1);
    		std::vector<std::vector<int>>::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,所以想播放其它动画就改函数吧)


    如今看看效果:


    完毕!



  • 相关阅读:
    OpenGL红宝书例3.1 -- glBufferSubData使用
    JNI调用问题(部分机型崩溃)
    文件编码转换工具
    vs2013安装visual assist和viemu之后提示功能等无效解决
    cocos2d-lua SDK接入
    OpenGL中shader读取实现
    CURL C++网络延时或者最低网速下载设置
    Spring框架
    软件安装方式
    Web前端常见问题
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6923029.html
Copyright © 2011-2022 走看看