转载标明出处:http://blog.csdn.net/notbaron/article/details/38308127
上篇回顾
上篇中,蛤蟆学习了怎么在一个层里面添加一个精灵。我们往里面加入了一个球一样的精灵。今天晚上我们将让这个精灵动起来,就想我们所玩的游戏那样。
理论补充
精灵动起来是什么样子的呢?
精灵为什么会动起来?
我们先来讨论下第一个问题,玩过魔兽世界那种大型端游的小伙伴一定非常了解角色动作。我们在聊天窗口只要输入/dance这个命令,那里面的角色会立马开始跳舞,每个角色都会舞蹈。这个跳舞就是精灵的动作,只要我们不做其他操作,他会一直在那里跳舞。当然我们手机游戏中的精灵不会有那么绚丽的动画,至少现在是。
至于为什么会动起来?魔兽世界这种3D游戏,他的动画是通过3DMAX或者其他建模软件,建模一个精灵,然后再制作一个精灵模型的一些关键帧,然后将这些关键帧串联起来就变成了一个动画,然后我们在输入/dance 的时候它就调用该动画。我们手机上的精灵动起来,其中有两种方法,1:我们本次要学习的帧动画,2,后续会一起学习的骨骼动画。帧动画是将精灵的整个图片快速的换掉,而骨骼动画师将一个精灵的四肢躯干都打碎,然他们自个儿动起来形成动画。
手机上的动画说白了就是图片的变化,不是整个图片的替换变换就是胳膊腿的图片扭动。
准备
未来实现帧动画,我们需要有一连串的动画精灵。蛤蟆自己不会美工,只能去网上找一下去了。在\cocos2d-x-3.2\tests\cpp-tests\Resources\Images路径下找到了图片,这个可以用来做我们的例子使用。如下图 1 ,我们将红框部分的图片复制到我们自己工程的resource目录中。
文件名很有规律大家有没有发现,这个将利于我们编程实现之的。
手动创建帧动画
好了,既然图片准备好了,那我们开始吧。
我们还是用之前创建的HelloWorld项目工程即可。
这次我们只需要在
bool HelloWorld::init() 函数中加入如下代码即可。
auto grossini =Sprite::create("grossini.png");
auto animation =Animation::create();
for( inti=1;i<15;i++)
{
char szName[100] = {0};
sprintf(szName, "grossini_dance_%02d.png", i);
animation->addSpriteFrameWithFile(szName);
}
animation->setDelayPerUnit(2.8f / 14.0f);
animation->setRestoreOriginalFrame(true);
auto action =Animate::create(animation);
grossini->runAction(action);
grossini->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 +origin.y));
this->addChild(grossini);
多么,才14行,不要害怕,而且还有两行是括号的呢。
蛤蟆是将这些代码放在了该函数的最后,return true之前。
代码解释
auto grossini =Sprite::create("grossini.png"); //这行是创建一个精灵,和我们上一篇中的是一模一样的却别只是再用图片不一样的。
auto animation =Animation::create(); //这个创建了一个Animation动画。 这个类的继承关系如下图,好像和昨天的精灵继承有点不一样的。这个类直接继承于Ref和Clonable(看论坛里面有人讨论以前好像有个 Object对像的,现在被Ref代替了??),感觉Animation类还是辈分比较大的。Clonalbe翻译过来的意思是 可以复制的。哦,这个就好解释了说明的我们的动画能直接被复制的。此处小伙伴们只要记住,这个类Animation是个名字,后面代码里面还有一个Animate类,那个类才是个动词。如下图2所示
for(inti=1;i<15;i++)
{
char szName[100] = {0};
sprintf(szName, "grossini_dance_%02d.png", i);
animation->addSpriteFrameWithFile(szName);
}
//上面是个for循环,学过任何编程语言的小伙伴都知道,它进行了15次循环,第15次就什么也不做。 每次循环做的工作就是,一个临时的字符变量szName,然后将该变量szName赋值成 grossini_dance_%02d.png”,这个%02d是会被 i变量的值所代替,而且是用二位数代替之。这样这个变量每次都是一个图片名字了。 应了 我们刚才所说,图片名字类似还是很利于编程的。
然后将 这个图片加入到动画当中。这个可以这样理解,我们现在正在创建一个动画,而动画有一帧一帧的图片组成,也是给动画创建一帧。 说白了,就是我们这个动画只有14帧其实。正如我们放入resource中的动画图片15张,其中1张不是动画帧图片。
animation->setDelayPerUnit(2.8f/ 14.0f);
//这个是设置该动画的默认属性,动画以多快的速度播放的。这里表示 2.8秒内播放完14张图片,就是每张的图片的播放时间,我们也可以直接设置一个1.0 f什么的,则表示每张图片用1秒时间。
animation->setRestoreOriginalFrame(true);
//这个表示,我们动画放完。就是放完14张图片后,这个精灵返回到原始的那个画面,就是grossini.png这个图片。
auto action = Animate::create(animation);
//这个是动作类,这个和 那个animation不重复么?而且这个类初始化的时候还调用animation类。不是多此一举么? 我们看下这个类的继承,就可以稍微明白一点。如下图3
这个Animate其实辈分啊比Animation低多了,你看Animation直接继承于Ref和 Clonable.按辈分将这个Animate得喊一声曾爷爷给Animation听呢。
小伙伴可以这样理解,这个Animation呢,只是将用于动画的图片收集了起来放在了一摞。而Animate就把这一摞图片变成一个动画,可以不给精灵调用。(这个后续小伙伴感兴趣的话可以去cocos2d-x源码,现在我们就这样理解足矣。)
grossini->runAction(action);
//这个表示精灵grossini调用这个动画了。
grossini->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 +origin.y));
//这行是上一篇中介绍的一样的,是精灵的位置摆放。
this->addChild(grossini); //这个是将精灵添加到HelloWorld 层中。
结果如下图 4
总结
通过本笔记我们介绍了如何让精灵动起来,当然图片小伙伴们可以进行替换的。当时这样手动创建动画是不是很烦琐呢?接下去我们会学习怎么通过一个文件创建动画。