(NO.00005)iOS實現炸彈人游戲(七):游戲數據的序列化表示


大熊貓豬·侯佩原創或翻譯作品.歡迎轉載,轉載請注明出處.
如果覺得寫的不好請告訴我,如果覺得不錯請多多支持點贊.謝謝! hopy ;)


用plist列表文件來表示游戲數據

因為在這個炸彈人游戲中有很多不同的關卡,難度依次上升,所以對於每個關卡的數據我們必須存放在某個地方,有很多種保存方法,這里我們選擇使用plist列表文件來保存每個關卡的數據.

選擇Resources目錄,在其中新建一個plist文件,命名為LevelsData.plist.

下面我們要想一想里面到底要存放神馬數據.

大致有這些每一關卡磚塊的數量,每關敵人的數量,每關剩余的時間限制和過關獎勵的分數.

其中關卡敵人的數量需要在細化下,因為我們在游戲開始的一個目標就是建立多種敵人,所以這里要按每種敵人給出一個對應的數量.

按照上述所討論的內容,最終建立的plist內容大致是如下這個樣子:

這里寫圖片描述

游戲數據的內存表示

有了plist文件還不夠,我們還需要將plist的內容讀取到內存中去,這是以類實例的方式來讀取的.

我們在Xcode中新建一個GameData類,繼承於NSObject.

打開GameData.h頭文件,設置如下:

#import <Foundation/Foundation.h>
//管理游戲數據的類
@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中,確保數據不會丟失.

游戲數據類是每個游戲都必不可少的功能類,可以考慮將其做成一個模板類來供不同程序的使用.

下一篇我們繼續介紹游戲的其它部分,see you ;)


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com