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 seconds auto
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 move auto
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 seconds auto
rotateTo = RotateTo::create(2.0f, 40.0f); mySprite->runAction(rotateTo); //
Rotates a Node clockwise by 40 degree over 2 seconds auto
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 seconds auto
scaleBy = ScaleBy::create(2.0f, 3.0f); mySprite->runAction(scaleBy); //
Scale X by 5 and Y by 3x over 2 seconds auto
scaleBy = ScaleBy::create(2.0f, 3.0f, 3.0f); mySprite->runAction(scaleBy); //
Scale to uniformly to 3x over 2 seconds auto
scaleTo = ScaleTo::create(2.0f, 3.0f); mySprite->runAction(scaleTo); //
Scale X to 5 and Y to 3x over 2 seconds auto
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 seconds auto
fadeIn = FadeIn::create(1.0f); mySprite->runAction(fadeIn); //
fades out the sprite in 2 seconds auto
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 values auto
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 moved Vector<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 frames Animation*
animation = Animation::createWithSpriteFrames(animFrames, 0.1f); Animate*
animate = Animate::create(animation); //
run it and repeat it forever mySprite->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 sprite auto
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 Action auto
move_ease_in = EaseBounceIn::create(move->clone() ); //
create a delay that is run in between sequence events auto
delay = DelayTime::create(0.25f); //
create the sequence of actions, in the order we want to run them auto
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 callbacks auto
callbackJump = CallFunc::create([](){ log ( "Jumped!" ); }); auto
callbackRotate = CallFunc::create([](){ log ( "Rotated!" ); }); //
create a sequence with the actions and callbacks auto
seq = Sequence::create(jump, callbackJump, rotate, callbackRotate, nullptr); //
run it mySprite->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 Sprite auto
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 Sprite auto
mySprite = Sprite::create( "mysprite.png" ); //
create a few Actions auto
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 use auto
mySpawn = Spawn::createWithTwoActions(scaleBy, fadeTo); //
tie everything together in a sequence auto
seq = Sequence::create(moveBy, mySpawn, moveBy, nullptr); //
run it mySprite->runAction(seq); |
運行“開發者指南示例”中的代碼查看動作效果。
Reverse(逆序)
Reverse的作用完全像它的名字一樣,例如運行一系列動作時,你完全可以調用reserve()函數使動作逆序執行。然而,這並不只是簡單的逆序運行,實際上還將原始的Sequence
和Spawn
的屬性也轉換爲逆序。
Using the Spawn
example above reversing is simple. 上面Spawn
中的例子使用逆序就會很簡單:
1
2
|
//
reverse a sequence, spawn or action mySprite->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 Sprite auto
mySprite = Sprite::create( "mysprite.png" ); mySprite->setPosition(50,
56); //
create a few Actions auto
moveBy = MoveBy::create(2.0f, Vec2(500,0)); auto
scaleBy = ScaleBy::create(2.0f, 2.0f); auto
delay = DelayTime::create(2.0f); //
create a sequence auto
delaySequence = Sequence::create(delay, delay->clone(), delay->clone(), delay->clone(),
nullptr); auto
sequence = Sequence::create(moveBy, delay, scaleBy, delaySequence, nullptr); //
run it newSprite2->runAction(sequence); //
reverse it newSprite2->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已經爲你完成了這複雜的邏輯
轉自cocos引擎中文官網