cocos2dx学习之路(八)——动作、动画 Action

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));
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恒德久远

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值