cocos2d-x库的动作(Action)

2024-06-17 11:08
文章标签 动作 action cocos2d

本文主要是介绍cocos2d-x库的动作(Action),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

从本章开始,我们开始讲解cocos2d-x库的动作(Action)。游戏的世界是一个动态的世界:无论是主角精灵还是NPC精灵都处于不断的运动当中,甚至是背景中漂流的树叶,随风而动的小草。这些明显的或者不明显的运动构成了我们栩栩如生的游戏世界。

仔细研究游戏中精灵的运动,我们发现:所有这样的运动都可以细分为若干个基本动作和基本动作的组合。通过进一步扩展,我们可以将同一精灵的更多动作和不同精灵之间的不同动作连贯起来,形成关于整个运动世界的连续模拟。

我们给出示例ZYG003,展示cocos2d-x支持的主要动作:

基本动作

从技术上来说,基本动作的本质就是改变某个图形对象的属性:位置、角度、大小等。cocos2d-x提供超过20种基本动作供我们使用。根据改变完成所需的时间,可以分为瞬时动作和延时动作。其中,延时动作的执行速度又可以按照不同的方式来改变(位置、大小、颜色、闪烁……)。
再进一步介绍基本动作之前,我们先来简单明确一下动作是如何与CCNode关联起来的。CCNode有一个成员函数叫runAction,定义为:

复制代码
1 /** Executes an action, and returns the action that is executed.
2 The node becomes the action's target.
3 @warning Starting from v0.8 actions don't retain their target anymore.
4 @since v0.7.1
5 @return An Action pointer
6 */
7 CCAction* runAction(CCAction* action);
复制代码

此接口确保所有的精灵都可以执行各种动作。也正是为了服从这个接口的定义,导致后续各种组合动作也都从CCAction派生。

下面的代码是通常调用某个动作的方法:

复制代码
1 CCSize s = CCDirector::sharedDirector()->getWinSize();
2 // 创建动作
3 CCActionInterval *actionTo = CCMoveTo::actionWithDuration(2.0f, ccp(s.width - 40.0f, s.height - 40.0f));
4 // 使用动作(tamara是一个CCSprite指针)
5 tamara->runAction(actionTo);
复制代码

瞬时动作

顾名思义,瞬时动作就是不需要时间,马上就完成的动作。瞬时动作的共同基类是CCActionInstant。

cocos2d-x提供以下瞬时动作:

瞬时动作大都有与之对应的属性设置方法,之所以作为一个动作来实现,是为了可以与其他动作形成一个连续动作。下面来看一下瞬时动作的使用。

放置 - CCPlace

效果类似于setPosition(ccp(x, y))。示例代码如下:

复制代码
1 void InstantActionLayer::onPlace(CCObject* pSender)
2 {
3     CCSize s = CCDirector::sharedDirector()->getWinSize();
4     // 理论上使用伪随机数前应该srand一下,但是知易的例子中没有,不知道是不是故意这么设计的。
5     // 如果使用time(NULL)初始化伪随机数种子,要注意time_t有可能是64位的!
6     CCPoint p = ccp(CCRANDOM_0_1() * s.width, CCRANDOM_0_1() * s.height);
7     flight->runAction(CCPlace::actionWithPosition(p));
8 }
复制代码

隐藏 - CCHide
效果类似于setIsVisible(false)。示例代码如下:

1 void InstantActionLayer::onHide(CCObject* pSender)
2 {
3     flight->runAction(CCHide::action());
4 }

显示 - CCShow
效果类似于setIsVisible(true)。示例代码如下:

1 void InstantActionLayer::onShow(CCObject* pSender)
2 {
3     flight->runAction(CCShow::action());
4 }

可见切换 - CCToggleVisibility
效果类似于setIsVisible(!getIsVisible())。示例代码如下:

1 void InstantActionLayer::onToggle(CCObject* pSender)
2 {
3     flight->runAction(CCToggleVisibility::action());
4 }

水平翻转 - CCFlipX
效果类似于setFlipX(true/false)。示例代码如下:

1 void InstantActionLayer::onFlipX(CCObject* pSender)
2 {
3     flight->runAction(CCFlipX::actionWithFlipX(true));
4 }

垂直翻转 - onFlipY
效果类似于setFlipY(true/false)。示例代码如下:

1 void InstantActionLayer::onFlipY(CCObject* pSender)
2 {
3     flight->runAction(CCFlipY::actionWithFlipY(true));
4 }

还有两个较为特殊的动作(网格重用 - CCReuseGrid|停止网格 - CCStopGrid),我们以后介绍。

延时动作

延时动作就是指动作的完成需要一段时间。因此,几乎所有的延时动作都使用执行时间作为第一个参数,它们有着共同的基类CCActionInterval。

cocos2d-x中常用的延时动作:

这里有一个简单的类命名规则:
CCXxxxTo - 绝对动作,执行的结果与当前的状态关系不密切;
CCXxxxBy - 相对动作,在当前的状态上执行某种动作,执行的结果与当前状态是紧密相关的。

移动到 - CCMoveTo
移动 - CCMoveBy
跳跃到 - CCJumpTo
参数为终点位置、跳跃高度和跳跃次数。
跳跃 - CCJumpBy
贝赛尔曲线 - CCBezierBy
支持三次贝赛尔曲线:P0-起点,P1-起点切线方向,P2-终点切线方向,P3-终点。


首先设置贝塞尔参数,然后执行。
放大到 - CCScaleTo
放大 - CCScaleBy
如果参数为小数,那就是缩小了。
旋转到 - CCRotateTo
旋转 - CCRotateBy
闪烁 - CCBlink
色调变化到 - CCTintTo
色调变换 - CCTintBy
变暗到 - CCFadeTo
由无变亮 - CCFadeIn
由亮变无 - CCFadeOut

组合动作

按照一定的次序将上述基本动作组合起来,形成连贯的一套组合动作。组合动作包括以下几类:

序列 - CCSequence

序列的使用非常简单,该类从CCActionInterval派生,本身就可以被CCNode对象执行。该类的作用就是线性排列若干个动作,然后按先后次序逐个执行。

复制代码
 1 void CompositionActionLayer::onSequence(CCObject* pSender)
 2 {
 3     CCSize s = CCDirector::sharedDirector()->getWinSize();
 4     // 创建5个动作
 5     CCFiniteTimeAction *action0 = CCPlace::actionWithPosition(ccp(s.width / 2, 50));
 6     CCFiniteTimeAction *action1 = CCMoveTo::actionWithDuration(1.2f, ccp(s.width - 50.0f, s.height - 50.0f));
 7     CCFiniteTimeAction *action2 = CCJumpTo::actionWithDuration(1.2f, ccp(150, 50), 30.0f, 5);
 8     CCFiniteTimeAction *action3 = CCBlink::actionWithDuration(1.2f, 3);
 9     CCFiniteTimeAction *action4 = CCTintBy::actionWithDuration(0.5f, 0, 255, 255);
10     // 将5个动作组合为一个序列,注意不要忘了用NULL结尾。
11     flight->runAction(CCSequence::actions(action0, action1, action2, action3, action4, action0, NULL));
12 }
复制代码

同步 - CCSpawn

同步的使用非常简单,该类也是从CCActionInterval派生,可以被CCNode对象执行。该类的作用就是同时并列执行若干个动作,但要求动作本身是可以同时执行的,比如:移动式翻转、变色、缩放等。
需要特别注意的是,同步执行最后完成的时间由基本动作中用时最大者决定。

复制代码
 1 void CompositionActionLayer::onSpawn(CCObject* pSender)
 2 {
 3     CCSize s = CCDirector::sharedDirector()->getWinSize();
 4     flight->setRotation(0.0f);
 5     flight->setPosition(ccp(s.width / 2, 50));
 6     // 创建4个需要并行的动作,确保动作用时可组合。(action1/action2/sequence的执行时间都是2秒)
 7     CCFiniteTimeAction *action1 = CCMoveTo::actionWithDuration(2.0f, ccp(s.width - 50.0f, s.height - 50.0f));
 8     CCFiniteTimeAction *action2 = CCRotateTo::actionWithDuration(2.0f, 180.0f);
 9     CCFiniteTimeAction *action3 = CCScaleTo::actionWithDuration(1.0f, 4.0f);
10     CCFiniteTimeAction *action4 = CCScaleBy::actionWithDuration(1.0f, 0.5f);
11     CCFiniteTimeAction *sequence = CCSequence::actions(action3, action4, NULL);
12     // 创建并执行同步动作。
13     flight->runAction(CCSpawn::actions(action1, action2, sequence, NULL));
14 }
复制代码

重复有限次数 - CCRepeat

CCRepeat用来将某一动作重复有限次数,示例代码如下:

复制代码
 1 void CompositionActionLayer::onRepeat(CCObject* pSender)
 2 {
 3     CCSize s = CCDirector::sharedDirector()->getWinSize();
 4     flight->setRotation(0.0f);
 5     flight->setPosition(ccp(s.width / 2, 50));
 6     // 创建动作序列
 7     CCFiniteTimeAction *action1 = CCMoveTo::actionWithDuration(2.0f, ccp(s.width - 50.0f, s.height - 50.0f));
 8     CCFiniteTimeAction *action2 = CCJumpBy::actionWithDuration(2.0f, ccp(-400, -200), 30.0f, 5);
 9     CCFiniteTimeAction *action3 = CCJumpBy::actionWithDuration(2.0f, ccp(s.width / 2, 0), 20.0f, 3);
10     CCFiniteTimeAction *sequence = CCSequence::actions(action1, action2, action3, NULL);
11     // 重复运行上述动作序列3次
12     flight->runAction(CCRepeat::actionWithAction(sequence, 3));
13 }
复制代码

反动作 - Reverse

反动作就是反向(逆向)执行某个动作,支持针对动作序列的反动作序列。反动作不是一个专门的类,而是CCFiniteTimeAction引入的一个接口。不是所有的类都支持反动作,CCXxxxTo类通常不支持反动作,而CCXxxxBy类通常支持,示例如下:

复制代码
 1 void CompositionActionLayer::onReverse(CCObject* pSender)
 2 {
 3     CCSize s = CCDirector::sharedDirector()->getWinSize();
 4     flight->setRotation(0.0f);
 5     flight->setPosition(ccp(s.width / 2, 50));
 6 
 7     CCFiniteTimeAction *action1 = CCMoveBy::actionWithDuration(2.0f, ccp(190, 220));
 8     // 创建某个动作的反动作
 9     CCFiniteTimeAction *action2 = action1->reverse();
10 
11     flight->runAction(CCRepeat::actionWithAction(CCSequence::actions(action1, action2, NULL), 2));
12 }
复制代码

动画 - CCAnimate

动画就是让精灵自身连续执行一段影像,形成模拟运动的效果:行走时的状态,打斗时的状态等。

复制代码
 1 void CompositionActionLayer::onAnimation(CCObject* pSender)
 2 {
 3     CCSpriteBatchNode *mgr = static_cast<CCSpriteBatchNode *>(this->getChildByTag(4));
 4 
 5     CCAnimation *animation = CCAnimation::animation();
 6     animation->setName("flight");
 7     animation->setDelay(0.2f);
 8     for (int i = 0; i < 3; ++i)
 9     {
10         // 定义每一帧的内容
11         float x = static_cast<float>(i % 3);
12         animation->addFrameWithTexture(mgr->getTexture(), CCRectMake(x * 32, 0, 31, 30));
13     }
14     // 创建并执行动画效果,而且要重复10次。
15     CCAnimate *action = CCAnimate::actionWithAnimation(animation);
16     flight->runAction(CCRepeat::actionWithAction(action, 10));
17 }
复制代码

无限重复 - CCRepeatForever

在CCRepeatForever Class Reference中,有这样一条警告“Warning: This action can't be Sequenceable because it is not an IntervalAction”,而实际上它的确是派生自CCActionInterval,这真有点儿把我也搞懵了。
仅从其本意来说,该类的作用就是无限期执行某个动作或动作序列,直到被停止。因此无法参与序列和同步,自身也无法反向执行(但是你可以将某一动作反向,然后无限重复执行)。

复制代码
 1 void CompositionActionLayer::onRepeatForever(CCObject* pSender)
 2 {
 3     CCSpriteBatchNode *mgr = static_cast<CCSpriteBatchNode *>(this->getChildByTag(4));
 4     // 飞行喷火模拟动画
 5     CCAnimation *animation = CCAnimation::animation();
 6     animation->setName("flight");
 7     animation->setDelay(0.1f);
 8     for (int i = 0; i < 3; ++i)
 9     {
10         float x = static_cast<float>(i % 3);
11         animation->addFrameWithTexture(mgr->getTexture(), CCRectMake(x * 32, 0, 31, 30));
12     }
13     CCAnimate *action = CCAnimate::actionWithAnimation(animation);
14     // 将该动画作为精灵的本征动画,一直运行。
15     flight->runAction(CCRepeatForever::actionWithAction(action));
16 
17     CCSize s = CCDirector::sharedDirector()->getWinSize();
18     flight->setRotation(0.0f);
19     flight->setPosition(ccp(100, 50));
20 
21     // 创建第二个连续无限期动作序列,叠加两者形成完整效果。
22     ccBezierConfig bezier;
23     bezier.controlPoint_1 = ccp(0, s.height / 2);
24     bezier.controlPoint_2 = ccp(300, -s.height / 2);
25     bezier.endPosition = ccp(300, 100);
26     CCFiniteTimeAction *action1 = CCBezierBy::actionWithDuration(3.0f, bezier);
27     CCFiniteTimeAction *action2 = CCTintBy::actionWithDuration(0.5f, 0, 255, 255);
28     CCFiniteTimeAction *action3 = CCSpawn::actions(action1, CCRepeat::actionWithAction(action2, 4), NULL);
29     CCFiniteTimeAction *action4 = CCSpawn::actions(action1->reverse(), CCRepeat::actionWithAction(action2, 4), NULL);
30     // CCSequence的actions成员函数返回的是CCFiniteTimeAction指针类型,
31     // 而CCRepeatForever的actionWithAction接受的是CCActionInterval指针类型,
32     // 所以这里需要强转一下,转成CCSequence指针类型,
33     // 只要保证序列中有2个或2个以上的动作,这么做是绝对没有问题的。
34     flight->runAction(CCRepeatForever::actionWithAction(static_cast<CCSequence *>(CCSequence::actions(action3, action4, NULL))));
35 }
复制代码

速度变化

基本动作和组合动作实现了针对精灵的各种运动和动画效果,但它们的速度通常是恒定不变的。通过CCActionEase类系和CCSpeed类,我们可以很方便地改变精灵执行动作的速度,是由快至慢还是由慢至快。

CCEaseIn - 由慢至快(速度线性变化)
CCEaseOut - 由快至慢
CCEaseInOut - 由慢至快再由快至慢
CCEaseSineIn - 由慢至快(速度正弦变化)
CCEaseSineOut - 由快至慢
CCEaseSineInOut - 由慢至快再由快至慢
CCEaseExponentialIn - 由慢至极快(速度指数级变化)
CCEaseExponentialOut - 由极快至慢
CCEaseExponentialInOut - 由慢至极快再由极快至慢
CCSpeed - 人工设定速度,还可通过setSpeed不断调整。

扩展动作

我们已经掌握了各种各样的动作,也可以按照不同的速度要求修改动作执行的时间,cocos2d-x还提供了针对现有动作的扩展,以实现各种灵活的效果。

延时 - CCDelayTime

通过CCDelayTime,我们可以在动作序列中增加一个时间间歇。

复制代码
1 void ExtendActionLayer::onDelay(CCObject* pSender)
2 {
3     CCFiniteTimeAction *action1 = CCMoveBy::actionWithDuration(1.2f, ccp(200, 200));
4     CCFiniteTimeAction *action2 = action1->reverse();
5     // 实现一个等待间歇
6     flight->runAction(CCSequence::actions(action1, CCDelayTime::actionWithDuration(1.0f), action2, NULL));
7 }
复制代码

函数调用

在动作序列中间或者末尾调用某个函数,执行任何任务:动作、状态修改等。在cocos2d-x中,调用函数的动作一共有4种。

1.CCCallFunc

仅函数调用,无任何参数。

复制代码
 1 void ExtendActionLayer::onCallBack1()
 2 {
 3     flight->runAction(CCTintBy::actionWithDuration(0.5f, 255, 0, 255));
 4 }
 5 
 6 void ExtendActionLayer::onCallFunc(CCObject* pSender)
 7 {
 8     CCFiniteTimeAction *action1 = CCMoveBy::actionWithDuration(2.0f, ccp(200, 200));
 9     CCFiniteTimeAction *action2 = action1->reverse();
10     CCFiniteTimeAction *actionF = CCCallFunc::actionWithTarget(this, callfunc_selector(ExtendActionLayer::onCallBack1));
11     flight->runAction(CCSequence::actions(action1, actionF, action2, NULL));
12 }
复制代码
2.CCCallFuncN

调用函数,并将当前对象的指针(CCNode指针)作为第一个参数传递进去。

复制代码
 1 void ExtendActionLayer::onCallBack2(CCNode* pSender)
 2 {
 3     // 在这个例子里,pSender就是flight,因为是他执行了那个actionF
 4     pSender->runAction(CCTintBy::actionWithDuration(1.0f, 255, 0, 255));
 5 }
 6 
 7 void ExtendActionLayer::onCallFuncN(CCObject* pSender)
 8 {
 9     CCFiniteTimeAction *action1 = CCMoveBy::actionWithDuration(2.0f, ccp(200, 200));
10     CCFiniteTimeAction *action2 = action1->reverse();
11     CCFiniteTimeAction *actionF = CCCallFuncN::actionWithTarget(this, callfuncN_selector(ExtendActionLayer::onCallBack2));
12     flight->runAction(CCSequence::actions(action1, actionF, action2, NULL));
13 }
复制代码
3.CCCallFuncND

在前一种方式的基础上增加一个数据参数,这是void指针类型。

复制代码
 1 void ExtendActionLayer::onCallBack3(CCNode* pSender, void* pData)
 2 {
 3     pSender->runAction(CCTintBy::actionWithDuration(static_cast<float>((int)pData), 255, 0, 255));
 4 }
 5 
 6 void ExtendActionLayer::onCallFuncND(CCObject* pSender)
 7 {
 8     CCFiniteTimeAction *action1 = CCMoveBy::actionWithDuration(2.0f, ccp(200, 200));
 9     CCFiniteTimeAction *action2 = action1->reverse();
10     // 这里直接将整数常量强转成(void *)类型似乎有欠妥当,但对这些Action的生命周期不太清楚,稍后深入一下。
11     CCFiniteTimeAction *actionF = CCCallFuncND::actionWithTarget(this, callfuncND_selector(ExtendActionLayer::onCallBack3), (void *)2);
12     flight->runAction(CCSequence::actions(action1, actionF, action2, NULL));
13 }
复制代码
4.CCCallFuncO

调用函数,并传递一个CCObject指针作为参数。这个似乎不太常用,资料比较少,以后再深入。

小结

至此,我们对cocos2d-x支持的动作有了整体了解。动作是我们的好帮手,它让游戏世界充满生机。在后面的章节中,我们会对部分动作以及动作系统继续深入。

示例代码下载:
http://files.cnblogs.com/cocos2d-x/ZYG003.rar

这篇关于cocos2d-x库的动作(Action)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1069271

相关文章

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物,今天我们实现一下人物实现移动和跳起,依次点击,我们准备创建一个C#文件 创建好我们点击进去,就会跳转到我们的Vision Studio,然后输入这些代码 using UnityEngine;public class Move : MonoBehaviour // 定义一个名为Move的类,继承自MonoBehaviour{private Rigidbo

Unable to instantiate Action, goodsTypeAction, defined for 'goodsType_findAdvanced' in namespace '/

报错: Unable to instantiate Action, goodsTypeAction,  defined for 'goodsType_findAdvanced' in namespace '/'goodsTypeAction......... Caused by: java.lang.ClassNotFoundException: goodsTypeAction.......

用ajax json给后台action传数据要注意的问题

必须要有get和set方法   1 action中定义bean变量,注意写get和set方法 2 js中写ajax方法,传json类型数据 3 配置action在struts2中

使用http-request 属性替代action绑定上传URL

在 Element UI 的 <el-upload> 组件中,如果你需要为上传的 HTTP 请求添加自定义的请求头(例如,为了通过身份验证或满足服务器端的特定要求),你不能直接在 <el-upload> 组件的属性中设置这些请求头。但是,你可以通过 http-request 属性来自定义上传的行为,包括设置请求头。 http-request 属性允许你完全控制上传的行为,包括如何构建请求、发送请

Cocos2d-x自适应Android屏幕分辨

ndroid下分辨率太多,不太可能为每种分辨率做一套资源,目前一般来说比较流行的是320*480, 800*400, 854*400。当然现在720P的也出来了,但至少目前不是主流机型^_^. 对于不支持的分辨率,我希望的是能够按照屏幕大小按比例缩放,即有了下面的代码。 1:ViewAutoScale 写了一个ViewAutoScale函数,如下:   #include "ViewAuto

cocos2d-x Android实现广告条竖立放置

 2:实现 原理:将屏幕设置为竖屏,然后CCDirector::setDeviceOrientation()设置为cocos2d-x为横屏。            在这种转屏模式下,控件是不会旋转的 缺点:所有Android原生控件仍然是竖立的 注意事项: ccTouchesBegan,ccTouchesMoved, ccTouchesEnded传入的坐标值仍然是屏幕坐标

Flink整合Oozie Shell Action 提交任务带Kerberos认证

最近这段时间一直在忙新集群迁移,上了最新的cdh6.3.0 于是Flink 提交遇到了许多的问题,还好有cloudera License 有了原厂的帮助和社区的伙伴,问题解决起来快了不少。 集群具体情况是 CDH6.3.0 Flink1.8.1,整个数据平台全部组件都上了kerberos和ldap因为要过认证,所以任务提交方法我们选择统一Oozie提交任务,并且因为kerberos认证,还需要F

jsp技术(内置对象,动作标签,指令)

一、 九大对象:   内置对象(又叫隐含对象,有9个内置对象):不需要预先声明就可以在脚本代码和表达式中随意使用   1-out:   javax.servlet.jsp.JspWriter类型,代表输出流的对象。作用域为page(页面执行期)   request:javax.servlet.ServletRequest的子类型,此对象封装了由WEB浏览器或其它客户端生成地HTTP

Servlet mapping specifies an unknown servlet name Action

看一下web.xml中<servlet-mapping>有没有配错

Unity3D ARPG(动作角色扮演游戏)设计与实现详解

动作角色扮演游戏(Action Role-Playing Game, ARPG)结合了传统角色扮演游戏(RPG)的深度与动作游戏(Action Game)的即时反应和流畅战斗体验。Unity3D 作为一款强大的跨平台游戏开发引擎,为开发者提供了丰富的工具和资源来创建高质量的 ARPG 游戏。本文将详细介绍如何使用 Unity3D 设计和实现一个基本的 ARPG 游戏,包括技术选型、游戏架构、关键系