接触到cocos2d-x 3.3中动画,写了如下笔记。我的笔记与代码实例是一起的,方便查看。笔记中记录了大部分动画创建、运用、理解和实现,也表明一些错误原由和可能出现错误地方,方便新手少走弯路,也使自己以后查看时会注意到。
查看代码时可能因为转过来格式问题,有些出入,望理解下,代码在VS2012测试都通过的。测试每个动画时,把注释去掉就可以。注意下多个动画运行时,不易观察的情况。要用这个代码的话,自己可以根据自己的项目酌情修改下。
在使用每个动画是最好追溯到源定义查看下它的定义与用法及实现,以便更好理解,这里希望大家一起交流、讨论下,不懂或有问题的留言给我,一起探讨。
下面贴上代码:
HelloWorldScene.h文件没有什么改变,加了3个回调函数,有写注释:
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
//用于测试CallFunc?系列函数
void test_CallFunc();
void test_CallFuncN(Node * pSence);
void test_CCCallFuncND(Node * pSence, void * data);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp文件这里才是重点,笔记全在这里,有做标记的:
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//
// 1. super init first
if ( !Layer::init() )
{
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
/
// 2. add a menu item with "X" image, which is clicked to quit the program
// you may modify it.
// add a "close" icon to exit the progress. it's an autorelease object
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(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);
/
// 3. add your codes below...
// add a label shows "Hello World"
// create and initialize a label
auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
// position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height));
// add the label as a child to this layer
this->addChild(label, 1);
//====================================================================================================================================================
//创建一个精灵用于反转等动画
auto sprite_flip = Sprite::create("CloseNormal.png");
sprite_flip->setPosition(Vec2(50, visibleSize.height/2));
this->addChild(sprite_flip, 1);
//动画演示 (可以用 auto 自动生成类型) 可以参考 http://www.jellythink.com/archives/749
//1、瞬时动画
//Place 瞬间移动 create(具体位置); 移动时间很快,一般看不到,不明显。
Place * pPlace = Place::create(Vec2(visibleSize.width/2, 50));
//label图层运行创建place的动画,下同。
label->runAction(pPlace);
//hide 隐藏动画 create(void);隐藏后消失。
Hide * pHide = Hide::create();
//label->runAction(pHide);
//show 显示动画 create(void);当运行隐藏动画后,就会重新显示。
Show * pShow = Show::create();
//label->runAction(pShow);
//ToggleVisibility 若先显示,则隐藏,若先隐藏,则显示 create(void); 可以用于判断,是显示和隐藏结合互反。
ToggleVisibility * pToggleVisibility = ToggleVisibility::create();
//label->runAction(pToggleVisibility);
//FlipX/FlipY 延X/Y轴反转 create(bool);精灵测试可以,而 label 的文本测试有中断错误
FlipX * pFlipX = FlipX::create(true);
sprite_flip->runAction(pFlipX);
FlipY * pFlipY = FlipY::create(true);
sprite_flip->runAction(pFlipY);
//2、延时动画
//MoveTo/MobveBy 移动到/移动多少距离 create(运行时间f,移动到的位置/移动的距离 ); 注意TO与BY的区别。
MoveTo * pMoveTo = MoveTo::create(3.0f, Vec2(430, visibleSize.height/2));
//sprite_flip->runAction(pMoveTo);
MoveBy * pMoveBy = MoveBy::create(3.0f, Vec2(50, 50));
//sprite_flip->runAction(pMoveBy);
//JumpTo/JumpBy 跳动到/跳动多少距离 create(运行时间f, 跳动到的位置/跳动的距离,跳动的高度f,跳动的次数); 注意TO与BY的区别。
JumpTo * pJumpTo = JumpTo::create(3.0f, Vec2(430, visibleSize.height/2), 20.0f, 5);
//sprite_flip->runAction(pJumpTo);
JumpBy * pJumpBy = JumpBy::create(3.0f, Vec2(50, 50), 20.0f, 5);
//label->runAction(pJumpBy);
//BezierTo/BezierBy 延贝塞尔曲线运动到/延贝塞尔曲线运动多少距离 create(运行时间f, 一阶贝塞尔曲线特殊结构体); 注意引用结构体和TO与BY的区别。
//ccBezierConfig 结构体 第一个为起始点,二为控制点,三为末尾点。
ccBezierConfig BezierConfig = { Vec2(50, 30), Vec2(60, 100), Vec2(200, 120) };
BezierTo * pBezierTo = BezierTo::create(3.0f, BezierConfig);
//sprite_flip->runAction(pBezierTo);
BezierBy * pBezierBy = BezierBy::create(3.0f, BezierConfig);
//label->runAction(pBezierBy);
//ScaleTo/ScaleBy 缩放到多少/缩放了多少 create(运行时间f,一个参数f时为整体,2个3个参数f分别为x、y、z方向); 缩放时,大于一为放大,小于一为缩小。
ScaleTo * pScaleTo = ScaleTo::create(3.0f, 0.5);
//sprite_flip->runAction(pScaleTo);
ScaleBy * pScaleBy = ScaleBy::create(3.0f, 1.5, 1.5);
//label->runAction(pScaleBy);
//RotateTo/RotateBy 旋转到/旋转了多少 create(运行时间f,线或者点或者面); 后面的参数可以是一条线,或者点,或者面,区别就是立体感觉,面时要用Vec3。
RotateTo * pRotateTo = RotateTo::create(3.0f, visibleSize.width/2, visibleSize.height/2);
//sprite_flip->runAction(pRotateTo);
RotateBy * pRotateBy = RotateBy::create(3.0f, 350);
//label->runAction(pRotateBy);
//Blink 闪烁 create(运行时间f,闪烁次数); 闪烁是如星星的动画
Blink * pBlink = Blink::create(3.0f, 5);
//label->runAction(pBlink);
//TintTo/TintBy 色调变化到/色调加减值 create(运行时间f,红值,绿值,蓝值); 当超过255或者低于0时,会进行在0-255循环加减。
TintTo * pTintTo = TintTo::create(5.0f, 255, 20, 20);
//label->runAction(pTintTo);
TintBy * pTintBy = TintBy::create(5.0f, -255, 20, 20);
//label->runAction(pTintBy);
//FadeTo 变暗到 create(运行时间f, 明亮度); 明亮度是0-255之间,初始时是255,有亮变暗。
FadeTo * pFadeTo = FadeTo::create(3.0f, 30);
//label->runAction(pFadeTo);
//FadeOut 渐隐 create(运行时间f); 可以配合组合动画与淡出配合
FadeOut * pFadeOut = FadeOut::create(3.0f);
//label->runAction(pFadeOut);
//FadeIn 淡出 create(运行时间f); 可以配合组合动画与渐隐配合
FadeIn * pFadeIn = FadeIn::create(3.0);
//label->runAction(pFadeIn);
//3、组合动画
//先建立Animation create(), 在建立Animate帧动画 create(Animation); 有几种创建方式,详细资料参考 https://my.oschina.net/Jacedy/blog/301360
auto sprite_Animate = Sprite::create("grossini_dance_01.png");
sprite_Animate->setPosition(Vec2(visibleSize.width/2, visibleSize.height/2));
this->addChild(sprite_Animate, 1);
Animation * pAnimation = Animation::create();
for(int i=1; i<=14; i++)
{
char array_Animate[50] = {0};
//"grossini_dance_%02d.png" 注意这里的%02d
sprintf(array_Animate, "grossini_dance_%02d.png", i);
pAnimation->addSpriteFrameWithFile(array_Animate);
}
//每一帧停留的时间,14秒时间完成14幅图片显示,切记要写成14.0f形式!
pAnimation->setDelayPerUnit(14.0f / 14);
//播放完后回到第一帧
pAnimation->setRestoreOriginalFrame(true);
Animate * pAnimate = Animate::create(pAnimation);
sprite_Animate->runAction(RepeatForever::create(pAnimate));
//Sequence 序列(顺序执行) create(要运行的动作,以逗号隔开,...,NULL); 依次顺序执行各个动作,记得最后以NULL结束。
Sequence * pSequence = Sequence::create(pFadeOut, pFadeIn, pBlink, NULL);
//label->runAction(pSequence);
//Spawn 同步执行 create(要运行的动作,以逗号隔开,...,NULL); 每个动作同时进行,记得最后以NULL结束。
Spawn * pSpawn = Spawn::create(pBlink, pScaleBy, pTintTo, NULL);
//label->runAction(pSpawn);
//Repeat 重复有限次数 create(要运行的动画,运行次数); 可以和其他动画嵌套使用。
Repeat * pRepeat = Repeat::create(pSpawn, 3);
//label->runAction(pRepeat);
//RepeatForever 重复无限次数 create(要运行的动画); 可以和其他动画嵌套使用。
RepeatForever * pRepeatForever = RepeatForever::create(pSequence);
//sprite_flip->runAction(pRepeatForever);
//Reverse 反动作 (动作)action->reverse(); 最好使用序列组合,否则同步时不好观察。
//(注意:以(动作)actionTo 的动作没有反动作的,如pRotateTo, 大部分以(动作)actionBy 的动作有反动作,如pRotateBy 。使用没有反动作的出现中止错误。)
ActionInterval * pReverse = pRotateBy->reverse();
//label->runAction(Sequence::create(pRotateBy, pReverse, NULL));
//4、扩展动作
//DelayTime 延时 create(延时的时间); 继承ActionInterval,可以与其他动作组合使用,相当与暂定几秒,一般动画过程中调用此函数。
DelayTime * pDelayTime = DelayTime::create(3);
//label->runAction(Sequence::create(pRotateBy, pDelayTime, pReverse, NULL));
/**
* CallFunc系列动作的后缀”N”表示Node参数,指的是执行动作的对象, “D”表示Data参数,指的是用户自定义的数据,
* ”O”表示对象,指的是一个用户自定义的Ref参数。
*/
//CallFunc 无参数函数 create(CC_CALLBACK_0(函数名,this)) 或 create(this, callfunc_selector(函数名));
//可以用CC_CALLBACK_0来引用,也可以使用callfunc_selector。
//注意CC_CALLBACK_?中0表示无参数,1表示一个参数,2表示两个参数,3表示3个参数,并且了解其构造和用法。
CallFunc * pCallFunc = CallFunc::create(this, callfunc_selector(HelloWorld::test_CallFunc));
//label->runAction(Sequence::create(pRotateBy, pDelayTime, pReverse, pCallFunc, NULL));
//CallFuncN 带当前节点Node参数函数 create(CC_CALLBACK_1(函数名,this)) 或 create(this, callfuncN_selector(函数名));
//可以用CC_CALLBACK_1来引用,也可以使用callfunc_selector。
CallFuncN * pCallFuncN = CallFuncN::create(CC_CALLBACK_1(HelloWorld::test_CallFuncN, this));
//label->runAction(Sequence::create(pRotateBy, pDelayTime, pReverse, pCallFuncN, NULL));
//CCCallFuncND 带当前节点Node参数和函数指针参数的函数 create(this, callfuncN_selector(函数名), void *指针);
//这里不能用CC_CALLBACK_? 是因为Node * 与 void * 参数转化问题。
CCCallFuncND * pCCCallFuncND = CCCallFuncND::create(this, callfuncND_selector(HelloWorld::test_CCCallFuncND), (void *)0xbebabeba);
//sprite_flip->runAction(Sequence::create(pRotateBy, pDelayTime, pReverse, pCCCallFuncND, NULL));
//5、速度变化
//EaseIn 由慢变快(速度线性变化) create(动作,末速率f); 这里的 in 表示由慢变快。
EaseIn * pEaseIn = EaseIn::create(pMoveBy, 5.0f);
//label->runAction(pEaseIn);
//EaseOut 由快变慢(速度线性变化) create(动作,初速率f); 这里的 out 表示由快变慢。
EaseOut * pEaseOut = EaseOut::create(pSequence, 5.0f);
//sprite_flip->runAction(pEaseOut);
//EaseInOut 由慢变快再由快变慢(速度线性变化) create(动作,初末速率f); 这里 in/out 同上面2种。
EaseInOut * pEaseInOut = EaseInOut::create(Sequence::create(pRotateBy, pDelayTime, pReverse, NULL), 5.0f);
//label->runAction(pEaseInOut);
//EaseSineIn 由慢变快(速度正弦变化) create(动作); 这里的 in 表示由慢变快。
EaseSineIn * pEaseSineIn = EaseSineIn::create(pJumpBy);
//label->runAction(pEaseSineIn);
//EaseSineOut 由快变慢(速度正弦变化) create(动作); 这里的 out 表示由快变慢。
EaseSineOut * pEaseSineOut = EaseSineOut::create(pBezierBy);
//sprite_flip->runAction(pEaseSineOut);
//EaseSineInOut 由慢变快再由快变慢(速度正弦变化) create(动作); 这里 in/out 同上面2种。
EaseSineInOut * pEaseSineInOut = EaseSineInOut::create(pRotateBy);
//label->runAction(pEaseSineInOut);
//EaseExponentialIn 由慢变快(速度指数变化) create(动作); 这里的 in 表示由慢变快。
EaseExponentialIn * pEaseExponentialIn = EaseExponentialIn::create(pScaleBy);
//sprite_flip->runAction(pEaseExponentialIn);
//EaseExponentialOut 由快变慢(速度指数变化) create(动作); 这里的 out 表示由快变慢。
EaseExponentialOut * pEaseExponentialOut = EaseExponentialOut::create(pBlink);
sprite_flip->runAction(pEaseExponentialOut);
//EaseExponentialInOut 由慢变快再由快变慢(速度指数变化) create(动作); 这里 in/out 同上面2种。
EaseExponentialInOut * pEaseExponentialInOut = EaseExponentialInOut::create(pTintTo);
label->runAction(pEaseExponentialInOut);
//====================================================================================================================================================
// add "HelloWorld" splash screen"
auto sprite = Sprite::create("HelloWorld.png");
// position the sprite on the center of the screen
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
// add the sprite as a child to this layer
this->addChild(sprite, 0);
return true;
}
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void HelloWorld::test_CallFunc()
{
CCLOG("CallFunc!");
}
void HelloWorld::test_CallFuncN(Node * pSence)
{
CCLOG("CallFuncN!!");
}
void HelloWorld::test_CCCallFuncND(Node * pSence, void * data)
{
CCLOG("CCCallFuncND!!!");
}
///<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
装载请注明:创建人:哈哈沃 交流群:580072227
谢谢浏览!!!不懂或有问题尽管留言甩给我,我定会全然接受与解决。