一:動作Actions
從上一篇我們看到菜單情境中菜單layer載入進來有個從上滑入的動作效果
//動作1 id ac = [CCMoveTo actionWithDuration:2 position:CGPointMake(winSize.width/2, winSize.height/2)]; CCRepeat *repe = [CCRepeat actionWithAction:ac times:4]; //動作二 id bc = [CCCallFunc actionWithTarget:self selector:@selector(test)]; CCSequence *seq = [CCSequence actions:repe,bc,nil]; [menu runAction:seq];
上面只是一個很簡單的例子,用cocos2d的ccAction類來實現節點元素的一些動作。
比如移動,旋轉等。
因為我們知道,cocos2d中scene,layer,sprite都實現了CCNode這個基類,
也就是說其實動作這個運用範圍不是我們一般狹隘的以為只是運用在Sprites上。
在layer,scene什麼的都是可以運用其中,當然,最多的還是運用在精靈上。
比如我們控制人物精靈的走動跳躍等等。
cocos2D廣義上將動作分為“即時動作”和“延時動作”。
即時動作更像是如設定對象的屬性一樣。
而延時動作也就是我們上面用到移動就是一種。
物體運動什麼的都屬於這個範疇。
延時動作:
1.常見的延時動作:CCMoveTo移動到,CCJumpTo跳躍到,方法都會接受不同參數,
但是我們延時動作至少要接受延時時間的參數。
2.舒緩動作CCEaseAction,
說白了我們簡單就是讓動作有個循序漸進的緩衝,
在視覺上更具美感。
很多時候,這個類額應用其實就是對上面的基本延時動作做了一層裝飾。
CCAction *c = [CCMoveTo actionWithDuration:5 position:ccp(240, 160)]; CCEaseInOut *ci = [CCEaseInOut actionWithAction:c rate:5]; [self runAction:ci];
如上面這段代碼,我有一個移動的動作,然後裝飾成移動開始時和結束時速度漸層效果。
常見的舒緩動作類
1. CCEaseBackIn, CCEaseBackInOut, CCEaseBackOut2. CCEaseBounceIn, CCEaseBounceInOut, CCEaseBounceOut
3. CCEaseElasticIn, CCEaseElasticInOut, CCEaseElasticOut
4. CCEaseExponentialIn, CCEaseExponentialInOut, CCEaseExponentialOut
5. CCEaseIn, CCEaseInOut, CCEaseOut
6. CCEaseSineIn, CCEaseSineInOut, CCEaseSineOut
重複動作:
重複動作從字面看其實很好理解。
但是真正用起來具有局限性。比如我下面這段代碼
CCAction *c = [CCMoveTo actionWithDuration:3 position:ccp(20, 100)]; CCEaseInOut *ci = [CCEaseInOut actionWithAction:c rate:5]; CCRepeat *re = [CCRepeat actionWithAction:ci times:2]; [self runAction:re];
是沒有重複效果的,而不是我們以為的如Android中類似是有我們這樣思路的動作效果。
動作最後還是只是執行了一次。
後來我大致這麼猜測
重複動作其實可以看成就是一個動作序列(對于于動作序列下面馬上提到),重複N次就是添加了N個這樣的Action。
但是為什麼我們肉眼只能看到移動動作只執行了一次。
其實這是我們自己造成的錯誤思維,
在我們思維中,以為比如重複2次這個moveto動作,第一次移動完了後,我們看到的現象是這個物體又突然出現在原來開始點,然後再次發生移動。
但是其實moveTo函數中我們傳遞一個postion,也就是移動到螢幕的位置p,第二次要在重複時,因為移動動作的起始位置就是要移動的左邊p。
因此看上去是不動的(好吧,上面只是自己的自我解釋而已~)
但是用CCMoveBy的話是可以的,因為傳入的參數是個位移值。
可是在在部分網上資料上說:
這裡需要注意的是actionBy不能重複使用,如果第二次使用的話,會繼續從第一次使用到的位置開始繼續,不明白的可以嘗試一下,現象很明顯!
所以說其的局限性麼,當然,api'也不過是提出這麼一個概念罷了。
CCRotateBy* rotateBy = [CCRotateBy actionWithDuration:2 angle:360];CCRepeatForever* repeat = [CCRepeatForever actionWithAction:rotateBy];[myNode runAction:repeat];
這個是資料上提供的一個列子。
動作序列
CCSequence *seq = [CCSequence actions:repe,bc,nil];
[menu runAction:seq];
顧名思義,一個動作接一個動作。
本身也是繼承了action類。
說道連續動作順便提下上面我們即時動作
我們說了,即時動作更像是一直屬性設定。但是cocos2d為什麼還要引入即時動作這個概念呢。
其實就是為了配合動作序列來說,就覺得,這個設計邏輯的好處了。
舉例:一個物體先移動到p,然後突然消失(hide),然後又移動到q,然後突然出現。
從這段描述,我們可以這麼設計,先是一個延時動作A,然後突然消失,那設定屬性唄(object.hide),然後在延時動做B,然後再設定屬性show。
好了,這邊我們就會發現一個問題,如果是是以上面額思維來設計,A動作finish後可能需要一個回調來執行屬性,也有人說,把屬性設定也當成一個動作,
放在隊列裡啊。然後問題就出在這裡了,我這個設定屬性的動作以什麼形式放進去,即時動作其實就是這麼一個讓序列看起統一的設計。
對於即時動作,資料上也說了:你可能會奇怪為什麼有基於CCInstantAction的即時動作存在,通過改變節點的 屬性不是可以達到一樣的目的嗎?比如那些用來翻轉節點,把節點放置的指定 的地方,還有用於開關節點的可視性屬性的即時動作。
但是通過上面的延時動作,做過android的就會有種不習慣,我第一個動作執行完後在執行第二個前要做一些額外操作,然後貌似它沒有類似於android中監聽這麼一種概念機制。
初看即時動作中最常用的CCCallFunc動作的調用格式,就會發現不正是一種回調麼。
而Android的回調執行一般是在前一個動作的finish方法裡,但是對於ios,因為放入了序列裡,
然後起一個動作執行玩了來執行下一個動作。這個動作是我們自訂的一個操作函數而已。
而非實際意義上必須產生物體移動的才叫動作。動作隊列最後也不過是成了一個操作隊列。
因此,即時動作的作用也就不言而喻了,在一個動作序列中配合使用,可以讓動作更加靈活。
CCCallFunc* func = [CCCallFunc actionWithTarget:self selector:@selector(onCallFunc)]; CCCallFuncN* funcN = [CCCallFuncN actionWithTarget:self selector:@selector(onCallFuncN:)];CCCallFuncND* funcND = [CCCallFuncND actionWithTarget:self selector:@selector(onCallFuncND:data:) data:(void*)self];CCSequence* seq = [CCSequence actions:tint1, func, tint2, funcN, tint3, funcND, nil]; [label runAction:seq];
同步操作
CCSpawn,這個就沒什麼說的,相信做個一些動畫效果的都知道比如一個圓一邊色彩坡形,一邊從小變大。
只不過要明白點,同步執行最後的完成時間由基本動作中用時最大者決定。