因為在這個炸彈人游戲中有很多不同的關卡,難度依次上升,所以對於每個關卡的數據我們必須存放在某個地方,有很多種保存方法,這裡我們選擇使用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的實現代碼,首先是類單例方法的實現:
//返回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中,確保數據不會丟失.
游戲數據類是每個游戲都必不可少的功能類,可以考慮將其做成一個模板類來供不同程序的使用.