• Cocos2d-x 动画

    2018-08-28 10:32:46
    Cocos2d-x动画 声明:本文分析的是cocos2d-x-3.12的代码 游戏中动画可以分为两类,帧动画和骨骼动画。帧动画由一张一张的完整的动画图片组成,骨骼动画由一张张分散的局部动画“拼凑”而成,动作由一个配置文件...

    Cocos2d-x动画

    声明:本文分析的是cocos2d-x-3.12的代码

    游戏中动画可以分为两类,帧动画和骨骼动画。帧动画由一张一张的完整的动画图片组成,骨骼动画由一张张分散的局部动画“拼凑”而成,动作由一个配置文件控制。cocos2d支持这两种动画。

     

    帧动画

    Cocos将帧动画设置成一个延时动作(IntervalAction),精灵Sprite只需要运行一个动作就可以显示帧动画。帧动画的类图大致如下:

     

    帧动画封装再Animation类中,Animation类中有一个数组Vector<AnimationFrame*> _frames

    ,存放了帧动画的每一帧。AnimationFrame类是帧动画的一帧,每一帧的纹理保存在SpriteFrame *_spriteFrame变量中,另外还有一个变量float AnimationFrame::_delayUnits,这个变量保存是该帧需要停留的多少个时间单位,不是具体的时间,时间单位由Animation类的float _delayPerUnit变量控制。一个帧具体的停留时间为delayUnits*delayPerUnit

    这样设计有一个好处,可以很方便的控制动画的播放速度,只需要更改Animation::_delayPerUnit就可以。

     

    要让一个帧动画显示出来,需要先创建一个Animate延时动作,然后让Sprite类执行Animate动作。

     

    AnimationCache类可以缓存已经加载过的动画,后面再做详细讨论。

     

    帧动画的创建

    创建一个帧动画的过程大致如下,

     

     

    代码如下:

       

    //加载帧动画资源
        SpriteFrameCache::getInstance()->addSpriteFramesWithFile("friend-zombie.plist");
        //创建这动画的所有帧
        Vector<AnimationFrame*>SpFrs;
        chartemp[50]= { 0 };
        for(inti= 1; i < 64; ++i)
        {
            snprintf(temp, sizeof(temp)/ sizeof(char),"friend-zombie-01-%04d.png", i);
            SpFrs.pushBack(AnimationFrame::create(SpriteFrameCache::getInstance()->getSpriteFrameByName(temp),1, ValueMap()));
        }
        //创建帧动画
        autoanimation= Animation::create(SpFrs,0.1, 1000);
        //创建帧动画动作
        autoanimate= Animate::create(animation);
        autosp2= Sprite::create();
        sp2->setPosition(150, 200);
        //运行动画
        sp2->runAction(animate);

     

     

     

     

    Animation创建函数

    static Animation*create(constVector<AnimationFrame*>&arrayOfAnimationFrameNames,floatdelayPerUnit,unsigned intloops= 1);

    static Animation*createWithSpriteFrames(constVector<SpriteFrame*>&arrayOfSpriteFrameNames,floatdelay= 0.0f,unsigned intloops= 1);

    创建函数可以通过一个AnimationFrame数组或SpriteFrame数组创建,使用SpriteFrame数组会将每一帧停留的时间单位设置为1。

    参数delay,代表每个时间单位的具体时间,单位为秒。

    参数loops,动画循环的次数。

     

    帧事件

    在播放帧动画时,有时需要在播放到某一帧或者结束时执行一些操作,Cocos绘制帧时可以发送一个EventCustom自定义事件,事件名用以下宏定义

    #define  AnimationFrameDisplayedNotification "CCAnimationFrameDisplayedNotification"

    事件是否发送取决于帧对应的AnimationFrame类中的ValueMap _userInfo变量,如果该Map变量不为空这会将该变量作为自定义事件的额外参数发送自定义事件。例如:

       

    AnimationFrame*f= AnimationFrame::create(spriteframe,1,ValueMap());
        f->getUserInfo().insert(std::make_pair("Finish",Value("finish")));
     
        ...//用 f 创建一个Animation
    auto l= EventListenerCustom::create(AnimationFrameDisplayedNotification,[](EventCustom* e){
            constValueMap*vm= static_cast<cocos2d::AnimationFrame::DisplayedEventInfo*>(e->getUserData())->userInfo;
     
            log("%s, %s",vm->begin()->first.c_str(), vm->begin()->second.asString().c_str());
        });
    _eventDispatcher->addEventListenerWithFixedPriority(l,1);

     

     

     

    AnimationCache

    AnimationCache是一个动画缓存类,该类的Map<std::string,Animation*>_animations变量存放了已加载的动画,Key存放的是动画的名字,这个名字可以任意。

     

    可以通过以下函数将一个已创建的Animation添加到缓存中

    void AnimationCache::addAnimation(Animation *animation,const std::string &name)

     

    AnimationCache支持读取配置文件添加动画,这样可以简化帧动画的创建。Animation支持两种配置文件格式,都是XML文件进行配置,一种是简单模式,一种相对复杂。

     

    简单模式的配置

     

    <?xml version="1.0"encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC"-//Apple//DTD PLIST 1.0//EN""http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
             <key>animations</key>
             <dict>
                       <key>walkFront</key>
                       <dict>
                                <key>delay</key>
                                <real>0.2</real>
                                <key>frames</key>
                                <array>
                                         <string>friend-zombie-01-0000.png</string>
                                         <string>friend-zombie-01-0001.png</string>
                                         <string>friend-zombie-01-0002.png</string>
                                         <string>friend-zombie-01-0003.png</string>
                                         <string>friend-zombie-01-0004.png</string>
                                         <string>friend-zombie-01-0005.png</string>
                                         <string>friend-zombie-01-0006.png</string>
                                         <string>friend-zombie-01-0007.png</string>
                                </array>
                       </dict>
             </dict>
    </dict>
    </plist>

     

     

     

     

    这种模式和Animation::initWithSpriteFrames函数类似,只是指定了一组SpriteFrame名字,这个名字时存储在SpriteFrameCache中的名字,所以添加动画前需要先用SpriteFrameCache加载好所有的帧,创建的帧动画时每帧都用一个时间单位,循环次数也为1。例:

        //必须先加载好图片资源
        SpriteFrameCache::getInstance()->addSpriteFramesWithFile("friend-zombie.plist");
        AnimationCache::getInstance()->addAnimationsWithFile("animations.plist");
        autosp1= Sprite::create();
        sp1->setPosition(150, 200);
        autoanimation= AnimationCache::getInstance()->getAnimation("walkFront");
        sp1->runAction(Animate::create(animation));
    

     

     

     

     

    复杂配置格式

     

    <?xml version="1.0"encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC"-//Apple//DTD PLIST 1.0//EN""http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
             <key>animations</key>
             <dict>
                       <key>WalkRight</key>
                       <dict>
                                <key>delayPerUnit</key>
                                <real>0.2</real>
                                <key>restoreOriginalFrame</key>
                                <true/>
                                <key>loops</key>
                                <integer>200</integer>
                                <key>frames</key>
                                <array>
                                         <dict>
                                                   <key>spriteframe</key>
                                                   <string>friend-zombie-01-0008.png</string>
                                                   <key>delayUnits</key>
                                                   <integer>1</integer>
                                                   <key>notification</key>
                                                   <dict>
                                                            <key>firstframe</key>
                                                            <true/>
                                                   </dict>
                                         </dict>
                                         <dict>
                                                   <key>spriteframe</key>
                                                   <string>friend-zombie-01-0009.png</string>
                                                   <key>delayUnits</key>
                                                   <integer>1</integer>
                                         </dict>
                                         <dict>
                                                   <key>spriteframe</key>
                                                   <string>friend-zombie-01-0010.png</string>
                                                   <key>delayUnits</key>
                                                   <integer>1</integer>
                                         </dict>
                                         <dict>
                                                   <key>spriteframe</key>
                                                   <string>friend-zombie-01-0011.png</string>
                                                   <key>delayUnits</key>
                                                   <integer>1</integer>
                                         </dict>
                                         <dict>
                                                   <key>spriteframe</key>
                                                   <string>friend-zombie-01-0012.png</string>
                                                   <key>delayUnits</key>
                                                   <integer>1</integer>
                                         </dict>
                                         <dict>
                                                   <key>spriteframe</key>
                                                   <string>friend-zombie-01-0013.png</string>
                                                   <key>delayUnits</key>
                                                   <integer>1</integer>
                                         </dict>
                                         <dict>
                                                   <key>spriteframe</key>
                                                   <string>friend-zombie-01-0014.png</string>
                                                   <key>delayUnits</key>
                                                   <integer>1</integer>
                                         </dict>
                                         <dict>
                                                   <key>spriteframe</key>
                                                   <string>friend-zombie-01-0015.png</string>
                                                   <key>delayUnits</key>
                                                   <integer>1</integer>
                                         </dict>
                                </array>
                       </dict>
             </dict>
             <key>properties</key>
             <dict>
                       <key>spritesheets</key>
                       <array>
                                <string>friend-zombie.plist</string>
                       </array>
                       <key>format</key>
                       <integer>2</integer>
             </dict>
    </dict>
    </plist>

     

     

    这种配置格式可以配置每一帧的参数类似于Animation::initWithAnimationFrames函数,可以配置循环次数,每一帧的单位时间,也可以通过<key>notification</key>配置帧事件。这种格式可以在<key>properties</key>中配置好帧所在的plist文件,添加动画前会先加载plist文件,所以不用手动加载plist文件。例:

       

     

        AnimationCache::getInstance()->addAnimationsWithFile("animations2.plist");
        autosp1= Sprite::create();
        sp1->setPosition(150, 200);
        autoanimation= AnimationCache::getInstance()->getAnimation("WalkRight");
        sp1->runAction(Animate::create(animation));

     

     

    骨骼动画Spine

    Cocos支持Spine的骨骼动画,Spine骨骼动画由各个小图片组成的大纹理,一个纹理配置文件,一个动画配置文件组成。

    纹理是由各个动画里的组件构成,如手、脚等等

    纹理配置记录了每个组件在大纹理里面的位置。

    动画配置文件,该文件为一个Jason文件,记录了各个时刻个组件的位置

     

    Cocos中Spine骨骼动画有一个单独的工程libSpine,这个工程由对骨骼动画的实现。要使用骨骼动画必须包含头文件#include"spine/spine-cocos2dx.h",骨骼动画所在的命名空间为spine

    骨骼动画的类为SkeletonAnimation

     

    创建骨骼动画

    static SkeletonAnimationSkeletonAnimation::createWithFile (const std::stringskeletonDataFile,const std::stringatlasFile,floatscale= 1);

    skeletonDataFile:动画配置文件

    atlasFile:纹理配置文件

     

    spTrackEntrysetAnimation(int trackIndex,const std::string&name,boolloop);

    spTrackEntry*  addAnimation (int trackIndex,const std::stringnameboolloopfloatdelay= 0);

    trackIndex动画管道,一般用0,只有一个动画管道,可以设置多个,这样会同时播放多个动画。可以把头和身体分开,使用两个管道,这样头和身体可以单独控制。

    name动画的名字

    loop是否循环播放,如果设为ture后续在添加的动画则不会播放

    delay延迟多次时间播放

    例:

    SkeletonAnimation*node=SkeletonAnimation::createWithFile("JXM.json","JXM.atlas",0.5f);

    auto track=node->setAnimation(0,"in",false);//设置0好管道的第一个动画,

    auto track1=node->addAnimation(0,"clk_1",true,1);// 0号管道后面来添加,用add

     

    动画事件

     

    //当管道中动画切换到另一个动画时调用,管道内第一个动画不会调用

    void setStartListener(const StartListener&  listener);

    //管道中有动画完成播放时调用

    void setEndListener(const EndListener&  listener);

    //管道中最后一个动画完成一次调用,最后一个为循环动画时会多次调用

    void setCompleteListener(const CompleteListenerlistener);

    //动画中内部有事件发生

    void setEventListener(const EventListenerlistener);

    例如(设置了15秒后会结束动画):

     

    SkeletonAnimation* node=SkeletonAnimation::createWithFile("JXM.json","JXM.atlas",0.5f);
    autotrack= node->setAnimation(0,"in", false); //设置0好管道的第一个动画,
    autotrack1= node->addAnimation(0,"clk_1", false,0.3); // 往0号管道后面来添加,用add
    autotrack2= node->addAnimation(0,"clk_1", true,1); 
    node->setStartListener([](intn){ log("setStartListener%d", n); });
    node->setEndListener([](intn){ log("setEndListener%d", n); });
    node->setCompleteListener([](intn,intl){ log("setCompleteListener%d, %d", n, l);});

     

    结果:

     

     

    spTrackEntry*entrysetAnimation或addAnimation的返回值

    //切换到动画时调用,管道内第一个动画不会调用

    void  setTrackStartListener(spTrackEntry*entry,const StartListener&listener);

    //管道中有动画结束

    void  setTrackEndListener(spTrackEntry*entry,const EndListener&listener);

    //最后一个动画完成一次,最后一个为循环动画时会多次调用

    void  setTrackCompleteListener(spTrackEntry*entry,const CompleteListener&listener);

    //动画中有事件发生

    void  setTrackEventListener(spTrackEntry*entry,const EventListener&listener);

     

    事件函数的调用总是先调用TrackXXXListener,然调用XXXXListener函数。

     

    结束骨骼动画

    以下两个函数,可以结束骨骼动画:

        voidSkeletonAnimation::clearTracks ();

        voidSkeletonAnimation::clearTrack (inttrackIndex= 0);

     

    非循环播放的动画可以在EndListener中直接删除如动画节点。果循环播放的动画要结束,然后删除动画,可以在setCompleteListener事件中调用clearTracks/ clearTrack函数,然后移除节点。

    不能在setTrackCompleteListener事件中调用clearTracks函数,因为在调用clearTracks/ clearTrack函数时,释放Track中所有数据,包括listener的Lambda表达式,当程序运行setCompleteListener中的CompleteListener的lambada表达式时,会导致崩溃。

    也不能在EndListener事件和TrackEndListener事件中调用clearTracks/ clearTrack函数这个函数内部会调用EndListener/TrackEndListener,从而导致死循环。

    例:

     

        autotrack= node->setAnimation(0,"out", false);
        node->setCompleteListener([node](intn,intl){
            log("leave %d, %d", n,l);
            node->clearTrack(0);         
            node->retain();//还在执行node节点的代码,对象不能被释放
            node->autorelease();//加入释放池,绘制完节点后再释放。
            node->removeFromParent();});

     

     

     

    展开全文
  • 你可以通过一系列图片文件,像如下这样,创建一个动画: CCAnimation *animation = CCAnimation::create(); //从本地文件系统中加载图片文件到CCSpriteFrame中区,然后添加到CCAnimation中 for (int i = 1; i ; i+...

    qinning199原创,欢迎转载,转载请注明:http://www.cocos2dx.net/?p=22

    一、帧动画

    你可以通过一系列图片文件,像如下这样,创建一个动画:
    	CCAnimation *animation = CCAnimation::create();
    	//从本地文件系统中加载图片文件到CCSpriteFrame中区,然后添加到CCAnimation中
    	for (int i = 1; i < 15; i++)
    	{
    		char szImageFileName[128] = {0};
    		sprintf(szImageFileName, "Images/grossini_dance_%02d.png", i);
    		animation->addSpriteFrameWithFileName(szImageFileName);  
    	}
    	animation->setDelayPerUnit(2.8f / 14.0f); // 这个动画包含14帧,将会持续2.8秒.
    	animation->setRestoreOriginalFrame(true); // 14帧播放完之后返回到第一帧
    	
    	CCAnimate *action = CCAnimate::create(animation);
    	sprite->runAction(action);  // 运行精灵对象



    注意CCAnimation是由许多精灵帧组成,可以设置间隔时间,持续时间等,它实际上是包含着一组数据。CCAnimate是一个动作,它是通过CCAnimation对象创建。
    二、精灵表动画
    尽管手工动画很容易理解,但它很少用在游戏开发中。相反的,精灵表动画的方式在2D动画中经常使用。
    这是一个精灵表。它实际上就是一系列动画帧图片,或者是一个能用于一个场景的图片集。


    在OpenGLES1.1阶段,精灵表因为以下几点被广泛应用:
    1、减少文件读写时间。读取一张图片比读取一堆小文件肯定要快。
    2、减少内存消耗。OpenGL ES 1.1仅仅能够使用2的几次方大小的图片(也就是宽度或者高度是2,4,864,128,256,512,1024,...)。也就是说,OpenGL ES1.1将会分配给每个图片2的几次方大小的内存空间,即使你这张图片达不到这样的宽度和高度也会分配大于此图片的2的n次方大小的空间。那么运用这种图片集的方式将会减少内存碎片。
    3、减少OpenGL ES绘制调用并且加速渲染。
    Cocos2d-x v2.0升级到了OpenGL ES2.0.OpenGL ES2.0不会再分配2的几次方的内存块了,但是减少读取时间和绘制调用的优势依然存在。
    那么生成的动画效果如何呢?正如我们所见,精灵表不是动画的一个必须条件。但是考虑到以上的一些优势,精灵表还是很有效率的。在Cocos2dx中,有许多不同的方式来创建精灵表。
    三、通过.png 和 .plist文件创建精灵表
    在cocos2dx 0.x和1.x版本中,CCSpriteSheet就是为以上的目的设计。在V2.0中CCSpriteBatchNode替代了CCSpriteSheet。
    CCSpriteBatchNode对象包含了所有精灵帧的图片纹理。即使它不会绘制,你也必须要把它添加到场景中,例如:
    CCSpriteBatchNode* spritebatch = CCSpriteBatchNode::create("animations/grossini.png");

    下一步,你需要运用CCSpriteFrameCache实例来确保帧名字对应帧边界。也就是说,图片在哪一块矩形区域中。例如:
    	CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache();
    	cache->addSpriteFramesWithFile("animations/grossini.plist");

    一旦你的精灵表和帧加载完成,并且精灵表已经被添加到了场景中,你可以通过createWithSpriteFrameName方法来创建精灵。并且通过addChild要添加到精灵表中:
    	m_pSprite1 = CCSprite::createWithSpriteFrameName("grossini_dance_01.png");
    	spritebatch->addChild(m_pSprite1);
    	addChild(spritebatch);


    createWithSpriteFrameName 方法将会从grossini.plist中找到对应的坐标以及矩形区域,之后再裁剪grossini.png的纹理成一个精灵帧。


    现在我们创建一个CCArray对象并且天剑所有的帧动画进去。在这个动画的例子中,我们发现所有的14帧都有相同的大小,所以我们可以用一个嵌套的循环遍历它们,并且当完成添加14帧之后结束掉循环。
    	CCArray* animFrames = CCArray::createWithCapacity(15);
    	char str[100] = {0};
    	
    	for(int i = 1; i < 15; i++) 
    	{
    		sprintf(str, "grossini_dance_%02d.png", i);
    		CCSpriteFrame* frame = cache->spriteFrameByName( str );
    		animFrames->addObject(frame);
    	}

    最后,我们需要创建一个CCAnimate动作实例来运行CCSprite。下面我们可以在CCRepeatForever动作中包裹CCAnimate动作来让它一直执行下去,像这样:
    	CCAnimation* animation = CCAnimation::createWithSpriteFrames(animFrames, 0.3f);
    	m_pSprite1->runAction( CCRepeatForever::create( CCAnimate::create(animation) ) );

    四、文件动画
    CCAnimateCache能够加载一个描述一批节点的xml/plist文件,包括帧名和他们的矩形区域。这个借口非常容易使用。
    	CCAnimationCache *cache = CCAnimationCache::sharedAnimationCache(); // 缓存在cocos2dx中一直是单例模式
    	cache->addAnimationsWithFile("animations/animations-2.plist");
    	CCAnimation animation = cache->animationByName("dance_1");
    	CCAnimate animate = CCAnimate::create(animation);
    	sprite->runAction(animate);

    展开全文
  • 本文为作者原创,其中知识内容出自闪电终结者的视频课程首先用ppt简单的做一个帧动画,把做好的每一张图片命名为pass01.png pass02.png ….复制到res文件夹下// 精灵是用于显示动画效果,... auto sprite = cocos2d:

    本文为作者原创,其中知识内容出自闪电终结者的视频课程

    首先用ppt简单的做一个帧动画,把做好的每一张图片命名为pass01.png pass02.png ….复制到res文件夹下

    // 精灵是用于显示动画效果,需要写一个动画,然后往动画中添加图片,在让精灵显示出来
    void TransferTestScene::spritePlayShow() {
        auto sprite = cocos2d::Sprite::create();
        // 设置锚点
        sprite -> setAnchorPoint(cocos2d::Vec2(0, 0));
        // 设置坐标
        sprite -> setPosition(0, 0);
        auto animation = cocos2d::Animation::create(); // 创建动画
        for (int index = 1; index <= 19; index++) {
            auto str = new char[50];// std::isstream << ""
            std::sprintf(str, "pass/pass%02d.png", index);
            animation -> addSpriteFrameWithFile(str); // 向动画添加图片
        }
        for (int index = 19; index >= 1; index--) {
            auto str = new char[50];// std::isstream << ""
            std::sprintf(str, "pass/pass%02d.png", index);
            animation -> addSpriteFrameWithFile(str); // 向动画添加图片
        }
        // 设置动画帧率
        animation -> setDelayPerUnit(5.0f / 38);
    //    // 设置动画播放完毕后是否回到第一帧
    //    animation -> setRestoreOriginalFrame(true);
        // 用动画创建精灵动作
        auto action = cocos2d::Animate::create(animation);
        // 让精灵来完成动作
        sprite -> runAction(cocos2d::RepeatForever::create(action));
    
        addChild(sprite);
    

    Animation是由许多精灵帧组成,可以设置间隔时间,持续时间等,它实际上是包含着一组数据。Animate是一个动作,它是通过Animation对象创建。

    展开全文
  • 上一篇我们学习了怎么制作一个AnimationClip,现在我们来学习如何使用它。 为了演示一个完整的流程,我们来重新创建一个节点:bomb(炸弹),用他来播放上次制作的爆炸的动画...我们可以看到,现在的Animation组件...

    上一篇我们学习了怎么制作一个AnimationClip,现在我们来学习如何使用它。

    为了演示一个完整的流程,我们来重新创建一个节点:bomb(炸弹),用他来播放上次制作的爆炸的动画。

    1. 创建一个节点,并命名为bomb

     

    为了演示这次的内容,我们把上次的blast先隐藏掉

    2. 为bomb节点添加上Animation组件

     

    我们可以看到,现在的Animation组件有三个属性:Default Clip,Clips和Play On Load,关于他们三个的作用,官方文档中有详细说明:http://www.cocos.com/docs/creator/components/animation.html#animation--1

     

    这里我们来操作Clips

    3. 将Clips后面的数字改为1,按回车使其生效,会看到发生了变化:

     

    4. 我们将刚才制作的动画small,拖拽到下图所示位置:

     

    5. 完成,会看到在0的位置装载了small动画:

     

    6. 在bomb炸弹节点上添加脚本,准备用脚本调用该动画

    我们创建一个名为Bomb的脚本,并挂载到bomb节点之下:

     

    7,在Bomb脚本的onLoad方法中加入代码

     

    8. 运行一下看看效果

    如果顺利的话,运行之后就能看到我们的爆炸动画播放了一次

    如果我们想让这个节点播放其他动画的话,根据上述方法同样可以实现,比如我给该节点的Animation组件添加一个动画idle:

     

    然后在代码中调用的时候,只要依照上面的形式,运行.play('idle')就可以了



    作者:30330218760f
    链接:https://www.jianshu.com/p/9874f917602d
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    展开全文
  • 这篇教程希望大家能够在CocosCreator中快速上手帧动画制作和脚本控制 并分享一些 意外的收获 和API的查看有关 这次的教程需要的前提并不高 只要安装了CocosCreator就可以了 我们先制作帧动画的plist和png吧...

    转自:http://www.cocoachina.com/bbs/read.php?tid-458312.html

    这篇教程希望大家能够在CocosCreator中快速上手帧动画制作和脚本控制  并分享一些 意外的收获 和API的查看有关

    这次的教程需要的前提并不高  只要安装了CocosCreator就可以了

    我们先制作帧动画的plist和png吧

    我们使用texturepakcer来制作  texturePacker_for_win  texturePacker_for_mac

    解压后目录是这样的  然后大家按照下面的某某说明一步一步做就可以了  很简单


    都完成后 安装目录如下 


    打开TexturePackerGUI.exe  对提示按叉关掉吧 我们不需要命令行工具


    然后呢 我们先拿到帧图片吧  当然自己有帧图片的话也可以 但出于学习目的  先和我的保持一致吧  练习用帧图片解压失败备用

    图片的命名我已经写好了 hero为类名 第一个数字为方向  0~7分别是左上方向顺时针到右方向的序号 后两个数字为动作编号 站着为00  最后一个数字为动画帧数目 一个朝向有4张图片

    然后呢 我们全选32张图片  拖到TexturePackerGUI右侧的Sprites中  


    然后看到左侧 layout栏下 将Trim mode 选为None  然后 Heuristic mask 勾上  这里一个去背景色 一个保持图片大小不变(默认会缩进背景色去除后透明的部分,这样会引来等会播放帧动画时候图片的偏移)


    然后我们选file -> publish  文件取名为hero100吧   1表示第一种角色的形象 00表示站着


    然后图片集的名字也是 hero100  (这里有点奇怪 我之前一次的时候不需要设置图片集的名字  总之记得 设置后 应该有两个文件 一个hero100.plist 一个hero100.png  同名)


    到这里 做动画需要的资源已经整理好了 现在可以关掉 TexturePacker了  打开CocosCreator 创建一个空项目


    然后呢 在资源管理器中 对asserts 鼠标右键 -> 新建 -> scene  然后重命名为GameScene  


    然后呢 我们在asserts 目录下新建几个文件夹 方便管理  script放脚本  image放图片  animation 放动画


    然后看到层级管理  对 canvas 鼠标右键 ->  创建节点 ->  创建渲染节点  ->Sprite  然后重命名为 "hero"


    然后选中 hero  点击界面中间下方的动画编辑器 点击添加Animation组件->新建AnimationClip  ->  名字取为 heroStand_0  保存 


    然后在资源管理器就能看到我们新建的动画了 在右侧的属性管理器里面也能看到新加的Animation组件  至于上面的是什么功能  等会就知道了  先将属性管理器里面的heroStand_0扔到Animation文件夹里面



    然后呢 将我们之前的hero100.plist 和 hero100.png 扔到项目目录的image下  


    点开hero100.plist  即为图标为红色方框的一项


    然后呢 点开中间的动画编辑器  点击属性列表的 添加属性 add Property  -> cc.Sprite.spriteFrame 然后属性列表就出现对应的属性了 


    后面呢 选中 资源管理器  image下 的hero0000~hero0003  (shift + 鼠标点击hero0000 + 鼠标点击hero0003)  拖动到动画编辑器里面下方帧列表(和属性列表同高的列表)的第一帧的位置



    然后呢 选中image 下 hero0000 


    拖动到离原本第四帧有点距离的第6 或7帧的位置


    然后呢 选中刚拖进来的第5帧 往回拉到贴紧第4帧 


    然后呢看到动画编辑器最下面一栏 将Sample 改为4 warpMode 改为 Loop  至于为什么Sample是4  这个我是试出来的 = = 


    然后呢 选中层级管理器中的 hero  将资源管理器的 heroStand_0 拖动到 属性管理器的Default Clip 中 选中 下面的 Play On Load


    然后就可以先预览一下效果啦  (动图我就截个图示意一下了 详细看电脑上显示吧)



    我们继续吧  

    选中资源管理器的animation文件夹  鼠标右键 -> 新建 -> animation Clip  重命名为heroStand_1



    然后呢 选中 层级管理器中的hero  将属性管理器中Animation 组件的 clip 加一 (记住是上面的三角形箭头  没事按下面的箭头的话 后果自负吧)  然后将资源管理器中的heroStand_1拖到属性管理器中的Clips [1] 中 



    然后呢 我们看到动画编辑器最下面一栏 开头的 Clip 选为 heroStand_1  后面就如法炮制吧 动画编辑器 属性列表 点击  add Property cc.Sprite.spriteFrame 选择hero1000~hero1003 拖到 下方帧列表中 再单独拖动hero1000到6 或7帧的位置 往回拖到第4帧后面  动画编辑器最下面一栏 Sample 改为4  warpNode改为Loop  




    然后呢 我们继续这个流程 将0~7  八个方向的动画头添加进来   (这时候我的电脑已经有点卡了 请大家在这时候稍安勿躁  添加不上的帧多尝试几次)









    到这里我们的动画部分就已经整理好了  我们也具备了基本的帧动画添加能力  下面我们来写两个简单的脚本  将玩家的朝向转向鼠标点击的方向 

    我们的思路是将整个屏幕分为9块 和9宫格一样 点中间的格子  动画不变 点其他位置的格子 就改变动画中玩家的朝向

    首先写一个hero脚本 (资源管理器中对script文件夹 鼠标右键 创建 javascript 重命名为myHero) 它的功能是接受一个方向的标志 (0~7) 然后改变动画中人物的朝向 



    脚本很简答 我们就敲了6行代码  首先在properties中添加了动画名 AnimName  供changeDirection函数调用 
    而changeDirection函数 接受一个方向标识 (0~7)  然后通过和AnimName拼起来  就能够选择到不同的动画来播放了 

    后面我们再写一个 app脚本 (资源管理器中对script文件夹 鼠标右键 创建 javascript 重命名为myApp)   它的功能是
    将鼠标点击的位置 换算为 0~7  数字  对应屏幕的8个不同方向的方格子 



    首先在properties中添加hero 对象  等会要通过它调用hero下的myHero.js的changeDirection来改变方向

    然后在onload中呢 我们先 将this存起来吧 免得等会在回调的时候 this胡乱指

    然后呢添加一个鼠标弹起监听事件  当我们鼠标按下弹起的时候  就会调用后面的函数  函数里的event可以获得鼠标点击的位置 通过event.getLocationX() 和event.getLocationY()可以获得

    然后后面呢 就是一个换算的代码  visibleSize 获得了整个屏幕的尺寸 默认的话大家应该和我一样 都是 (960, 640) 

    我们为了将整个点击的区域分为行3块竖3块 我们就用 鼠标点击的位置 除以 (屏幕的尺寸/3)  但是算出来的是小数 我们用javascript内置的Math.floor函数(javascript内置的对象就只有几个 大家感兴趣可以去看看 官网文档里面讲javascript的一节里面的链接就不错 )  将小数部分截掉  变成整数



    然后呢我们的目标呢 是将这些点的坐标换算成这个样子



    具体怎么算呢  我的思路就是 先将坐标的Y的值上下翻过来    通过 2 - Yindex 


    然后就会发现  位置为 0 1 2 3 4 的都已经可以直接算出来了 通过直接将Xindex 和 Yindex 相加就可以了 

    而 5 6 7 的位置  只要将 8 - (Xindex + Yindex) 也可以算出来了  

    换算的问题解决之后  我们就调用 myHero.js中的changeDirection(dir)  将方向传进去就可以了 

    后面还有一点点收尾工作  选中层级管理器中的canvas  将资源管理器中的myapp.js  层级管理器中的 hero 拖到canvas层级管理器中的Script 和hero 中 Script可以一下子就可以放上去 hero要在上面悬停  大概15~20秒


    然后选中 层级管理器的hero 等待加载完成  将资源管理中的myHero.js拖到属性选择器的Script中 并在AnimName 中 填入 heroStand_  也就是动画统一的前缀



    后面就可以看一下效果了 (这边我就只剪 换方向后的一帧 来演示一下)










    到这里 我们已经具备基本的通过脚本控制动画的能力了   后面讲一下查看API的内容

    其实我本来的想法是将myApp.js  和 myHero.js  通过自定义事件的传输和监听  实现一个更好的解耦 但是 官方对于事件的传播只支持事件的冒泡  而事件之间的点对点的传输又和解耦的出发点相违背

    我就想看看有没有什么办法 结果 解决方案没想出来  反而找到一个我觉得还不错的看API的方法

    那时候我在研究 能不能通过自定义事件 将传播类型写成捕获来看看能不能行 但是api的资料有点少 突然灵光一闪 在onload写了下面的代码



    本来只是想看看为什么一直报错 结果运行后看到了还不错的东西



    大家可以通过这样的方式结合API  看一下实例之中都有什么属性和方法  

    后面会推出 结合帧动画 和node.js 实现一个简易的角色扮演社区的教程 (当然在3月份之前里面的玩家都不能讲话就是了)  并在此基础上  继续收尾一些UI组件  和脚本之间交互设计的思想

    由于教程的实验 图片整理 和文字整理和前两篇不同 是分开整理的 可能会有一些问题 请在下方回帖提问 

    还有我再也不用这个截图工具了。

    源码在这里 AnimationDemo

    2016-03-31

    0.7->1.0 动画编辑器变化











    ->前往教程司令部

    下一篇:CocosCreator + 在线角色扮演社区(1) 简易教程

    下一篇: CocosCreator + AnimationCurve 简易教程

    展开全文
  • 在用cocos creator编辑器的时候遇到了一个问题,就是在给Animation添加动画事件的过程中事件不能执行。如果利用编辑器添加事件的话必须要把事件监听的脚本放在跟Animation组件一个控件下才会执行脚本注册的事件。 ...
  • http://icelily.xyz/?p=845
  • Cocos2dx帧动画的两种创建方式 看了好几天cocos2dx的帧动画,现在才有点眉目,为了高效期间我们一般会用到精灵帧缓存(CCSpriteFrameCache) 和动画缓存(CCAnimationCache) .大体的操作步骤: 1.把多个帧动画合成一张...
  • Cocos2d-x为了降低开发难度,对于动画的实现采用的帧动画的方案。这也就是说Cocos2d-x中的动画是帧动画。 帧动画的原理相信大家都不陌生,就是多张图片循环播放以实现动画的效果。 一个简单的动画动画实现如下: ...
  • 原文地址[http://docs.cocos.com/creator/manual/zh/animation/scripting-animation.html#动画事件] 发现官方文档写的很全,也有很多实例,所以直接搬过来。播放var anim = this.getComponent(cc.Animation); // ...
  • cocos creator 动画播放完成后监听事件自动移除 动画的Wrapmode有很多任何模式:Default、Normal、Loop、PingPong等 根据上面的事件可以监听事件并调用相应的方法 监听方法,使用on注册动画事件回调 let anim: ...
  • 要通过cocos2d-js实现帧动画,需要完成以下基本操作: 通过cc.Animation定义动画中基本信息:帧以及帧切换速度等创建Action(cc.Animate)并在cc.Node上播放它 定义帧动画——cc.Animation //定义cc....
  • Cocos Creator Animation

    2017-08-10 22:42:36
    素材准备 注意命名顺序规范 使用TexturePackerGUI生成图集包 导出的图集包 在Cocos Creator中使用
  • 关于 Animation Animation 组件 之前我们了解了 Cocos Creator 是组件式的结构。那么 Animation 也不例外,它也是节点上的一个组件。 Clip 动画剪辑 动画剪辑就是一份动画的声明数据,我们将它挂载到 Animation 组件...
  • Animation 组件提供了一些常用的动画控制函数,如果只是需要简单的控制动画,可以通过获取节点的 Animation 组件来做一些操作。 播放 var anim = this.getComponent(cc.Animation); // 如果没有指定播放哪个...
  • cocos 设置Animation的循环次数、播放速度 动画的Wrapmode可以是任何模式:Default、Normal、Loop等
  • 第一点:最容易出错的就是读取图片,新版的cocos2d-x 读取图片失败只会执行一个CCLOG 也就是说 就算读取失败 也不会判断错误,而是要自己去看 指针指向内容是否为空, 第二点:就是注意图片的相对路径,这个也很...
  • CCSize s = CCDirector::sharedDirector()-&gt;getWinSize(); //载入动画所需纹理图片 CCTexture2D *texture = CCTextureCache::...animations/dragon_animation.png"); // manually...
  • 原来有一两个人说我不帅的时候,我不以为意,逗我玩而已,后来几乎所有人都说我不帅,我才真正意识到事态的严重,这社会骗子真是越来越多了... 好吧我承认,这个笑话不好笑,其实我想说的是,做人一定要坚持自己的...
  • 首先,了解一下cc.Animation作用是什么,它是在cc.Sprite对象展示动画时使用的一个cc.Animation对象。  构造方法:  cc.Animation(frames, delay, loops)  在cc.Sprite对象展示动画时使用的一个cc....
1 2 3 4 5 ... 20
收藏数 7,181
精华内容 2,872
热门标签