(NO.00005)iOS實現炸彈人遊戲(七):遊戲資料序列化表示介紹
用plist列表檔案來表示遊戲資料
因為在這個炸彈人遊戲中有很多不同的關卡,難度依次上升,所以對於每個關卡的資料我們必須存放在某個地方,有很多種儲存方法,這裡我們選擇使用plist列表檔案來儲存每個關卡的資料.
選擇Resources目錄,在其中建立一個plist檔案,命名為LevelsData.plist.
下面我們要想一想裡面到底要存放神馬資料.
大致有這些每一關卡磚塊的數量,每關敵人的數量,每關剩餘的時間限制和過關獎勵的分數.
其中關卡敵人的數量需要在細化下,因為我們在遊戲開始的一個目標就是建立多種敵人,所以這裡要按每種敵人給出一個對應的數量.
按照上述所討論的內容,最終建立的plist內容大致是如下這個樣子:
遊戲資料的記憶體表示
有了plist檔案還不夠,我們還需要將plist的內容讀取到記憶體中去,這是以類執行個體的方式來讀取的.
我們在Xcode中建立一個GameData類,繼承於NSObject.
開啟GameData.h標頭檔,設定如下:
#import //管理遊戲資料的類@interface GameData : NSObject+(id)sharedInstance;@property (nonatomic,assign) NSInteger bombExplodeRange; //炸彈爆炸範圍@property (nonatomic,assign) BOOL isManualExplode; //是否手動引爆@property (nonatomic,assign) BOOL isFearBomb; //玩家是否怕炸彈@property (nonatomic,assign) NSInteger bombCountLimit; //炸彈的數量限制@property (nonatomic,assign) NSInteger life; //玩家的命數@property (nonatomic,assign) BOOL isPlayerSpeedUp; //玩家是否處於加速狀態@property (nonatomic,assign) BOOL canPlayerAcrossBrick; //玩家是否可以穿磚@property (nonatomic,assign) BOOL canPlayerAcorssBomb; //玩家是否可以穿炸彈@property (nonatomic,assign) NSInteger playerTotalScore; //玩家總得分@property (nonatomic,assign) NSInteger curLevelNumber; //當前關卡序號@property (nonatomic,assign) NSInteger curLevelBrickCount; //當前關卡磚塊數量//@property (nonatomic,assign) NSInteger curLevelEnemyCount; //當前關卡敵人數量@property (nonatomic,assign) NSInteger curLevelFSCount; //當前關卡普通敵人的數量@property (nonatomic,assign) NSInteger curLevelFSGhostCount; //當前關卡FSGhost敵人的數量@property (nonatomic,assign) NSInteger curLevelFSDogCount; //當前關卡FSDog敵人的數量@property (nonatomic,assign) NSInteger curLevelFSCatTracerCount; //當前關卡FSCatTracer敵人的數量@property (nonatomic,assign) NSInteger curLevelGPCount; //當前關卡遊戲道具數量@property (nonatomic,assign) NSInteger curLevelLeftTime; //當前關卡時間限制(秒)@property (nonatomic,assign) NSInteger curLevelPassScore; //當前關卡過關得分-(void)synchronize;-(void)saveGameData;-(void)loadGameData;-(void)initGameData;-(void)setGameDataWhenLevelLose;//註冊預設遊戲資料,如果App第一次運行則使用該資料.(因為你還未存入資料)-(void)regDefaultGameData;@end
裡面定義了若干屬性,分為兩部分內容:和當前關卡相關的以及和遊戲主角狀態相關的內容,大家從屬性的名稱中大致可以區分出來,這裡就不一一介紹了,注釋都做的很詳細.
GameData類中定義的方法並不多,一個類方法sharedInstance用來返回類的唯一執行個體,剩下的都是執行個體方法用來讀取和儲存遊戲資料.
GameData類的實現
接下來我們來看一下GameData的實現代碼,首先是類單例方法的實現:
//返回GameDate類唯一單例+(instancetype)sharedInstance{ static dispatch_once_t once; static GameData *sharedInstance; dispatch_once(&once,^{ sharedInstance = [self new]; }); return sharedInstance;}
內容沒啥好說的,然後是另一個簡單的同步方法:
//將NSUserDefaults資料寫入磁碟-(void)synchronize{ [[NSUserDefaults standardUserDefaults]synchronize];}
下面是讀取資料的loadGameData方法:
//從磁碟上將遊戲資料讀取出來-(void)loadGameData{ NSDictionary *dict = [[NSUserDefaults standardUserDefaults] objectForKey:kPlayerData]; self.bombExplodeRange = [dict[kBombExplodeRange] intValue]; self.isManualExplode = [dict[kIsManualExplode] boolValue]; self.isFearBomb = [dict[kIsFearBomb] boolValue]; self.bombCountLimit = [dict[kBombCountLimit] intValue]; self.life = [dict[kLife] intValue]; self.isPlayerSpeedUp = [dict[kIsPlayerSpeedUp] boolValue]; self.canPlayerAcrossBrick = [dict[kCanPlayerAcrossBrick] boolValue]; self.canPlayerAcorssBomb = [dict[kCanPlayerAcrossBomb] boolValue]; self.playerTotalScore = [dict[kPlayerTotalScore] intValue]; self.curLevelNumber = [dict[kCurLevelNumber] intValue]; //取得關卡資料檔案的全路徑 NSString *plistFullPath = [[NSBundle mainBundle] pathForResource:s_LevelsDataFile ofType:@"plist"]; //讀取關卡資料到數組中 NSArray *levelsDataAry = [NSArray arrayWithContentsOfFile:plistFullPath]; NSAssert(self.curLevelNumber > 0 && self.curLevelNumber <= levelsDataAry.count, @"Error curLevel Number!"); //關卡是從1開頭,所以要調整為數組中的從0開頭. NSInteger index = self.curLevelNumber - 1; //依次取得關卡中的每個資料 self.curLevelBrickCount = [levelsDataAry[index][kCurLevelBrickCount] intValue]; [self initCurLevelEmenyCount:levelsDataAry[index][kCurLevelEnemyCount]]; self.curLevelGPCount = [levelsDataAry[index][kCurLevelGPCount] intValue]; self.curLevelLeftTime = [levelsDataAry[index][kCurLevelLeftTime] intValue]; self.curLevelPassScore = [levelsDataAry[index][kCurLevelPassScore] intValue];}
代碼很簡單,就是依次分別讀取level和player的資料然後設定對應的執行個體變數.
最後是寫入資料的saveGameData方法:
//將遊戲資料寫入磁碟-(void)saveGameData{ //建立資料字典 NSDictionary *dict = @{kBombExplodeRange:@(self.bombExplodeRange), kIsManualExplode:@(self.isManualExplode), kIsFearBomb:@(self.isFearBomb), kBombCountLimit:@(self.bombCountLimit), kLife:@(self.life), kIsPlayerSpeedUp:@(self.isPlayerSpeedUp), kCanPlayerAcrossBrick:@(self.canPlayerAcrossBrick), kCanPlayerAcrossBomb:@(self.canPlayerAcorssBomb), kPlayerTotalScore:@(self.playerTotalScore), kCurLevelNumber:@(self.curLevelNumber) }; //將資料字典寫入NSUserDefaults執行個體 [[NSUserDefaults standardUserDefaults] setObject:dict forKey:kPlayerData]; [self synchronize];}
該方法是讀取方法的逆方法,最後調用了[self synchronize]來將記憶體中的資料刷入plist中,確保資料不會丟失.
遊戲資料類是每個遊戲都必不可少的功能類,可以考慮將其做成一個模板類來供不同程式的使用.