(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 ;)
(NO.00005)iOS实现炸弹人游戏(七):游戏数据的序列化表示的更多相关文章
- (NO.00005)iOS实现炸弹人游戏(八):游戏主角(一)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 最近一直在做另一个RPG游戏,所以本系列迟迟没有更新,上一篇博 ...
- (NO.00005)iOS实现炸弹人游戏(三):从主场景类谈起
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我又粗粗看了下整个项目的代码,比较多: 不少类都与其他类有着千丝 ...
- (NO.00005)iOS实现炸弹人游戏(十一):怪物之火精灵
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 从本篇开始我们一次介绍一下游戏中敌人的制作过程.看过第一篇的小 ...
- (NO.00005)iOS实现炸弹人游戏(五):游戏数据的初始化(二)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们现在来依次看一下上篇中提到的各个方法,首先介绍的是updat ...
- (NO.00005)iOS实现炸弹人游戏(四):游戏数据的初始化(一)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 上一篇我们初步看了一下MainScene类的初始化方法里都做了神 ...
- (NO.00005)iOS实现炸弹人游戏(二):素材选择的取舍
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 前面一篇里我们基本明确了游戏的大致玩法和特点.下面就游戏中会用到 ...
- (NO.00005)iOS实现炸弹人游戏(一):游戏的整体规划设计
在这新的系列中,我们来尝试完成一款经典的游戏:炸弹人 这是以前红白机上的炸弹人,由于游戏可玩性强,玩法又简单,在后面的机型上陆续推出了很多款续作. 在随后的触屏设备上也出现了炸弹人的模拟版,用的是模拟 ...
- (NO.00005)iOS实现炸弹人游戏(十):游戏主角(三)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 下面我们来看游戏主角类里面几个播放特殊动画的方法,首先从run ...
- (NO.00005)iOS实现炸弹人游戏(九):游戏主角(二)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 上篇介绍了游戏主角的初始化方法,下面我们一次来实现主角的其他方 ...
随机推荐
- VS2017+xamain开发安卓(Addroid)应用
Visual Studio 2017下载地址: https://www.visualstudio.com/zh-hans/ 安卓模拟器官网下载: https://www.visualstudio.c ...
- Linux文件系统的介绍
1.Linux的文件系统是一个典型的树形结构,只有一个根节点 如下图: 2.在Linux中一切皆文件 Linux 对数据文件(.mp3..bmp),程序文件(.c..h.*.o),设备文件(LCD.触 ...
- SpringMVC 处理映射
一.Spring MVC控制器名称处理映射 以下示例展示如何利用Spring MVC 框架使用控制器名称处理程序映射. ControllerClassNameHandlerMapping类是基于约定的 ...
- C语言程序设计第四次作业-选择结构
(一)改错题 输出三角形的面积和周长,输入三角形的三条边a.b.c,如果能构成一个三角形,输出面积area和周长perimeter(保留2位小数):否则,输出"These sides do ...
- html5应用程序缓存
缓存概念: ------页面缓存: html.JS.CSS等,这些缓存资源是由于浏览器的行为而产生; ------数据缓存 ----------AppCache: Cache Manifest 操作 ...
- ES6(数组)
ES6数组新增特性 1. 空数组 2.将伪数组转换成真正的数组 将 p 标签集合转换成真正数组 类似于map的用法,转换数组同时还在遍历. 3.填充数组(将所有数组换成一个值) 1代表起始位置,3代表 ...
- JVM中判断对象是否存活的方法
Java中几乎所有的对象实例都存放在堆中,在垃圾收集器对堆内存进行回收前,第一件事情就是要确定哪些对象还“存活”,哪些对象已经“死去”(即不可能再通过任何途径被使用). 引用计数算法 首先需要声明,至 ...
- promise应用及原生实现promise模型
一.先看一个应用场景 发送一个请求获得用户id, 然后根据所获得的用户id去执行另外处理.当然这里我们完全可以使用回调,即在请求成功之后执行callback; 但是如果又添加需求呢?比如获得用户id之 ...
- H5canvas基础
本篇文章开始讲解HTML5的核心功能之一:Canvas 通过Canvas可以动态生成和展示图形.图表.图像以及动画. Canvas API功能非常多,我们将讨论最常用的功能. 我们先新建一个canva ...
- d4d#9 玩Docker只要浏览器就够了,PWD是个神奇的网站
本文是d4d系列的第9篇,在这一篇中给大家介绍一个学习Docker最为快捷高效的方式,你不需要自己搭建环境,也不用担心把自己的开发环境搞乱,你需要的只是一个浏览器,就可以立即开始学习Docker的常用 ...