cocos2d基礎介紹

cocos2d中,大量使用了單例(singleton)模式,單例其實就是一個普通的類,但是它在整個應用程序生命週期內只實例化一次,cocos2d中,要訪問單例對象,基本上都是使用shared開頭的方法(目前爲止,我沒有發現過有不這樣使用的單例)。如果你還沒看懂單例是什麼,那麼看看下面這個例子你就知道了。

複製代碼
static MyManager *shareManager = nil;

+(MyManager) sharedManager

{

if(shareManager == nil)

{

shareManager = [[MyManager alloc] init];

}



return shareManager;

}
複製代碼

cocos2d的整體結構類圖:



  我覺得單例應該是包含了一些公用的方法,而且調用這些方法,不會去修改單例的屬性,否則其他的類來調用單例的時候,所遇到的結果就是未知的了。說完單例,我們先來說說一個重要的單例類——CCDirector。CCDiretor類是Cococs2d遊戲引擎的核心,它存儲了cocos2d種大量的全局配置信息,而且管理着所有的cocos2d場景。Dirctor的主要作用有一下幾點:

  • 切換場景
  • 存儲cocos2d的配置信息
  • 訪問試圖(包含OpenGL、UIView、UIWindow)
  • 暫停、恢復以及終止遊戲
  • 在UIKit和OpenGL之間轉換座標
  • CCNode類

     接下來,說說CCNode類。cocos2d中,所有的節點都繼承自CNode類,它是一個沒有具體顯示的抽象類,僅用於定義所有的公共屬性和方法。首先我們來看一下cocos文檔裏面列舉出來的類的繼承關係,可以從中發現CCScene、CCSprite都繼承自CCNode,以前CCLayer也應該是繼承自CCNode,但是在1.0.1的文檔中查不到這個類,先記錄下,等下再去查。

 再來看看這個類的部分公共函數,裏面包含了各種對節點的操作,增加、刪除、獲取節點、調度(即隔多少秒執行一次,稍後會詳細說、取消調度、開始播放動作、停止動作等):

(void) 

addChild:

(void) 

addChild:z:

(void) 

addChild:z:tag:

(void) 

removeFromParentAndCleanup:

(void) 

removeChild:cleanup:

(void) 

removeChildByTag:cleanup:

(void) 

removeAllChildrenWithCleanup:

(CCNode *) 

getChildByTag:

(void) 

reorderChild:z:

(void) 

cleanup

(void) 

draw

(void) 

visit

(void) 

transform

(void) 

transformAncestors

(CGRect) 

boundingBox

(CGRect) 

boundingBoxInPixels

(CCAction *) 

runAction:

(void) 

stopAllActions

(void) 

stopAction:

(void) 

stopActionByTag:

(CCAction *) 

getActionByTag:

(NSUInteger) 

numberOfRunningActions

(void) 

scheduleUpdate

(void) 

scheduleUpdateWithPriority:

(void) 

schedule:

(void) 

schedule:interval:

(void) 

unschedule:

(void) 

unscheduleAllSelectors

(void) 

resumeSchedulerAndActions

(void) 

pauseSchedulerAndActions

 

  • CCScene類

     一個CCScene對象往往是場景圖種的第一個節點。通常來說,CCScene節點的第一層子節點一定是CCLayer的子類,而CCScene對象本身,通常是利用CCLayer對象種的靜態方法+(id)scene來創建,而且遊戲中的各個對象,也通常是由這些子節點(CCLayer)來保存,而不是CCScene本身來保存,這樣做的好處,會在CCLayer部分介紹。

 

     1、場景類跟app建立關係上

     我們可以把要顯示的第一個場景,加在AppDelegate中applicationDidFinishLaunching方法的最後,類似如下:

     [[CCDirector sharedDirector] runWithScene:[HelloWorld scene]];

 

     HelloWold類是一個繼承自CCLayer的類,scene是其中的一個靜態方法,用來將layer加入scene裏面,如下所示:

複製代碼
     +(id)scene

{

CCScene *scene = [CCScene node];

CCLayer *layer = [HelloWord node];

[scene addChild:layer];



return scene;

}
複製代碼



 

     2、內存使用

     當進行場景替換的時候,cocos2d會把自己佔用的內存清理乾淨,它會刪除所有的節點,停止所有的動作,並且對所有用選擇器選中的方法取消調度。但是,由於在進行場景替換時,新場景往往在舊場景釋放之前就被加載到內存了,這會導致內存負荷瞬間加大,這個問題在使用場景轉換動畫的時候,顯得格外明顯。這時候,場景首先會被創建,然後過渡效果運行,一直要到過度效果運行完畢之後,舊場景纔會從內存中釋放。

  由於場景替換的時候,會停止所有的動作,那麼可否在播放場景過渡動畫前先把前一個場景截屏,然後釋放掉前一個場景再播放動畫,這樣的話,就能節省不少內存。

 

     3、場景的推進和彈出

     cocos2d種有pushScene和popScene這兩個有用的方法,這兩個方法用來在不釋放舊場景內存的情況下運行新場景,可以加快場景替換的速度。由於很多場景可以互相疊加的存在於內存之中,很容易就會忘記彈出一個場景,或者對於同一個場景彈出太多遍。學過堆棧的同學,應該知道這種情況的危險性。但是這個用來切換setting還是不錯的選擇,因爲setting一般都不怎麼佔內存,當然,特殊情況除外。

 

一個CCScene可以包含多個CCLayer:


  • CCTransitonScene

     場景過渡動畫有時候能爲遊戲添色不少。在cocos2d中,要使用過度動畫還是比較簡單的,只要在場景轉換時添加兩行代碼就行了。比如下面這個淡入淡出效果:

    

複製代碼
 CCFadeTransition *tran = [CCFadeTransition transitionWithDuration:1 

scene:[HelloWorld scene]

withColor:ccWHITE];

[[CCDirector sharedDirector] replaceScene:tran];
複製代碼

 

 

     CCTransitonScene定義了很多的場景轉換動畫,看下下面這張類圖應該能很清楚的知道:


  • CCLayer

     開始在CCScene裏面提到過,CCLayer本質是對節點進行分組,遊戲中的各個對象,一般是用CCLayer來保存的。這樣的好處是,可以很輕鬆的修改層的屬性或者在該層上運行一個動作來影響層上的所有子節點。例如你可以對某一層施加一個動作,然後這個動作會對該層上的所有對象產生影響。當然,不使用層也能達到這樣的效果,只要對每個對象分別進行操作即可,但是顯然,不使用層的做法是非常低效的。

 

     CCLayer能夠接收觸摸事件和加速劑事件,但是接收觸摸或者加速計事件的開銷是很大的,這也就導致有人說使用多個層會影響性能。實際上你可以使用任意多個蹭,與其他的節點相比,他們對於性能並沒有太大的影響。如果太多的層需要接收和處理觸摸或者加速計事件,可以只用一個蹭來接收和處理這些輸入,然後在必要的情況下,通過這個層將輸入事件通知給其他節點或者類。

 

     1、接收觸摸事件

     使用self.isTouchEnabled = YES來顯示啓動接收觸摸事件,一般會在init方法中開啓此功能。下面列出幾個常用單點觸控的觸摸事件:

     a)當手指接觸到屏幕時被調用:

 -(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event

 

  b)當手指離開屏幕時候被調用:

 -(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event 

     c)當觸摸時間被取消時調用:

-(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event

     d)當手指在屏幕上移動的時候被調用:

    

 -(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event

     在使用單點觸摸之前,要向層中添加以下方法來啓用有針對性的觸摸處理:

複製代碼
     -(void) registerWithTouchDispatcher

{

[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
priority:INIT_MIN + 1
swallowsTouches:YES];

複製代碼

     CCTouchBegan返回一個bool值,如果返回YES,就意味着不想讓這個觸摸被傳送到其他優先級更低的有針對性的觸摸處理,也就相當於你直接吞噬掉了這個觸摸事件。

 

     由於觸摸事件是由Cocoa Touch API接收的,因此一定要吧觸摸位置轉換成cocos2d所用的OpenGL座標:

     

-(CGPoint) locationFromTouch:(UITouch *)touch
{
CGPoint touchLocation = [touch locationInView:[touch view]];
return [[CCDirector sharedDirector] convertToGL:touchLocation];
}

     2、接收加速計事件

     同樣,需要self.isAccelerometerEnabled = YES來顯示啓動加速計來接收加速計事件,但是這個事件的處理比觸摸時間就簡單多了,只需要向層裏面添加一個特定方法來接收加速計事件:

     

複製代碼
- (void)accelerometer:(UIAccelerometer*)accelerometer 
didAccelerate:(UIAcceleration*)acceleration
{
//可以利用以下參數來決定三維中任意方向的加速度
//acceleration.x acceleration.y acceleration.z
}
複製代碼


 

  • CCSprite

   CCSprite是cocos2d種最爲常用的類,它用一副圖像將精靈顯示到屏幕上。要創建一個精靈很簡單,比如你的工程的Resources分組下有一張叫做monster.png的圖,那麼只需要使用如下方法,就能將精靈顯示在層上:

CCSpirt *sprite = [[CCSprite spriteWithFile:@"monster.png"]];

[self addChild:sprite];   

     通過上面的操作後,cocos2d內部會把該圖片加載到CCTexture2D類的圖像資源中。在這裏,順便提一下,由於ios設備只支持尺寸爲“2的n次冪”的紋理,即圖片的長寬只能偉:2、4、8等像素。如果你有一張貼圖,大小爲260*260像素32位色的圖片,那麼就比較悲劇了。你覺得它在內存中應該只佔用260*260*4=270KB左右的空間,單實際上,它佔用了512*512*4=1MB的內存。

      CCSprite還有一個比較重要的就是位置問題,想象下現實生活中,如果你要把一張照片釘在牆上某個問題,你會怎麼做?首先,你會把圖釘插在照片上的某個點(在cocos2d中稱爲anchorPoint),然後你會確定要把這個圖釘訂在牆上的某個位置(在cocos2d種稱爲positon),這兩個點就能確定照片在牆上的位置了。比如你想把照片放到左下角,那麼你可以選擇將圖釘釘在照片的左下角(0,0),然後釘在牆的左下角(0,0).或者,你可以選擇把圖釘定在照片的右上角(1,1),然後把照片訂在牆的(照片長,照片寬)的位置。auchorPoint表示的其實是一個百分比,用來標明相對於圖片左下角的(長*百分比,寬*百分比)像素的位置,比如auchorPoint爲(0.5, 0.5), 那麼在圖片的座標系裏,它標明的位置就應該是(長*0.5, 寬*0.5)的位置,也就是圖片的中心點。最好好anchorPoint設置成(0.5, 0.5),也就是在圖片的中心,這樣,當你進行旋轉、縮放等動作的時候,會比較方便。幸運的是,anchorPoint的默認位置就是(0.5,0.5).

  • CCLabelTTF

  這個類的作用就是在屏幕上顯示文本。cocos2d內部會以制定的字體作爲參數創建一個CCTexture2D對象,也就是一張紋理,然後再用改紋理渲染出最後顯示的文本.因爲每次文本發生改變,就要做一次上述工作,所以cocos2d的文檔中也建議改用CCLabelAtlas或者CCLabelBMFont代替。

     你可能會發現,每次修改標籤上的文本時候,這些文本都會自動中對齊,如果要改成左對齊,或者右對齊這些,只需要改變anchorPoint的屬性就可以了。

  • 動作CCAction



  • CCActionEase是CCActionInterval的子類



     動作是可以用來讓節點執行諸如移動、旋轉、縮放、變色、消失等很多動作。由於他們能作用在所有的節點上,因此可以對精靈、標籤甚至菜單或整個場景施加動作。動作在完成後,會自動從節點上清除並釋放它所佔用的內存。

     動作又分爲即時動作和延時動作。延時動作就是我們一般理解上的動作,比如讓一個精靈移動到哪裏。即時動作,一般就類似於設置精靈的屬性等,及時動作平時看起來是沒有多大意義的,一般要配合後文所述的動作序列。

     1)重複動作

     這個很容易理解,就是讓一個動作不停的重複,可以用這個方法創建無限循環的動畫。使用起來也很簡單,例如下面這個讓一個節點不停的旋轉:

     

CCRotateBy* rotateBy = [CCRotateBy actionWithDuration:2  angle:360];

CCRepeatForever *repeat = [CCRepeatForever actionWithAction:rotateBy];

[myNode runAction:repeat]; 

     還有一個類CCRepeat是讓一個動畫重複多少次,函數原型如下:     

actionWithAction:(CCFiniteTimeAction *)action times:(NSUInteger) times;


     2、流暢動作(CCEaseAction) 

     一般的動作,比如你定義了一個物體是向哪個方向移動,那麼它就會勻速的過去,但是很顯然,我們喜歡更有點變化的動作,比如加速進入,然後迅速一段時間,再減速停止,流暢動作就是用來做這個的。

 

     3、動作序列

    CCSequence,這個比較好理解,就是定義一組動作,然後讓他們按照這個順序執行。


發佈了16 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章