Cocos2d-x中的动作
Action继承树
Action类的使用
基本动作
重复执行动作
序列
帧动画
回调函数包装器
延时类——ActionInterval
基本动作
重复执行——Repeat和RepeatForever
序列——Sequence和Spawn
帧动画——Animate
瞬时类——ActionInstant
基本动作
回调函数包装器
Cocos2d中常见的动作
Cocos2d中常见的Action
动作 | Action |
---|---|
位置移动 | MoveBy、MoveTo |
缩放大小 | ScaleBy、ScaleTo |
旋转 | RotateBy、RotateTo |
淡入淡出 | FadeIn、FadeOut |
显示隐藏 | Show、Hide |
闪烁 | Blink |
色彩混合 | TintBy、TintTo |
延时类中By和To的区别
By算的是相对于节点对象的当前位置,To算的是绝对位置,不考虑当前节点对象在哪。
**创建动作:*所有延时类的时间单位都是秒
里氏替换原则:
任何基类可以出现的地方,子类一定可以出现。
Action moveAction = MoveBy::create(2.f,Vec2(visibleSize.width / 2, 0));
下面这句代码用到了里氏替换原则
执行动作:同一个动作不能执行两次,两个按钮创建了一个动作让他移动,如果两个都想用那就需要克隆
不能两个节点对应同一个Action实例
sprite->runAction(moveAction);
停止动作:
sprite->stopActionByTag(1000);
sprite->stopAllAction();
ActionDemo.h
#pragma once
#include"cocos2d.h"
class ActionScene:public Scene
{
public:
CREATE_FUNC(ActionScene);
virtual bool init();
}
ActionDemo.cpp
bool ActionScene::init()
{
if(!Scene::init())return false;
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 position = Vec2(visibleSize / 2);
//创建一个动作演示示例
//呈持续2秒钟,水平移动100像素
//moveBy第二个参数;相对于当前位置移动的位移
Action* moveByAction = MoveBy::create(20.f,Vec2(100.f,0));
//moveTo第二个参数;移动的终点坐标(移动到指定位置)
Action* moveToAction = MoveTo::create(2.f,Vec2(position.x + 100.f,position.y));
//创建一个精灵的演示动作
auto polygonInfo = AutoPolygon::generatePolygon("bg/bg_05.png",Rect(0,0,437,437));
auto sprite = Sprite::create(polygonInfo);
sprite->setPosition(position);
sprite->setScale(0.3f);//缩放到0.3,缩放了0.7
this->addChild(sprite);
sprite->runAction(moveByAction);
//一个动作不能被两个精灵同时执行
auto cloneSprite = Sprite::create(polygonInfo);
cloneSprite ->setPosition(Vec2(position) - Vec2(100,100));
cloneSprite ->setScale(0.3f);
this->addChild(cloneSprite);
//可以代替moveToAction不支持反转的方案,从而实现
//两个精灵同时执行一个动作
cloneSprite ->runAction(MoveBy::create(2.f,Vec2(100.f,0)));
//moveToAction 是不能反转的
Action* reverseAction = moveByAction->reverse();
sprite->runAction(reverseAction);
return true;
}
重复执行动作——Repeat
动作类型为有限时间动作类
Action* moveAction = MoveBy::create(0.5f,Vec2(20,0));
sprite->runAction(Repeat::create(moveAction,2));
永久执行——RepeatForever
动作类型为时间间隔动作类
Action* moveAction = MoveBy::create(0.5f,Vec2(20,0));
sprite->runAction(RepeatForever::create(moveAction));
ActionDemo.cpp
bool ActionScene::init()
{
if(!Scene::init())return false;
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 position = Vec2(visibleSize / 2);
Action* moveByAction = MoveBy::create(20.f,Vec2(100.f,0));
Action* moveToAction = MoveTo::create(2.f,Vec2(position.x + 100.f,position.y));
//创建一个精灵的演示动作
auto polygonInfo = AutoPolygon::generatePolygon("bg/bg_05.png",Rect(0,0,437,437));
auto sprite = Sprite::create(polygonInfo);
sprite->setPosition(position);
sprite->setScale(0.3f);//缩放到0.3,缩放了0.7
this->addChild(sprite);
//这里必须要用FiniteTimeAction 动作类型为有限时间动作类
FiniteTimeAction* moveAction=MoveBy::create(2.f,Vec2(100.f,0));
//第二个参数表示,这个动作执行两次
//sprite->runAction(Repeat::create(moveAction,2));
ActionInterval* foeverAction = dynamic_cast<FiniteTimeAction*>(moveAction->clone());
sprite->runAction(RepeatForever::create(foeverAction));
return true;
}
多个动作的执行——序列
多个动作依次执行——auto action = Sequence::createWithTwoAction(
RotateBy::create(.5f,10.f),
DelayTime::create(.5f));
多个动作同时执行——Spawn
auto action = Spawn::createWithTwoAction(
RotateBy::create(.5f,10.f),
DelayTime::create(1.f));
ActionDemo.cpp
bool ActionScene::init()
{
if(!Scene::init())return false;
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 position = Vec2(visibleSize / 2);
Action* moveByAction = MoveBy::create(20.f,Vec2(100.f,0));
Action* moveToAction = MoveTo::create(2.f,Vec2(position.x + 100.f,position.y));
//创建一个精灵的演示动作
auto polygonInfo = AutoPolygon::generatePolygon("bg/bg_05.png",Rect(0,0,437,437));
auto sprite = Sprite::create(polygonInfo);
sprite->setPosition(position);
sprite->setScale(0.3f);//缩放到0.3,缩放了0.7
this->addChild(sprite);
ActionInterval*moveAction=MoveBy::create(2.f,Vec2(100.f,0));
ActionInterval*fadeout = FadeOut::create(1.f);
//演示Sequence序列的使用
//sprite->runAction(Sequence::create(
//moveAction,//移动一段距离
//fadeout,//淡出
//nullptr));
//sprite->runAction(Sequence::createWithTwoActions(
//moveAction,//移动一段距离
//fadeout//淡出
//));
//演示Spawn序列的使用
Spawn*spawn = Spawn::create(moveAction,fadeout,nullptr);
sprute->runAction(spawn);
return true;
}
帧动画
Animate类
加载图集资源
auto cache = SpriteFrameCache::getInstance();
cache->addSpriteFramesWithFile("vampire/vampire.plist");
创建帧动画精灵
Sprite* vampireSprite = Sprite::createWithSpriteFrameName("1");
创建帧动画
Vector<SpriteFrame*>images;
for(int i = 1;i <= 8 ; i++){
images.pushBack(cache->getSpriteFrameByName(Value(i).asString()))
}
Animation* _animation = Animation::createWithSpriteFrames(images,1.f/8);
vimpireSprite->runAction(RepeatForever::create(Animate::create(_animation)));
//演示帧动画
ActionDemo.cpp
bool ActionScene::init()
{
if(!Scene::init())return false;
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 position = Vec2(visibleSize / 2);
Action* moveByAction = MoveBy::create(20.f,Vec2(100.f,0));
Action* moveToAction = MoveTo::create(2.f,Vec2(position.x + 100.f,position.y));
//演示帧动画
auto cache = SpriteFrameCache::getInstance();
cache ->addSpriteFramesWithFile("vampire/vamp.plist");
Sprite*vampireSprite = Sprite::createWithSpriteFrameName("1");
vampireSprite ->setPosition(position);
this->addChild(vampireSprite);
//创建精灵帧
Vector<SpriteFrame*>images;
for(int i = 1;i <= 8 ; i++){
images.pushBack(cache->getSpriteFrameByName(Value(i).asString()));
}
//第二个参数表示1秒钟播放八张图片
Animation* animation = Animation::createWithSpriteFrames(images,1.f/images.size());
Animate* animate = Animate::create(animation);
//只运行一次
//vimpireSprite->runAction(animation);
//会一直运行
vimpireSprite->runAction(RepeatForever::create(animate));
return true;
}
回调函数包装器
使用动作执行的方式调用函数
注意:回调函数一般是在特定的时间点或事件之后执行
四种回调函数包装器
CallFunc
CallFunc::create(CC_CALLBACK_0(Node::removeFromParent,//函数指针
sprite))
//lamda表达式
CallFuncN::create(sprite{
sprite->removeFromParent();});
CallFuncND
CallFuncO
ActionDemo.cpp
bool ActionScene::init()
{
if(!Scene::init())return false;
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 position = Vec2(visibleSize / 2);
Action* moveByAction = MoveBy::create(20.f,Vec2(100.f,0));
Action* moveToAction = MoveTo::create(2.f,Vec2(position.x + 100.f,position.y));
//演示帧动画
auto cache = SpriteFrameCache::getInstance();
cache ->addSpriteFramesWithFile("vampire/vamp.plist");
Sprite*vampireSprite = Sprite::createWithSpriteFrameName("1");
vampireSprite ->setPosition(position);
this->addChild(vampireSprite);
//创建精灵帧
Vector<SpriteFrame*>images;
for(int i = 1;i <= 8 ; i++){
images.pushBack(cache->getSpriteFrameByName(Value(i).asString()));
}
//第二个参数表示1秒钟播放八张图片
Animation* animation = Animation::createWithSpriteFrames(images,1.f/images.size());
Animate* animate = Animate::create(animation);
//演示一个回调函数包装器
vampireSprite->runAction(Sequence:createWithTwoActions(
Repeat::create(animate,3),
//vampireSprite只是一个局部变量所以必须传进来不然没办法移除
CallFunc::create([vampireSprite]()
{
vampireSprite->removeFromParent();
})
));
return true;
}
综合案例:翻卡牌
获得卡牌时,卡背旋转的同时放大出现
点击卡牌时,卡牌翻转显示正面
卡牌正面播放人物动画
CardScene.h
#pragma once
#include"cocos2d.h"
#include"ui/UIButton.h"
class CardScene:public Scene
{
public:
CREATE_FUNC(ActionScene);
virtual bool init();
private:
//卡牌
Button * _button;
//帧动画精灵
Sprite* _sprite;
//卡牌出现
void showCard();
//点击翻转卡牌
void getCard();
//帧动画播放
void playAnimation();
}
CardScene.cpp
bool CardScene::init()
{
if(!Scene::init())return false;
//演示翻转卡牌动画
//添加一个背景
Size visibleSize = Director::getInstance()->getVisibleSize();
Sprite*sprite = Sprite::create("card/bg.jpg");
sprite->setPosition(Vec2(visibleSize / 2));
sprite->setContentSize(visibleSize);
this->addChild(sprite,1);
//创建卡牌
_button = Button::create("card/card/jpg","card/card/jpg","card/card/jpg");
_button ->setPosition(aprite->getPosition());
_button->setScale(.1f);
_button->addClickEventListener([this](Ref*ref)
{
//禁用卡牌的点击事件
_button->setEnabled(false);
//点击卡牌播放翻牌动作
getCard();
});
this->addChild(_button,2);
//卡牌显示动画
showCard();
return true;
}
//卡牌出现
void CardScene::showCard()
{
//旋转的同时放大卡牌360°一圈
auto rotateAction = RotateTo::create(0.5f,2160);
//放大到0.5,时间也是0.5
auto scaleAction = ScaleTo::create(0.5f,0.5f);
_button->runAction(Spawn::createWithTwoActions(rotateAction,scaleAction));
}
//点击翻转卡牌
void CardScene::getCard()
{
//水平缩放到0,再加载卡面和帧动画
auto sacleXAction = ScaleTo::create(0.5f,0,0.5f);
auto callback = CallFunc::create([this]()
{
//卡背变卡面
_button->loadTextures("card/card_bg.png","card/card_bg.png","card/card_bg.png");
//播放帧动画
playAnimation();
});
//继续水平翻转
auto scaleXActionEnd = ScaleTo::create(0.5f,-0.5f,0.5f);
_button->runAction(Sequence::create(
scaleXAction,//缩小到0
callback,//回调
scaleXActionEnd,//翻转过来
nullptr
));
}
//帧动画播放
void CardScene::playAnimation()
{
auto cache = SpriteFrameCache::getInstance();
cache->addSpriteFramesWithFile("card/animate.plist");
//创建一个帧动画
_sprite = Sprite::createWithSpriteFrameName("0.png");
_sprite->setPosition(Vec2(_button->getCotentSize() / 2) + Vec2(0,50));
_button->addChild(_sprite);
_button->setEnabled(false);
//创建精灵帧集合
Vector<SpriteFrame*>images;
for(int i=0;i<6;i++)
{
//注意plist里边的键是纯数字还是还有.png什么的,如果有.png那么这里需要连接下
images.pushBack(cache->getSpriteFrameByName(Value(i).asString() + ".png"));
}
//此处注意第二个参数 间隔时间 1秒钟播放一次动画
Animation* animation = Animation::createWithSpriteFrames(images,1.f/images.size());
auto animate = Animation::create(animation);
_sprite->runAction(RepeatForever::create(animate));
}