瘋狂ios講義之瘋狂打飛機(1)

瘋狂打飛機遊戲

   本次我們將帶領大家手動完成一個簡單但功能完整的打飛機遊戲,實現飛機飛行、飛機碰撞、發射子彈、敵機發射大子彈、背景音樂、子彈音效、分數統計、菜單管理等功能。它雖然不會爲你贏得什麼獎項,但是可以總結前面所學的所有知識,幫助大家更好地掌握cocos2d基本對象的使用,同時體驗cocos2d的強大以及易用性。

1開始前的準備工作

首先打開Xcode,使用cocos2d iOS模板新建一個項目,命名爲“AirfightGame”,然後選擇一個目錄,單擊“Create”按鈕。爲cocos2d項目的源代碼添加-fno-objc-arc選項讓項目支持ARC

接下來,將所需要的資源文件,包括圖片和聲音拖到項目的“Resources”組。在遊戲開發當中,通常都會使用精靈表單來優化遊戲性能,在這個小遊戲當中,雖然這種性能優化並不會有特別明顯的效果,但是建議大家以後開發遊戲時都使用精靈表單來提高遊戲性能。使用Zwoptex將所有圖片製作成精靈表單,生成對應的airfightSheet.pngairfightSheet.plist文件,並將這兩個文件拖到項目的“Resources”組。

2添加遊戲菜單項功能

現在,我們來爲遊戲添加一個菜單設置功能,在這裏可以完成開始遊戲、遊戲設置、退出遊戲等操作。步驟如下。

選擇“AirfightGame”組並單擊右鍵,選擇“New File”,在左邊欄中選擇“cocos2d v2.x”模板,在右邊的模板類中選擇“CCNode class”模板類,“Subclass of”選擇“CCLayer”,然後單擊“Next”按鈕。命名爲“MenuLayer”,然後單擊“Create”按鈕。

MenuLayer繼承自CCLayer,提供一個類方法sceneCCDirector對象調用。該類的作用是顯示一個菜單場景,讓用戶選擇。

打開MenuLayer.m文件,實現代碼如下。

程序清單:codes/13/13.14/AirfightGame/AirfightGame/MenuLayer.m

-(id) init
{
    if( (self=[super init]) ) {
        CGSize winSize = [[CCDirector sharedDirector] winSize];
        // 創建“開始遊戲”標籤,當觸碰該標籤時,調用startGame:方法
        CCMenuItemFont* startItem = [CCMenuItemFont itemWithString:@"開始遊戲"
            target:self selector:@selector(startGame:)];
        startItem.position=ccp(winSize.width/2, winSize.height*0.6);
        // 創建“遊戲設置”標籤,當觸碰該標籤時,調用setting:方法
        CCMenuItemFont* settingItem = [CCMenuItemFont itemWithString:@"遊戲設置"
            target:self selector:@selector(setting:)];
        // 設置“遊戲設置”標籤位置
        settingItem.position=ccp(winSize.width/2, winSize.height*0.4);
        // 創建控制菜單,並將兩個標籤添加進去
        CCMenu* menu = [CCMenu menuWithItems:startItem,settingItem, nil];
        menu.position = CGPointZero;
        [self addChild:menu];
    }
    return self;
}

init方法比較簡單,創建了兩個CCMenuItemFont,選擇標籤時會調用對應的startGame:setting:方法,並將它們添加到CCMenu當中,再將CCMenu添加爲當前層的子節點。

添加startGame:setting:兩個方法,實現代碼如下(程序清單同上):

-(void) startGame:(id)sender{
    // 切換到PreloadLayer場景
    CCTransitionSlideInL* transitionScene = [CCTransitionSlideInL
        transitionWithDuration:2.0 scene:[PreloadLayer scene]];
    [[CCDirector sharedDirector] replaceScene:transitionScene];
}

startGame:方法非常簡單,當用戶選擇“開始遊戲”標籤時,場景切換到PreloadLayer,在下一節中將重點介紹PreloadLayer(程序清單同上)。

-(void) setting:(id)sender{
    // 切換到SettingLayer場景
    CCTransitionSlideInL* transitionScene = [CCTransitionSlideInL
        transitionWithDuration:2.0 scene:[SettingLayer scene]];
    [[CCDirector sharedDirector] replaceScene:transitionScene];
}

當用戶選擇“遊戲設置”標籤時,場景切換到SettingLayer,進行遊戲設置。

同上面的步驟一樣,使用“cocos2d v2.x”模板創建一個類並命名爲“SettingLayer”,繼承自CCLayer。該類的實現代碼如下。

程序清單:codes/13/13.14/AirfightGame/AirfightGame/SettingLayer.m

-(id) init
{
    if( (self=[super init]) ) {
        CGSize winSize = [[CCDirector sharedDirector] winSize];
        // 提示菜單項
        CCMenuItemFont* musicItem = [CCMenuItemFont itemWithString:@"背景音樂:"];
        musicItem.position = ccp(winSize.width*0.4, winSize.height*0.6);
        // 創建“開”和“關”菜單項
        CCMenuItemFont* musicOn = [CCMenuItemFont itemWithString:@"開"];
        CCMenuItemFont* musicOff = [CCMenuItemFont itemWithString:@"關"];
        // CCMenuItemToggle,默認顯示“開”。開=0,關=1
        CCMenuItemToggle* musicToggle = [CCMenuItemToggle itemWithTarget:self
            selector:@selector(change:) items:musicOff,musicOn, nil];
        musicToggle.position = ccp(winSize.width*0.6, winSize.height*0.6);
        // 創建“返回主菜單“菜單項
        CCMenuItemFont* returnItem = [CCMenuItemFont itemWithString:@"返回主菜單"
            target:self selector:@selector(backToMainLayer:)];
        returnItem.position = ccp(winSize.width/2, winSize.height*0.4);
        // 創建控制菜單,並將3個標籤添加進去
        CCMenu* menu = [CCMenu menuWithItems:musicItem,musicToggle,returnItem, nil];
        menu.position = CGPointZero;
        [self addChild:menu];
        // NSUserDefaults用戶首選項可以用來保存用戶在操作應用的過程中設置的首選項。
        NSUserDefaults* userDef = [NSUserDefaults standardUserDefaults];
        // 如果Bool爲No,則顯示1=關
        if(![userDef boolForKey:@"music"]){
            musicToggle.selectedIndex = 1;
        }
    }
    return self;
}
-(void) change:(id)sender{
    // 判斷mute(靜音)屬性,根據屬性狀態進行切換
    if([CDAudioManager sharedManager].mute == TRUE){
        [CDAudioManager sharedManager].mute = FALSE;
    }else{
        [CDAudioManager sharedManager].mute = TRUE;
    }
    NSUserDefaults* userDef = [NSUserDefaults standardUserDefaults];
    CCMenuItemToggle* tooggle = (CCMenuItemToggle*)sender;
    // 關=1,設置Bool爲NO
    if(tooggle.selectedIndex == 1){
        [userDef setBool:NO forKey:@"music"];
    }else{
        [userDef setBool:YES forKey:@"music"];
    }
}
// 定義一個CCTransitionSlideInL場景切換效果,並使用CCDirector單例對象來切換場景
-(void) backToMainLayer:(id)sender{
    CCTransitionSlideInL* transitionScene =
        [CCTransitionSlideInL transitionWithDuration:2.0 scene:[MenuLayer scene]];
    [[CCDirector sharedDirector] replaceScene:transitionScene];
}

SettingLayer類代碼在13.13.2節中已經詳細介紹過,這裏不再贅述。

修改IntroLayer.m文件

IntroLayer默認加載HelloWorldLayer,但此時我們不再使用HelloWorldLayer作爲應用的第一個場景,而是使用MenuLayer作爲應用的第一個場景,因此需要修改IntroLayer,將IntroLayer改爲加載MenuLayer場景修改如下。

IntroLayer.m文件的頂部添加所包含的頭文件:

#import "MenuLayer.h"

修改-(void) makeTransition:(ccTime)dt方法,將該方法改成下面的代碼。

程序清單:codes/13/13.14/AirfightGame/AirfightGame/IntroLayer.m

-(void) makeTransition:(ccTime)dt
{
    [[CCDirector sharedDirector] replaceScene:
        [CCTransitionFade transitionWithDuration:1.0
        scene:[MenuLayer scene] withColor:ccWHITE]];
}

ios講義之瘋狂打飛機(1)

瘋狂打飛機遊戲

   本次我們將帶領大家手動完成一個簡單但功能完整的打飛機遊戲,實現飛機飛行、飛機碰撞、發射子彈、敵機發射大子彈、背景音樂、子彈音效、分數統計、菜單管理等功能。它雖然不會爲你贏得什麼獎項,但是可以總結前面所學的所有知識,幫助大家更好地掌握cocos2d基本對象的使用,同時體驗cocos2d的強大以及易用性。

1開始前的準備工作

首先打開Xcode,使用cocos2d iOS模板新建一個項目,命名爲“AirfightGame”,然後選擇一個目錄,單擊“Create”按鈕。爲cocos2d項目的源代碼添加-fno-objc-arc選項讓項目支持ARC

接下來,將所需要的資源文件,包括圖片和聲音拖到項目的“Resources”組。在遊戲開發當中,通常都會使用精靈表單來優化遊戲性能,在這個小遊戲當中,雖然這種性能優化並不會有特別明顯的效果,但是建議大家以後開發遊戲時都使用精靈表單來提高遊戲性能。使用Zwoptex將所有圖片製作成精靈表單,生成對應的airfightSheet.pngairfightSheet.plist文件,並將這兩個文件拖到項目的“Resources”組。

2添加遊戲菜單項功能

現在,我們來爲遊戲添加一個菜單設置功能,在這裏可以完成開始遊戲、遊戲設置、退出遊戲等操作。步驟如下。

選擇“AirfightGame”組並單擊右鍵,選擇“New File”,在左邊欄中選擇“cocos2d v2.x”模板,在右邊的模板類中選擇“CCNode class”模板類,“Subclass of”選擇“CCLayer”,然後單擊“Next”按鈕。命名爲“MenuLayer”,然後單擊“Create”按鈕。

MenuLayer繼承自CCLayer,提供一個類方法sceneCCDirector對象調用。該類的作用是顯示一個菜單場景,讓用戶選擇。

打開MenuLayer.m文件,實現代碼如下。

程序清單:codes/13/13.14/AirfightGame/AirfightGame/MenuLayer.m

01-(id) init
02{
03if( (self=[super init]) ) {
04CGSize winSize = [[CCDirector sharedDirector] winSize];
05// 創建“開始遊戲”標籤,當觸碰該標籤時,調用startGame:方法
06CCMenuItemFont* startItem = [CCMenuItemFont itemWithString:@"開始遊戲"
07target:self selector:@selector(startGame:)];
08startItem.position=ccp(winSize.width/2, winSize.height*0.6);
09// 創建“遊戲設置”標籤,當觸碰該標籤時,調用setting:方法
10CCMenuItemFont* settingItem = [CCMenuItemFont itemWithString:@"遊戲設置"
11target:self selector:@selector(setting:)];
12// 設置“遊戲設置”標籤位置
13settingItem.position=ccp(winSize.width/2, winSize.height*0.4);
14// 創建控制菜單,並將兩個標籤添加進去
15CCMenu* menu = [CCMenu menuWithItems:startItem,settingItem, nil];
16menu.position = CGPointZero;
17[self addChild:menu];
18}
19returnself;
20}

init方法比較簡單,創建了兩個CCMenuItemFont,選擇標籤時會調用對應的startGame:setting:方法,並將它們添加到CCMenu當中,再將CCMenu添加爲當前層的子節點。

添加startGame:setting:兩個方法,實現代碼如下(程序清單同上):

1-(void) startGame:(id)sender{
2// 切換到PreloadLayer場景
3CCTransitionSlideInL* transitionScene = [CCTransitionSlideInL
4transitionWithDuration:2.0 scene:[PreloadLayer scene]];
5[[CCDirector sharedDirector] replaceScene:transitionScene];
6}

startGame:方法非常簡單,當用戶選擇“開始遊戲”標籤時,場景切換到PreloadLayer,在下一節中將重點介紹PreloadLayer(程序清單同上)。

1-(void) setting:(id)sender{
2// 切換到SettingLayer場景
3CCTransitionSlideInL* transitionScene = [CCTransitionSlideInL
4transitionWithDuration:2.0 scene:[SettingLayer scene]];
5[[CCDirector sharedDirector] replaceScene:transitionScene];
6}

當用戶選擇“遊戲設置”標籤時,場景切換到SettingLayer,進行遊戲設置。

同上面的步驟一樣,使用“cocos2d v2.x”模板創建一個類並命名爲“SettingLayer”,繼承自CCLayer。該類的實現代碼如下。

程序清單:codes/13/13.14/AirfightGame/AirfightGame/SettingLayer.m


01-(id) init
02{
03if( (self=[super init]) ) {
04CGSize winSize = [[CCDirector sharedDirector] winSize];
05// 提示菜單項
06CCMenuItemFont* musicItem = [CCMenuItemFont itemWithString:@"背景音樂:"];
07musicItem.position = ccp(winSize.width*0.4, winSize.height*0.6);
08// 創建“開”和“關”菜單項
09CCMenuItemFont* musicOn = [CCMenuItemFont itemWithString:@"開"];
10CCMenuItemFont* musicOff = [CCMenuItemFont itemWithString:@"關"];
11// CCMenuItemToggle,默認顯示“開”。開=0,關=1
12CCMenuItemToggle* musicToggle = [CCMenuItemToggle itemWithTarget:self
13selector:@selector(change:) items:musicOff,musicOn, nil];
14musicToggle.position = ccp(winSize.width*0.6, winSize.height*0.6);
15// 創建“返回主菜單“菜單項
16CCMenuItemFont* returnItem = [CCMenuItemFont itemWithString:@"返回主菜單"
17target:self selector:@selector(backToMainLayer:)];
18returnItem.position = ccp(winSize.width/2, winSize.height*0.4);
19// 創建控制菜單,並將3個標籤添加進去
20CCMenu* menu = [CCMenu menuWithItems:musicItem,musicToggle,returnItem, nil];
21menu.position = CGPointZero;
22[self addChild:menu];
23// NSUserDefaults用戶首選項可以用來保存用戶在操作應用的過程中設置的首選項。
24NSUserDefaults* userDef = [NSUserDefaults standardUserDefaults];
25// 如果Bool爲No,則顯示1=關
26if(![userDef boolForKey:@"music"]){
27musicToggle.selectedIndex = 1;
28}
29}
30returnself;
31}
32-(void) change:(id)sender{
33// 判斷mute(靜音)屬性,根據屬性狀態進行切換
34if([CDAudioManager sharedManager].mute == TRUE){
35[CDAudioManager sharedManager].mute = FALSE;
36}else{
37[CDAudioManager sharedManager].mute = TRUE;
38}
39NSUserDefaults* userDef = [NSUserDefaults standardUserDefaults];
40CCMenuItemToggle* tooggle = (CCMenuItemToggle*)sender;
41// 關=1,設置Bool爲NO
42if(tooggle.selectedIndex == 1){
43[userDef setBool:NO forKey:@"music"];
44}else{
45[userDef setBool:YES forKey:@"music"];
46}
47}
48// 定義一個CCTransitionSlideInL場景切換效果,並使用CCDirector單例對象來切換場景
49-(void) backToMainLayer:(id)sender{
50CCTransitionSlideInL* transitionScene =
51[CCTransitionSlideInL transitionWithDuration:2.0 scene:[MenuLayer scene]];
52[[CCDirector sharedDirector] replaceScene:transitionScene];
53}

SettingLayer類代碼在13.13.2節中已經詳細介紹過,這裏不再贅述。

修改IntroLayer.m文件

IntroLayer默認加載HelloWorldLayer,但此時我們不再使用HelloWorldLayer作爲應用的第一個場景,而是使用MenuLayer作爲應用的第一個場景,因此需要修改IntroLayer,將IntroLayer改爲加載MenuLayer場景修改如下。

IntroLayer.m文件的頂部添加所包含的頭文件:

1#import "MenuLayer.h"

修改-(void) makeTransition:(ccTime)dt方法,將該方法改成下面的代碼。

程序清單:codes/13/13.14/AirfightGame/AirfightGame/IntroLayer.m

1-(void) makeTransition:(ccTime)dt
2{
3[[CCDirector sharedDirector] replaceScene:
4[CCTransitionFade transitionWithDuration:1.0
5scene:[MenuLayer scene] withColor:ccWHITE]];
6}

編譯並運行遊戲,運行時模擬器顯示效果如圖13.58所示。

100040_phF0_262659.jpg

3預加載遊戲資源

在真實項目當中,在遊戲開始前,都會預先加載遊戲所需要的圖片、背景音樂、音效等資源,這裏介紹如何製作一個PreloadLayer來預加載遊戲資源。

1. 創建PreloadLayer

選擇“AirfightGame”組並單擊右鍵,選擇“New File”,在左邊欄中選擇“cocos2d v2.x”模板,在右邊的模板類中選擇“CCNode class”模板類,“Subclass of”選擇“CCLayer”,然後單擊“Next”按鈕。命名爲“PreloadLayer”,然後單擊“Create”按鈕。

PreloadLayer繼承自CCLayer,提供一個類方法sceneCCDirector對象調用。該類的作用是預加載遊戲資源,在加載過程中會顯示一個進度條,進度條全部顯示完成代表加載完畢,加載完畢後顯示遊戲主場景。

首先打開PreloadLayer.m文件,先在文件上方定義一個私有的Category。實現代碼如下。

程序清單:codes/13/13.14/AirfightGame/AirfightGame/PreloadLayer.m

/**
 定義一個私有的Category,爲了不讓API暴露給客戶端
 將一些類內部所使用的方法和變量放在私有的擴展裏面,而不是直接聲明在頭文件當中
 */
@interface PreloadLayer ()
- (void) loadMusics:(NSArray *) musicFiles;  // 加載背景音樂
- (void) loadSounds:(NSArray *) soundClips;  // 加載遊戲音效
- (void) loadSpriteSheets:(NSArray *) spriteSheets;  // 加載精靈表單
- (void) loadingComplete;  // 資源全部加載完成,切換到另一個遊戲場景
- (void) progressUpdate;  // 更新遊戲進度條,計算何時加載完成
@end;

這裏定義了一系列的load方法,每個方法接收一個NSArray數組作爲參數。這些參數代表一些具體資源的文件名,參數值會從一個配置文件中讀取出來,該配置文件在之後的代碼實現時會給出。

然後定義3個變量,其中sourceCount用來保存遊戲需要加載的資源總數;progress用於顯示進度條,CCProgressTimer 類是cocos2d中對進度條的一個封裝,用來實現各種進度條功能,非常方便,之後我們還會使用該類來實現遊戲的自定義血條量;progressInterval代表進度條更新的次數。實現代碼如下:

@implementation PreloadLayer
// 用來保存遊戲需要加載的資源總數
int sourceCount;
// 顯示進度條的成員變量
CCProgressTimer* progress;
// 代表進度條更新的次數
float progressInterval;

2. PreloadLayer的具體實現

創建一個preloadResources.plist文件,該文件用於保存項目需要的所有資源文件,文件內容如圖13.59所示。

100147_j0tV_262659.jpg


可以看出,加載的音效是b0.mp3,精靈表單是airfightSheet.plist,背景音樂是s3.wav

100216_l9E3_262659.jpg

PreloadLayer.m文件中添加代碼。實現代碼如下。

程序清單:codes/13/13.14/AirfightGame/AirfightGame/PreloadLayer.m

+ (CCScene *) scene
{
    CCScene* scene = [CCScene node];
    PreloadLayer* layer = [PreloadLayer node];
    [scene addChild:layer];
    return scene;
}
- (id) init{
    if((self = [super init])){
        // 獲取屏幕大小
        CGSize winSize = [[CCDirector sharedDirector] winSize];
        // 創建一個進度條精靈
        CCSprite* barSprite = [CCSprite spriteWithFile:@"progressbar.png"];
        // 初始化一個CCProgressTimer進度條對象
        progress = [CCProgressTimer progressWithSprite:barSprite];
        // setPercentage:0.0f,表示並未加載任何資源,表現在屏幕上就是什麼也看不見
        [progress setPercentage:0.0f];
        // 由於圖片大小關係,把scale設置成0.5,即縮小一半
        progress.scale = 0.5;
        // 設置進度條動畫的起始位置,默認在圖片的中點
        // 如果想要顯示從左到右的一個動畫效果,必須改成(0,y)
        progress.midpoint = ccp(0,0.5);
        // barChangeRate表示是否改變水平或者垂直方向的比例,設置成1表示改變,0表示不改變
        progress.barChangeRate = ccp(1,0);
        // 本例製作一個從左至右的水平進度條,所以midpoint應該是(0,0.5)
        // 因爲x方向需要改變,而y方向不需要改變,所以barChangeRate = ccp(1, 0)
        // kCCProgressTimerTypeBar表示爲條形進度條
        progress.type = kCCProgressTimerTypeBar;
        // 設置position在中心點
        [progress setPosition:ccp(winSize.width/2,winSize.height/2)];
        // 將進度條添加爲當前層的子節點
        [self addChild:progress];
    }
    return self;
}
- (void) onEnterTransitionDidFinish{
    [super onEnterTransitionDidFinish];
    // 加載preloadResources.plist配置文件
    NSString* path = [[CCFileUtils sharedFileUtils]
        fullPathFromRelativePath:@"preloadResources.plist"];
    // 讀取配置文件中的遊戲資源名稱列表,返回一個NSDictionary對象
    NSDictionary* resources = [NSDictionary dictionaryWithContentsOfFile:path];
    // 通過key值取出每種不同類型資源的數組
    NSArray *spriteSheets = [resources objectForKey:@"SpriteSheets"];
    NSArray *sounds = [resources objectForKey:@"Sounds"];
    NSArray *musics = [resources objectForKey:@"Musics"];
    // 調用數組的count方法得到總共需要加載的資源數量
    sourceCount = [spriteSheets count]  + [sounds count] + [musics count];
    // 設置進度條更新次數=100/需要加載的資源數量
    progressInterval = 100.0 / (float) sourceCount;
    // 調用performSelectorOnMainThread在主線程上依次加載每種類型的遊戲資源
    // waitUntilDone的值爲YES能保證所有的資源按照序列依次加載
    if(sounds){
        [self performSelectorOnMainThread:@selector(loadSounds:)
            withObject:sounds waitUntilDone:YES];
    }
    if(spriteSheets){
        [self performSelectorOnMainThread:@selector(loadSpriteSheets:)
            withObject:spriteSheets waitUntilDone:YES];
    }
    if(musics){
        [self performSelectorOnMainThread:@selector(loadMusic:)
            withObject:musics waitUntilDone:YES];
    }
}
// 加載背景音樂
- (void) loadMusics:(NSArray *)musicFiles{
    for (NSString *music in musicFiles) {
        [[SimpleAudioEngine sharedEngine] preloadBackgroundMusic:music];
        [self progressUpdate];
    }
}
// 加載聲音
- (void) loadSounds:(NSArray *)soundClips{
    for (NSString *soundClip in soundClips) {
        [[SimpleAudioEngine sharedEngine] preloadEffect:soundClip];
        [self progressUpdate];
    }
}
// 加載精靈表單
- (void) loadSpriteSheets:(NSArray *)spriteSheets{
    for (NSString *spriteSheet in spriteSheets) {
        // 該方法會加載與該plist文件名稱相同但後綴爲.png的紋理圖片
        // 把該plist的所有spriteFrame信息讀取出來
        // 在之後的代碼中可以通過spriteFrameWithName獲取相應的精靈幀
        // 本例中airfightSheet.plist對應airfightSheet.png
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile: spriteSheet];
        [self progressUpdate];
    }
}
- (void) progressUpdate{
    // 每次調用該方法說明加載一個資源,自減更新資源總數
    if (--sourceCount) {
        [progress setPercentage:100.0f-(progressInterval * sourceCount)];
    }else{
        // CCProgressFromTo動作用於以漸進的方式顯示圖片
        // actionWithDuration表示持續0.5秒,from表示進度條百分百從開始一直到100
        CCProgressFromTo *ac = [CCProgressFromTo actionWithDuration:0.5
            from:progress.percentage to:100];
        // 當資源全部加載完畢時調用loadingComplete方法
        CCCallBlock *callback = [CCCallBlock actionWithBlock:^() {
            [self loadingComplete];
        }];
        // CCSequence組合動作
        id action = [CCSequence actions:ac.callback.nil];
        // 進度條執行動作
        [progress runAction:action];
    }
}
// 延遲2秒之後運行一個場景切換特效跳轉到遊戲主場景,即HelloWorldLayer
- (void) loadingComplete{
    CCDelayTime *delay = [CCDelayTime actionWithDuration:2.0f];
    CCCallBlock *callblock = [CCCallBlock actionWithBlock:^(void) {
        [[CCDirector sharedDirector] replaceScene:
        [CCTransitionFade transitionWithDuration:1.0f scene:[HelloWorldLayer scene]]];
    }];
    CCSequence *sequence = [CCSequence actions:delay.callblock.nil];
    [self runAction:sequence];
}
@end

下面依次解釋以上代碼中的每一個方法。

+(CCScene *) scene方法很簡單,和前面的一樣,首先創建了一個scene場景,然後創建了一個PreloadLayer層,將PreloadLayer層作爲scene場景的子節點,最後返回scene場景。

init方法首先獲取屏幕窗口大小,然後創建了一個進度條。這裏使用progressbar.png圖片初始化一個精靈,再通過該精靈初始化一個CCProgressTimer對象,設置setPercentage屬性爲0,表示當前未加載任何資源,表現在屏幕上就是什麼也看不見。由於圖片大小關係,把scale設置成0.5,即縮小一半。

接下來設置CCProgressTimer對象最重要的3個參數。

qmidpoint:表示進度條動畫的起始位置,默認在圖片的中點,如果想要顯示從左到右的一個動畫效果,則必須改成(0,y)

qbarChangeRate:表示是否改變水平或者垂直方向的比例,設置成1表示改變,0表示不改變。本例製作一個從左至右的水平進度條,所以midpoint應該是(0,0.5)。因爲x方向需要改變,而y方向不需要改變,所以設置barChangeRateccp(1,0)

qtype:設置爲kCCProgressTimerTypeBar,表示條形進度條。

關於CCProgressTimer類的使用可以參考官方文檔,讀者也可以找到cocos2d的示例項目cocos2d-tests-ios.xcodeproj,並運行ActionProgressTest這個TARGET。感興趣的讀者也可以仔細分析該項目中的ActionProgressTest.m源文件(位於項目的tests目錄下)來掌握不同progress的用法示例。

最後設置CCProgressTimer對象的位置,並添加爲當前層的子節點。

onEnterTransitionDidFinish方法加載配置文件preloadResources.plist,讀取配置文件中的遊戲資源名稱列表並存儲在不同的數組中。首先使用CCFileUtil獲得plist文件的具體路徑,調用NSDictionarydictionaryWithContentsOfFile方法把該文件轉換成一個字典對象。然後通過字典的key值取出不同類型資源的數組,調用每個數組的count方法累加得到總共需要加載的資源總數量,使用100除以資源總數量獲得進度條需要更新次數用於之後計算進度條顯示的百分比。最後將數組作爲參數調用performSelectorOnMainThread: withObject: waitUntilDone:方法在主線程中依次加載每種類型的遊戲資源,將waitUntilDone的值設置爲“YES”能保證所有的資源按照序列依次加載。

loadMusics:loadSounds:方法比較簡單,通過循環遍歷數組,預加載背景音樂和音效,加載完後調用progressUpdate方法更新進度條。

這裏需要注意的是loadSpriteSheets:方法,該方法循環遍歷數組,數組的每個元素是一個plist文件名稱,調用CCSpriteFrameCacheaddSpriteFramesWithFile時,該方法會加載與該plist文件名稱相同但後綴爲.png的紋理圖片(本例中airfightSheet.plist對應airfightSheet.png),把該plist的所有spriteFrame信息讀取出來,之後在項目當中就可以通過spriteFrameWithName獲取相應的精靈幀了。

progressUpdate方法比較簡單,每次被調用時自減更新資源總數變量,修改進度條的百分比。當資源全部加載完畢時調用loadingComplete方法。

loadingComplete方法被調用說明資源加載完畢,延遲2秒後運行一個場景切換特效跳轉到遊戲主場景HelloWorldLayer

編譯並運行遊戲,選擇“開始遊戲”菜單項,模擬器首先會顯示一個進度條,進度條全部顯示完畢切換到HelloWorldLayer顯示經典的Hello World畫面。恭喜你!資源文件加載成功,進度條功能實現。運行時模擬器顯示效果如圖13.60所示。

100325_oZSM_262659.jpg
   ————本文節選自《瘋狂ios講義(下)》   100627_lvjp_262659.jpg


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章