Action类如其名,它可以改变Node对象的属性,Action对象是随着时间改变Node的属性。任何一个以Node为基类的对象都有可执行的动作对象。例如,你可以在一个时间段内将Sprite精灵从一个位置移动到另一个位置。
如下为MoveTo和MoveBy两个动作的实例:
|
1
2
3
4
5
6
7
|
//
Move sprite to position 50,10 in 2 seconds.auto
moveTo = MoveTo::create(2, Vec2(50, 10));mySprite1->runAction(moveTo);//
Move sprite 20 points to right in 2 secondsauto
moveBy = MoveBy::create(2, Vec2(20,0));mySprite2->runAction(moveTo); |
By和To的区别
或许你已经注意到了每个动作都有By和To两个状态。为什么呢?因为它们所执行的结果是不同的。By相当于这个节点是相对的。To是绝对的,意思是它并不考虑到这个节点的当前状态。让我们看一个具体的例子:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
auto
mySprite = Sprite::create("mysprite.png");mySprite->setPosition(Vec2(200,
256));//
MoveBy - lets move the sprite by 500 on the x axis over 2 seconds//
MoveBy is relative - since x = 200 + 200 move = x is now 400 after the moveauto
moveBy = MoveBy::create(2, Vec2(500, mySprite->getPositionY()));//
MoveTo - lets move the new sprite to 300 x 256 over 2 seconds//
MoveTo is absolute - The sprite gets moved to 300 x 256 regardless of//
where it is located now.auto
moveTo = MoveTo::create(2, Vec2(300, mySprite->getPositionY()));auto
seq = Sequence::create(moveBy, delay, moveTo, nullptr);mySprite->runAction(seq); |

基本动作以及如何执行动作
基本动作通常是一个单一的动作,只完成一个目标。让我们看看几个例子:
移动(Move)
在规定的时间内移动Node的位置。
|
1
2
3
4
5
6
7
8
9
10
11
|
auto
mySprite = Sprite::create("mysprite.png");//
Move a sprite to a specific location over 2 seconds.auto
moveTo = MoveTo::create(2, Vec2(50, 0));mySprite->runAction(moveTo);//
Move a sprite 50 pixels to the right, and 0 pixels to the top over 2 seconds.auto
moveBy = MoveBy::create(2, Vec2(50, 0));mySprite->runAction(moveBy); |

旋转(Rotate)
在2秒内顺时针旋转Node。
|
1
2
3
4
5
6
7
8
9
|
auto
mySprite = Sprite::create("mysprite.png");//
Rotates a Node to the specific angle over 2 secondsauto
rotateTo = RotateTo::create(2.0f, 40.0f);mySprite->runAction(rotateTo);//
Rotates a Node clockwise by 40 degree over 2 secondsauto
rotateBy = RotateBy::create(2.0f, 40.0f);mySprite->runAction(rotateBy); |

缩放(Scale)
在两秒内将Node放大10倍
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
auto
mySprite = Sprite::create("mysprite.png");//
Scale uniformly by 3x over 2 secondsauto
scaleBy = ScaleBy::create(2.0f, 3.0f);mySprite->runAction(scaleBy);//
Scale X by 5 and Y by 3x over 2 secondsauto
scaleBy = ScaleBy::create(2.0f, 3.0f, 3.0f);mySprite->runAction(scaleBy);//
Scale to uniformly to 3x over 2 secondsauto
scaleTo = ScaleTo::create(2.0f, 3.0f);mySprite->runAction(scaleTo);//
Scale X to 5 and Y to 3x over 2 secondsauto
scaleTo = ScaleTo::create(2.0f, 3.0f, 3.0f);mySprite->runAction(scaleTo); |

淡入淡出
Node淡入
FadeIn修改透明度的值(0~255之间)。与之相反的动作是“淡出”
|
1
2
3
4
5
6
7
8
9
|
auto
mySprite = Sprite::create("mysprite.png");//
fades in the sprite in 1 secondsauto
fadeIn = FadeIn::create(1.0f);mySprite->runAction(fadeIn);//
fades out the sprite in 2 secondsauto
fadeOut = FadeOut::create(2.0f);mySprite->runAction(fadeOut); |

色调(Tint)
Tint使节点的NodeRGB从当前值改变到用户设置值。
|
1
2
3
4
5
6
7
8
9
|
auto
mySprite = Sprite::create("mysprite.png");//
Tints a node to the specified RGB valuesauto
tintTo = TintTo::create(2.0f, 120.0f, 232.0f, 254.0f);mySprite->runAction(tintTo);//
Tints a node BY the delta of the specified RGB values.auto
tintBy = TintBy::create(2.0f, 120.0f, 232.0f, 254.0f);mySprite->runAction(tintBy); |

动画(Animate)
通过Animate可以很容易地实现精灵的帧动画效果。只要简单的每隔一段时间替换_display frame_即可。如下例子:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
auto
mySprite = Sprite::create("mysprite.png");//
now lets animate the sprite we movedVector<SpriteFrame*>
animFrames;animFrames.reserve(12);animFrames.pushBack(SpriteFrame::create("Blue_Front1.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Front2.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Front3.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Left1.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Left2.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Left3.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Back1.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Back2.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Back3.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Right1.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Right2.png",
Rect(0,0,65,81)));animFrames.pushBack(SpriteFrame::create("Blue_Right3.png",
Rect(0,0,65,81)));//
create the animation out of the framesAnimation*
animation = Animation::createWithSpriteFrames(animFrames, 0.1f);Animate*
animate = Animate::create(animation);//
run it and repeat it forevermySprite->runAction(RepeatForever::create(animate)); |
很难以文字形式描述一个动画,所以请运行《开发者指南示例》中动作部分的代码查看动作效果。
减速(Easing)
Easing用一个给定的加速度来使动画更加顺畅。需要记住的是,无论速度快慢,ease动作总是同时开始和结束。在游戏中如果你想模拟一些物理特效,但又不想过度且麻烦地使用多个非常基本的动作,那么此时Ease动作将是模拟物理特效的一个很好的方法。这里有另一个给菜单和按钮添加动画的很好的例子。
下图显示了一些常用的减速功能:

Cocos2d-x支持上图中所显示的大部分减速功能。这些功能也是容易实现的。让我们一起看看一个特殊的用例。屏幕的上方添加一个Sprite对象,并使其上下跳动。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//
create a spriteauto
mySprite = Sprite::create("mysprite.png");//
create a MoveBy Action to where we want the sprite to drop from.auto
move = MoveBy::create(2, Vec2(200, dirs->getVisibleSize().height - newSprite2->getContentSize().height));auto
move_back = move->reverse();//
create a BounceIn Ease Actionauto
move_ease_in = EaseBounceIn::create(move->clone() );//
create a delay that is run in between sequence eventsauto
delay = DelayTime::create(0.25f);//
create the sequence of actions, in the order we want to run themauto
seq1 = Sequence::create(move_ease_in, delay, move_ease_in_back, delay->clone(),
nullptr);//
run the sequence and repeat forever.mySprite->runAction(RepeatForever::create(seq1)); |
运行“开发者指南示例”中的这部分的代码可以查看动作效果。
序列动作以及如何执行它
Sequence可以使一系列的动作对象按顺序执行。这一系列对象可以是任何数量的动作对象、函数,甚至是另外一个序列动作。函数?是的!Cocos2d-x中有一个CallFunc对象,它允许你创建一个function()函数并可以传递到Sequence中执行。这就允许你在序列动作对象中添加自己的函数功能,而不是仅仅局限于Cocos2d-x中提供的动作对象。如下例为序列动作被执行时的状态:

序列动作的例子
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
auto
mySprite = Sprite::create("mysprite.png");//
create a few actions.auto
jump = JumpBy::create(0.5, Vec2(0, 0), 100, 1);auto
rotate = RotateTo::create(2.0f, 10);//
create a few callbacksauto
callbackJump = CallFunc::create([](){log("Jumped!");});auto
callbackRotate = CallFunc::create([](){log("Rotated!");});//
create a sequence with the actions and callbacksauto
seq = Sequence::create(jump, callbackJump, rotate, callbackRotate, nullptr);//
run itmySprite->runAction(seq); |
那么,Sequence对象做了什么呢?
它可以按顺序执行如下动作:
Jump -> callbackJump -> Rotate -> callbackRotate
运行“开发者指南示例”中的代码查看动作效果。
Spawn
Spawn与Sequence类似,不同的是使用Spawn时所有动作是同时执行的。你可以有很多动作对象,甚至其他Spawn对象。

Spawn的作用与运行多个连续的runAction()语句所产生的结果是相同的。然而,使用Spawn的优点在于你可以将其放到一个序列中,从而实现特定的效果。而runAction()是不可以的。将Spawn和Sequence结合使用讲会实现很多强大的功能。
举例:
|
1
2
3
4
|
//
create 2 actions and run a Spawn on a Spriteauto
mySprite = Sprite::create("mysprite.png");auto
moveBy = MoveBy::create(10, Vec2(400,100)); |
使用Spawn:
|
1
2
3
|
//
running the above Actions with Spawn.auto
mySpawn = Spawn::createWithTwoActions(moveBy, fadeTo);mySprite->runAction(mySpawn); |
使用连贯的runAction()语句:
|
1
2
3
|
//
running the above Actions with consecutive runAction() statements.mySprite->runAction(moveBy);mySprite->runAction(fadeTo); |
两个产生的效果是相同的。但是,其中一个可以在Sequence中使用Spawn。如下流程图所示:

|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//
create a Spriteauto
mySprite = Sprite::create("mysprite.png");//
create a few Actionsauto
moveBy = MoveBy::create(10, Vec2(400,100));auto
fadeTo = FadeTo::create(2.0f, 120.0f);auto
scaleBy = ScaleBy::create(2.0f, 3.0f);//
create a Spawn to useauto
mySpawn = Spawn::createWithTwoActions(scaleBy, fadeTo);//
tie everything together in a sequenceauto
seq = Sequence::create(moveBy, mySpawn, moveBy, nullptr);//
run itmySprite->runAction(seq); |
运行“开发者指南示例”中的代码查看动作效果。
Reverse(逆序)
Reverse的作用完全像它的名字一样,例如运行一系列动作时,你完全可以调用reserve()函数使动作逆序执行。然而,这并不只是简单的逆序运行,实际上还将原始的Sequence和Spawn的属性也转换为逆序。
Using the Spawn example above reversing is simple. 上面Spawn中的例子使用逆序就会很简单:
|
1
2
|
//
reverse a sequence, spawn or actionmySprite->runAction(mySpawn->reverse()); |
大部分Action和Sequence对象都是可逆的!
使用很简单,但是让我们来验证一下是不是这样,如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//
create a Spriteauto
mySprite = Sprite::create("mysprite.png");mySprite->setPosition(50,
56);//
create a few Actionsauto
moveBy = MoveBy::create(2.0f, Vec2(500,0));auto
scaleBy = ScaleBy::create(2.0f, 2.0f);auto
delay = DelayTime::create(2.0f);//
create a sequenceauto
delaySequence = Sequence::create(delay, delay->clone(), delay->clone(),delay->clone(),
nullptr);auto
sequence = Sequence::create(moveBy, delay, scaleBy, delaySequence, nullptr);//
run itnewSprite2->runAction(sequence);//
reverse itnewSprite2->runAction(sequence->reverse()); |
发生了什么呢?如下步骤清单或许对我们有帮助:
- 创建mySprite
- 设置mySprite位置为(50,56)
- 开始运行
sequence - 在两秒内sequence将mySprite移动了500个像素,mysprite新位置为(550,56)
- sequence延迟2秒
- 在两秒内sequence将mySprite扩大两倍
- 延迟了6秒多(注意,这里我们运行了另外一个sequence来完成这个)
- 在sequence上运行一reverse,因此我们可以向后重新运行每个动作。
- sequence被延迟了6秒
- 在2秒内sequence将mySprite扩大了两倍
- sequence延迟了两秒
- 在两秒内,sequence移动mySprite了-500个像素,mySprite的新位置为(50,56)
你可以看到reverse()用起来很简单,但是其实逻辑上并不简单。Cocos2d-x已经为你完成了这复杂的逻辑。
本文深入解析 Cocos2d-x 中的动作系统,包括 Action 类的基本概念、如何改变 Node 对象属性,以及 MoveTo、MoveBy、RotateTo、ScaleTo 等基本动作的使用方法。详细讲解了 By 和 To 的区别、如何执行动作以及如何使用 Sequence、Spawn、Reverse 等高级功能。

9374

被折叠的 条评论
为什么被折叠?



